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 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 访问--提高安全性的更多相关文章
- 提高安全性而在HTTP响应头中可以使用的各种响应头字段
本文介绍在Web服务器做出响应时,为了提高安全性而在HTTP响应头中可以使用的各种响应头字段.由于部分浏览器中有可能对某些字段或选项不提供支持,所以在使用这些字段时请先确认客户端环境. X-Frame ...
- ie8用ajax访问不能每次都刷新的问题
最近发现,用ajax访问后台,用ie8访问,第一次可以正常返回值,后面就一直不会执行后台,总是返回第一次访问的结果. 用ie9,ie10等都没问题,chrome,等浏览器也没有问题. 测试后发现,是i ...
- WebForm.aspx 页面通过 AJAX 访问WebForm.aspx.cs类中的方法,获取数据
WebForm.aspx 页面通过 AJAX 访问WebForm.aspx.cs类中的方法,获取数据 WebForm1.aspx 页面 (原生AJAX请求,写法一) <%@ Page Langu ...
- 通过ajax访问Tomcat服务器web service接口时出现No 'Access-Control-Allow-Origin' header问题的解决办法
问题描述 通过ajax访问Web服务器(Tomcat7.0.42)中的json web service接口的时候,报以下跨域问题: XMLHttpRequest cannot load http:// ...
- 【spring 后台跳转前台】使用ajax访问的后台,后台正常执行,返回数据,但是不能进入前台的ajax回调函数中
问题: 使用ajax访问的后台,后台正常执行,并且正常返回数据,但是不能进入前台的ajax回调函数中 问题展示: 问题解决: 最后发现是因为后台的方法并未加注解:@ResponseBody,导致方法 ...
- 通过ajax访问aspx的CodeBehind中的方法
引言 在项目中突然看到,aspx中的ajax可以访问aspx.cs中的方法,觉得很新奇,也许是lz少见多怪,不过,真的有发现新大陆似的那种兴奋,你也许知道这代表什么,学会了这种方式,代表你以后,可以建 ...
- jquery ajax 访问webServer的xml文件
最近项目中要使用到通过ajax访问webServer的xml文件,通过下面的方式可以直接访问webServer的xml文件,不需要在web.xml中进行任何配置.它的返回参数就是服务器上的xml文件. ...
- WebForm.aspx 页面通过 AJAX 访问WebForm.aspx.cs类中的方法,获取数据(转)
WebForm.aspx 页面通过 AJAX 访问WebForm.aspx.cs类中的方法,获取数据 WebForm1.aspx 页面 (原生AJAX请求,写法一) <%@ Page Langu ...
- 微信公众平台宣布增加接口IP白名单提高安全性
微信公众平台目前已经发布通知在平台接口调用上为了提高安全性需要添加IP白名单并仅允许白名单IP调用. 目前微信公众平台面向开发者主要提供的开发者ID和开发者密钥,在调用时ID和密钥通过检验即可进行调用 ...
随机推荐
- 解决:并排的两个div底部对齐
我希望在页面上画2个栈,并列起来,并且其内容是动态的,高度.宽度都可变,但是要保持底部对齐,如图: 实现的代码如下: <html> <head> <meta http-e ...
- Zn离子参数
Generating Topology and Coordinates Files Using xLeap (AmberTools V1.5) Parameter and example files: ...
- onTouch与onClick事件的关系
这几天遇到点关于Android的触摸事件相关的,还跟onClick有关,暂且记下: LinearLayout分别设置了onTouchListener,onClickListener,onLongCli ...
- AE开发 入门教程
此过程说明适合那些使用.NET建立和部署应用的开发者,它描述了使用ArcGIS控件建立和部署应用的方法和步骤. 你可以在下面的目录下找到相应的样例程序: <安装目录>/DeveloperK ...
- 南阳理工ACM Skiing问题
描述 Michael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激.可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你.Michael想知道载一个区域中最长底 ...
- poj-3616 Milking Time (区间dp)
http://poj.org/problem?id=3616 bessie是一头工作很努力的奶牛,她很关心自己的产奶量,所以在她安排接下来的n个小时以尽可能提高自己的产奶量. 现在有m个产奶时间,每个 ...
- Android 内存相关 onTrimMemory,onLowMemory,MemoryInfo()
参考: Android Application生命周期学习 Android中如何查看内存(上) Android OnLowMemory和OnTrimMemory OnLowMemory OnLowMe ...
- java之并发
一.线程 在java中多线程执行任务,主要有两种方式,一种是通过继承Thread类,重写run方法,优点是比较方便的创建一个线程,缺点是java中每个类只能有一个基类,所有继承了T火热ad类后,就不能 ...
- java double保留小数点的零的问题,java保留小数点问题
1.用DecimalFormat格式化,DecimalFormat df=new DecimalFormat("0.00"); System.out.println(df.form ...
- 在单机Hadoop上面增加Slave
之前的文章已经介绍了搭建单机Hadoop, HBase, Hive, Spark的方式:link 现在希望在单机的基础上,加一个slave. 首先需要加上信任关系,加信任关系的方式,见前一篇文章:li ...