首页 > 代码库 > ajax 访问--提高安全性
ajax 访问--提高安全性
首先受到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 datahttp://www.mamicode.com/=="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: 个人见解,有不足之处,可以提出来大家参考
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。