首先受到struts token的启发,产生了客户端发起的ajax请求进行验证的想法,大致思路是客户端每次请求产生一个key ,然后服务端接收到key,然后解析,判断是否为合法key, 对于不带key 或者验证失败的直接拦截下来,从而减轻服务器的压力,好了废话不多说,上代码

首先我使用的是struts2的拦截器,(ps:不知道的度娘告诉你)

继承 AbstractInterceptor 实现init()和 intercept() ,从字面意思上去理解这两个方法 初始化 和拦截

第一个方法 就是从配置文件读取配置信息,没什么特别的

第二个方法 主要是分为两部分验证key 我这里 分 ajax 访问和普通方法 看代码

public String intercept(ActionInvocation invocation) throws Exception {
String rs = null;
if (isTokenInterceptor) {
boolean flag = false;
String msg = "{_success : false,_operationMsg:'非正常访问,属于非法客户端!'}";
ActionContext ac = invocation.getInvocationContext();
HttpServletRequest request = (HttpServletRequest) ac.get("com.opensymphony.xwork2.dispatcher.HttpServletRequest");
if (PublicUtil.isNotEmpty(freeURL)) {
String urlValue[] = freeURL.split(",");
if (PublicUtil.isNotEmpty(urlValue)) {
String as[];
int j = (as = urlValue).length;
for (int i = 0; i < j; i++) {
String url = as[i];
if (request.getRequestURI().indexOf(url) != -1) {
flag = true;
break;
}
}
}
}
if(!flag){
HttpSession session = request.getSession();
String requestToken;
HttpServletResponse response;
try {
response = (HttpServletResponse) ac.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse");
String requestType = request.getHeader("X-Requested-With");
if("XMLHttpRequest".equals(requestType)){ //验证是否为ajax 请求
requestToken = request.getHeader(TOKEN_NAME);
if(PublicUtil.isNotEmpty(requestToken) && requestToken.indexOf("||")!=-1){
String token = (String) session.getAttribute(SESSION_TOKEN);
if (!requestToken.equals(token)) {
flag = true;
} else {
logger.warn(PublicUtil.toAppendStr(
"客户端表单防重复验证生效:客户端多次提交 requestToken:",
requestToken));
msg = "{_success : false,_operationMsg : '对不起,网络异常,请重新提交尝试!'}";
}
session.setAttribute(SESSION_TOKEN, requestToken);
}
}else{ //普通请求 通过读取cookie 来验证
requestToken = CookieUtil.getCookie(request, TOKEN_NAME);
if(PublicUtil.isEmpty(requestToken)){
requestToken = DesUtil.getRequestKey();
}
if(PublicUtil.match("^[0-9]{8}$", DesUtil.strDec(requestToken))){
String token = (String) session.getAttribute(COOKIE_TOKEN);
if(PublicUtil.isEmpty(token)){
token = requestToken;
}
if (requestToken.equals(token)) {
flag = true;
} else {
logger.warn(PublicUtil.toAppendStr(
"客户端表单防重复验证生效:客户端多次提交 requestToken:",
requestToken, " url:", request.getRequestURI()));
msg = "{_success : false,_operationMsg : '对不起,网络异常,请重新提交尝试!'}";
}
}
String nextToken = DesUtil.getRequestKey();
CookieUtil.setCookie(response, TOKEN_NAME, nextToken);
session.setAttribute(COOKIE_TOKEN, nextToken);
flag = true;
}
} catch (IllegalStateException e) {
flag = false;
msg = PublicUtil.toAppendStr(
"{_success : false,_operationMsg : 'Error creating HttpSession due response is commited to client. You can use the CreateSessionInterceptor or create the HttpSession from your action before the result is rendered to the client: ",
e.getMessage(), "'}");
e.printStackTrace();
}
}
if (flag) {
rs = invocation.invoke();
} else {
HttpServletResponse response = (HttpServletResponse) ac
.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse");
response.setCharacterEncoding("UTF-8");
response.getWriter().write(msg);
}
} else {
rs = invocation.invoke();
}
return rs;
}

前台, 对于ajax 提交,我采用的header 夹带验证key的方式进行传递, 因为项目中使用的jquery 所以 我直接重写 $.ajax 方法就搞定了

var TOKEN_NAME = "Albedo-Requst-Token";
(function($){
//备份jquery的ajax方法
var _ajax=$.ajax; //重写jquery的ajax方法
$.ajax=function(opt){
//备份opt中error和success方法
var fn = {
error:function(XMLHttpRequest, textStatus, errorThrown){},
success:function(data, textStatus){}
}
if(opt.error){
fn.error=opt.error;
}
if(opt.success){
fn.success=opt.success;
} //扩展增强处理
var _opt = $.extend(opt,{
beforeSend: function(request) {
request.setRequestHeader("Albedo-Requst-Token", getRequestKey()+"||"+opt.url); //产生一个时间不同时的唯一key 特别注意 时间不同,如果时间相同,可以应该一样
},
error:function(XMLHttpRequest, textStatus, errorThrown){
//错误方法增强处理
fn.error(XMLHttpRequest, textStatus, errorThrown);
},
success:function(data, textStatus){
//成功回调方法增强处理
if(typeof data=="string"){ //对于被拦截下来的请求统一做提示
try{
eval("var rs = " + data);
if(rs && rs._success == false && rs._operationMsg){
if(!g_showTip) alert(rs._operationMsg);
else setTimeout(function(){g_showTip(rs._operationMsg);},500);
}
}catch(e){}
}
fn.success(data, textStatus);
}
});
_ajax(_opt);
};
})(jQuery);

