CSRF 
CSRF(Cross-site request forgery跨站请求伪造,也被称为“One Click Attack”或者Session Riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。尽管听起来像跨站脚本(XSS),但它与XSS非常不同,并且攻击方式几乎相左。XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。与XSS攻击相比,CSRF攻击往往不大流行(因此对其进行防范的资源也相当稀少)和难以防范,所以被认为比XSS更具危险性。

攻击示例 
如:一个网站用户Bob可能正在浏览聊天论坛,而同时另一个用户Alice也在此论坛中,并且后者刚刚发布了一个具有Bob银行链接的图片消息。设想一下,Alice编写了一个在Bob的银行站点上进行取款的form提交的链接,并将此链接作为图片src。如果Bob的银行在cookie中保存他的授权信息,并且此cookie没有过期,那么当Bob的浏览器尝试装载图片时将提交这个取款form和他的cookie,这样在没经Bob同意的情况下便授权了这次事务。 
CSRF是一种依赖web浏览器的、被混淆过的代理人攻击(deputy attack)。在上面银行示例中的代理人是Bob的web浏览器,它被混淆后误将Bob的授权直接交给了Alice使用。 
下面是CSRF的常见特性: 
依靠用户标识危害网站 
利用网站对用户标识的信任 
欺骗用户的浏览器发送HTTP请求给目标站点 
另外可以通过IMG标签会触发一个GET请求,可以利用它来实现CSRF攻击。

spring mvc 框架下防御策略

思路概要: 
1.初始化页面时在token隐藏域。 
2.表单提交后带入token到后台,验证token,如成功继续操否为受到攻击。 
3.操作完之后重新生成token到页面隐藏域。 
代码示例: 
创建拦截器:

/**
* <一句话功能简述>
* <功能详细描述>
* 防止跨站请求伪造拦截器
* 为每个返回的页面添加CSRFToken参数
* @author Tangguilin
* @version [版本号, 2016年3月26日]
*/
public class AvoidCSRFInterceptor extends HandlerInterceptorAdapter
{
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception
{
String url = request.getRequestURI();
if (!url.endsWith(".do"))
{
return true;
}
HandlerMethod handlerMethod = (HandlerMethod)handler;
Method method = handlerMethod.getMethod();
VerifyCSRFToken annotation = method.getAnnotation(VerifyCSRFToken.class);
if (annotation != null)
{
String xrq = request.getHeader("X-Requested-With");//是否为Ajax标志
//非法的跨站请求校验
if (annotation.verifyCSRFToken() && !verifyCSRFToken(request))
{
if (StringUtil.isEmpty(xrq))
{
//form表单提交,url get方式,刷新csrftoken并跳转提示页面
request.getSession(false).setAttribute("CSRFToken",
TokenProcessor.getInstance().generateToken(request));
response.setContentType("application/json;charset=UTF-8");
PrintWriter out = response.getWriter();
out.print("非法请求");
response.flushBuffer();
return false;
}
else
{
//刷新CSRFToken,返回错误码,用于ajax处理,可自定义
BaseDataResp baseResp = new BaseDataResp();
String csrftoken = TokenProcessor.getInstance().generateToken(request);
request.getSession(false).setAttribute("CSRFToken", csrftoken);
baseResp.setCode(IDiMengResultCode.SystemManager.CSRF);
response.setContentType("application/json;charset=UTF-8");
PrintWriter out = response.getWriter();
out.print(baseResp.toString());
response.flushBuffer();
return false;
}
} }
return true;
} @Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView)
throws Exception
{ String url = request.getRequestURI();
if (!url.endsWith(".do"))
{
return;
} //第一次生成token
if (modelAndView != null)
{
if (request.getSession(false) == null
|| StringUtil.isEmpty((String)request.getSession(false).getAttribute("CSRFToken")))
{
request.getSession(false).setAttribute("CSRFToken",
TokenProcessor.getInstance().generateToken(request));
return;
}
}
//刷新token
HandlerMethod handlerMethod = (HandlerMethod)handler;
Method method = handlerMethod.getMethod();
RefreshCSRFToken refreshAnnotation = method.getAnnotation(RefreshCSRFToken.class);
String xrq = request.getHeader("X-Requested-With");//是否为Ajax标志
if (refreshAnnotation != null && refreshAnnotation.refreshCSRFToken() && StringUtil.isEmpty(xrq))
{
request.getSession(false).setAttribute("CSRFToken", TokenProcessor.getInstance().generateToken(request));
return;
}
VerifyCSRFToken verifyAnnotation = method.getAnnotation(VerifyCSRFToken.class);
if (verifyAnnotation != null)
{
//成功后刷新token
if (verifyAnnotation.verifyCSRFToken())
{
if (StringUtil.isEmpty(xrq))
{
request.getSession(false).setAttribute("CSRFToken",
TokenProcessor.getInstance().generateToken(request));
}
else
{
Map<String, String> map = new HashMap<String, String>();
map.put("CSRFToken", TokenProcessor.getInstance().generateToken(request));
response.setContentType("application/json;charset=UTF-8");
OutputStream out = response.getOutputStream();
out.write((",'csrf':" + JSONObject.toJSONString(map) + "}").getBytes("UTF-8"));
}
}
}
} /** <一句话功能简述>
* 处理跨站请求伪造
* 针对需要登录后才能处理的请求,验证CSRFToken校验
* @author tangguilin
* @param request
*/
protected boolean verifyCSRFToken(HttpServletRequest request)
{
String requstCSRFToken = request.getHeader("CSRFToken");//请求中的CSRFToken
if (StringUtil.isEmpty(requstCSRFToken))
{
return false;
}
String sessionCSRFToken = (String)request.getSession().getAttribute("CSRFToken");
if (StringUtil.isEmpty(sessionCSRFToken))
{
return false;
}
return requstCSRFToken.equals(sessionCSRFToken);
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135

注解类:

/**
* 跨站请求仿照注解
* 刷新CSRFToken
* @author Tangguilin
* @version [版本号, 2016年3月28日]
*/
@Target({java.lang.annotation.ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface RefreshCSRFToken
{
/**
* 刷新CSRFToken
* @author tangguilin
* @return
*/
public abstract boolean refreshCSRFToken();
} /**
* 跨站请求仿照注解
*
* @author Tangguilin
* @version [版本号, 2016年3月28日]
*/
@Target({java.lang.annotation.ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface VerifyCSRFToken
{
/**
* 需要验证防跨站请求
* @author tangguilin
* @return
*/
public abstract boolean verifyCSRFToken(); }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

配置拦截:

   <mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<!-- 定义在mvc:interceptor下面的表示是对特定的请求才进行拦截的 -->
<bean class="com.front.interceptor.AvoidCSRFInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

在jsp页面中添加隐藏域

 <input type="hidden" name="CSRFToken" value="${CSRFToken }"></input>  
  • 1
  • 1

修改公用Ajax

 ajax: function(options) {
var datas = null;
if (options["isAjaxForm"]) {
$("#" + options["formId"]).submit();
} else {
if (options["serialize"]) {
if (options["formId"]) {
datas = $("#" + options["formId"]).serialize();
} else {
datas = $(document.forms[0]).serialize();
}
}
var defaultOptions = {
type: "post",
async: false,
data: datas
};
options = $.extend(defaultOptions, options);
var path="";
if(options["url"].indexOf(basePath)==-1){
path=basePath;
}
var headers = {};
headers['CSRFToken'] = $("input[name='CSRFToken']").val();
$.ajax({
type: options["type"],
headers: headers,
async: options["async"],
dataType: options["dataType"],
url: path + options["url"],
data: options["data"],
success: function(data) {
//登录超时刷新页面后跳转首页
if("2000062"==data.code){
window.location.reload();
}
//处理跨站请求伪造
if("666666" == data.code){
if(Dialog){
Dialog.show("操作失败,请刷新页面重试","error");
}else{
alert("操作失败,请刷新页面重试");
}
return false;
}
if (typeof(options["success"]) == "function") {
options["success"](data);
}
},
error: function(data) {
//CSRFToken处理
if(data && data.readyState && data.readyState == '4'){
var responseBody = data.responseText;
if(responseBody){
responseBody = "{'retData':"+responseBody;
var resJson = eval('(' + responseBody + ')');
$("input[name='CSRFToken']").val(resJson.csrf.CSRFToken);
if (typeof(options["success"]) == "function") {
options["success"](resJson.retData);
}
}
return ;
}
//登录超时跳转登录页
/*if(data.responseText){
window.location.reload();//刷新当前页面.
return;
}*/
if (typeof(options["error"]) == "function") {
options["error"](data);
}else{
alert("请求地址:"+options["url"]+" 出现异常!请联系管理员!");
} }
});
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78

使用场景 
为需要防御的Controller加上@VerifyCSRFToken(verifyCSRFToken = true)注解

@RefreshCSRFToken(refreshCSRFToken=true):如新打开的页面,弹出框体需要CSRFToken时使用

CSRF spring mvc 跨站请求伪造防御(转)的更多相关文章

  1. Django:CSRF(Cross-request forgery)跨站请求伪造

    一.CSRF是什么 二.CSRF攻击原理 三.CSRF攻击防范 一.CSRF是什么 CSRF(Cross-site request forgery)跨站请求伪造,也被称为“One Click Atta ...

  2. DVWA(五):CSRF 全等级跨站请求伪造

    CSRF,全称Cross-site request forgery,翻译过来就是跨站请求伪造,是指利用受害者尚未失效的身份认证信息(cookie.会话等),诱骗其点击恶意链接或者访问包含攻击代码的页面 ...

  3. 2、Web应用程序中的安全向量 -- CSRF/XSRF(跨站请求伪造)

    CSRF的概念可以分为两类:XSS和混淆代理. 混淆代理中的"代理"是指用户的浏览器.CSRF是基于浏览器的工作方式运作的.用户登录到一个站点后,用户的信息将会存储在cookie中 ...

  4. Web安全测试之跨站请求伪造(CSRF)篇

    跨站请求伪造(即CSRF)被Web安全界称为诸多漏洞中“沉睡的巨人”,其威胁程度由此“美誉”便可见一斑.本文将简单介绍该漏洞,并详细说明造成这种漏洞的原因所在,以及针对该漏洞的黑盒测试与灰盒子测试具体 ...

  5. Django框架之跨站请求伪造

    跨站请求伪造(英语:Cross-site request forgery),也被称为one-click attack或者session riding,通常缩写为CSRF或者XSRF, 是一种挟制用户在 ...

  6. ASP.NET MVC 防止跨站请求伪造(CSRF)攻击的方法

    在HTTP POST请求中,我们多次在View和Controller中看下如下代码: View中调用了Html.AntiForgeryToken(). Controller中的方法添加了[Valida ...

  7. 安全性测试入门 (三):CSRF 跨站请求伪造攻击和防御

    本篇继续对于安全性测试话题,结合DVWA进行研习. CSRF(Cross-site request forgery):跨站请求伪造 1. 跨站请求伪造攻击 CSRF则通过伪装成受信任用户的请求来利用受 ...

  8. PHP安全编程:跨站请求伪造CSRF的防御(转)

    跨站请求伪造(CSRF)是一种允许攻击者通过受害者发送任意HTTP请求的一类攻击方法.此处所指的受害者是一个不知情的同谋,所有的伪造请求都由他发起,而不是攻击者.这样,很你就很难确定哪些请求是属于跨站 ...

  9. .NET Core实战项目之CMS 第十四章 开发篇-防止跨站请求伪造(XSRF/CSRF)攻击处理

    通过 ASP.NET Core,开发者可轻松配置和管理其应用的安全性. ASP.NET Core 中包含管理身份验证.授权.数据保护.SSL 强制.应用机密.请求防伪保护及 CORS 管理等等安全方面 ...

随机推荐

  1. 5.RabbitMQ 客户端控制消息

    1.生产者发送消息,消费者结束消息并回执 2.通过channel.basicConsume向服务器发送回执,删除服务上的消息 3.//不向服务器发送回执,服务器的消息一直存在 4.//消费者拒绝接受消 ...

  2. JVM内核-原理、诊断与优化学习笔记(五):GC参数

    文章目录 堆的回顾 串行收集器 并行收集器 ParNew(par-并行的缩写,new-新生代,所以只是新生代并行) Parallel收集器 参数设置 -XX:MaxGCPauseMills -XX:G ...

  3. 在jsp页面直接读取mysql数据库显示数据

    闲来无事,学学java,虽说编程语言相通,但是接触一门新知识还是有些疑惑,边学边记录,方便以后温故. 直接给出代码: <%@page import="java.sql.ResultSe ...

  4. LeetCode刷题笔记-回溯法-括号生成

    题目描述: 给出 n 代表生成括号的对数,请你写出一个函数,使其能够生成所有可能的并且有效的括号组合. 例如,给出 n = 3,生成结果为: [ "((()))", "( ...

  5. man命令的使用方法

    转载自:http://www.cnblogs.com/hnrainll/archive/2011/09/06/2168604.html Linux man命令的使用方法 Linux提供了丰富的帮助手册 ...

  6. HashMap底层实现原理及面试问题

    ①HashMap的工作原理 HashMap基于hashing原理,我们通过put()和get()方法储存和获取对象.当我们将键值对传递给put()方法时,它调用键对象的hashCode()方法来计算h ...

  7. DRF的序列化组件

    目录 DRF的序列化组件 Serializer组件 序列化 反序列化 ModelSerializer组件 序列化和反序列化 自定义Response方法 基表相关 DRF中ORM的多表关联操作 外键设计 ...

  8. uoj192 【UR #14】最强跳蚤

    题目 和成爷达成一致,被卡随机的话就是过了 考虑一个完全平方数的所有质因子次幂一定是偶数,于是对于每一条边我们都只保留其出现次数为奇数的质因子 注意到有一个点的\(w\leq 80\),于是考虑状压质 ...

  9. 我写的界面,在ARM上跑

    这个...其实,我对ARM了解并不多,我顶多也就算是知道ARM怎么玩,EMMC干啥,MMU干啥,还有早期的叫法,比如那个NorFlash NandFlash ,然后也就没啥了. 然后写个裸机什么的,那 ...

  10. JAVA读取PROPERTIES文件方式一

    import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.i ...