当然,没有用这个的,也不要跪,至少还有?后面传参也是可以搞定的 ^_^,

这样之后就搞定了,如果一个页面连续对一个地址发起几次请求,那么这样之后只会有第一个请求成功,之后的请求全部会被拦截下来

ps: 个人见解,有不足之处,可以提出来大家参考

ajax 访问--提高安全性的更多相关文章

  1. 提高安全性而在HTTP响应头中可以使用的各种响应头字段

    本文介绍在Web服务器做出响应时,为了提高安全性而在HTTP响应头中可以使用的各种响应头字段.由于部分浏览器中有可能对某些字段或选项不提供支持,所以在使用这些字段时请先确认客户端环境. X-Frame ...

  2. ie8用ajax访问不能每次都刷新的问题

    最近发现,用ajax访问后台,用ie8访问,第一次可以正常返回值,后面就一直不会执行后台,总是返回第一次访问的结果. 用ie9,ie10等都没问题,chrome,等浏览器也没有问题. 测试后发现,是i ...

  3. WebForm.aspx 页面通过 AJAX 访问WebForm.aspx.cs类中的方法,获取数据

    WebForm.aspx 页面通过 AJAX 访问WebForm.aspx.cs类中的方法,获取数据 WebForm1.aspx 页面 (原生AJAX请求,写法一) <%@ Page Langu ...

  4. 通过ajax访问Tomcat服务器web service接口时出现No 'Access-Control-Allow-Origin' header问题的解决办法

    问题描述 通过ajax访问Web服务器(Tomcat7.0.42)中的json web service接口的时候,报以下跨域问题: XMLHttpRequest cannot load http:// ...

  5. 【spring 后台跳转前台】使用ajax访问的后台,后台正常执行,返回数据,但是不能进入前台的ajax回调函数中

    问题: 使用ajax访问的后台,后台正常执行,并且正常返回数据,但是不能进入前台的ajax回调函数中 问题展示:  问题解决: 最后发现是因为后台的方法并未加注解:@ResponseBody,导致方法 ...

  6. 通过ajax访问aspx的CodeBehind中的方法

    引言 在项目中突然看到,aspx中的ajax可以访问aspx.cs中的方法,觉得很新奇,也许是lz少见多怪,不过,真的有发现新大陆似的那种兴奋,你也许知道这代表什么,学会了这种方式,代表你以后,可以建 ...

  7. jquery ajax 访问webServer的xml文件

    最近项目中要使用到通过ajax访问webServer的xml文件,通过下面的方式可以直接访问webServer的xml文件,不需要在web.xml中进行任何配置.它的返回参数就是服务器上的xml文件. ...

  8. WebForm.aspx 页面通过 AJAX 访问WebForm.aspx.cs类中的方法,获取数据(转)

    WebForm.aspx 页面通过 AJAX 访问WebForm.aspx.cs类中的方法,获取数据 WebForm1.aspx 页面 (原生AJAX请求,写法一) <%@ Page Langu ...

  9. 微信公众平台宣布增加接口IP白名单提高安全性

    微信公众平台目前已经发布通知在平台接口调用上为了提高安全性需要添加IP白名单并仅允许白名单IP调用. 目前微信公众平台面向开发者主要提供的开发者ID和开发者密钥,在调用时ID和密钥通过检验即可进行调用 ...

随机推荐

  1. Case 架构的实际应用-1

    We use testlink to manage cases, and the frame is below: Project Name -All Features(Modules) -Featur ...

  2. git checkout not discard changes

    1. checkout one branch, show status user@vbox:/mnt/tmp$ git checkout masterSwitched to branch 'maste ...

  3. SQLServer2008 行转列3

    with a as ( select 日期,学号,名字, '语文' as 科目,语文 as 分数 from tsco union all select 日期,学号,名字, '数学' as 科目,数学 ...

  4. HDU 1941 Hide and Seek(离散化+树状数组)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1941 题意:给出平面上n个点,找出一点p,使得距离p最近和最远的点的距离之差最小.输出这 ...

  5. EditText控件实现只读

      android的EditText控件实现只读只需设置三个方法: editText.setCursorVisible(false);//隐藏光标 editText.setFocusable(fals ...

  6. HDU 1024 (不重叠m段最大和) Max Sum Plus Plus

    题解是看的这里的: http://www.acmerblog.com/hdu-1024-Max-Sum-Plus-Plus-1276.html 当前这个状态是dp[i][j],i 表示当前的段,j表示 ...

  7. Asp.Net验证码3

    using System; using System.Collections.Generic; using System.Web; using System.Web.UI; using System. ...

  8. Asp.Net验证码1

    验证码html调用 验证码:<input name="> <img src="CodeHandler.ashx" id="imgCode&qu ...

  9. HDU 4741

    获得 新的模板了/// 此模板 有线段和线段的最短距离方法,同时包含线段与线段的最短距离:#include<iostream> #include<stdio.h> #inclu ...

  10. LOL-无双剑姬我的最爱

    LOL打了几年了,是一种娱乐的好方式,但是一个人玩不开黑就很无聊.这游戏最开始我玩的时候无论是赢是输就无所谓的,很高兴的.但是现在输了反而很气愤.也不知道为什么,所以很少玩了. 剑姬对反甲:如果对方出 ...