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到页面隐藏域。 
代码示例: 
创建拦截器:

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

注解类:

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

配置拦截:

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

在jsp页面中添加隐藏域

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

修改公用Ajax

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

    传送门 解题思路 前两个操作都比较基础.对于第三个操作分类讨论一下,首先如果当前根不是要操作点的子树,那么就无影响,直接查询操作点的子树即可.第二种是当前根是操作点的子树,那就找到当前根到操作点这条链 ...

  2. NOIp2018集训test-9-15(联考二day1)

    T1.矩阵游戏 水题.每一行最后乘的数为x[i],每一列为y[i],暴力算第一行的列的贡献,每一行的列的贡献是公差为所有列的贡献之和的等差数列,然后每一行再乘上行的贡献求和即为答案. //Achen ...

  3. NX二次开发-C++time函数计时

    NX11+VS2013 #include <uf.h> #include <uf_modl.h> #include <uf_ui.h> #include <t ...

  4. Python爬虫-《神雕侠侣》

    Python3.5 爬取<神雕侠侣>http://www.kanunu8.com/wuxia/201102/1610.html 武侠迷,所以喜欢爬取武侠小说 #!/usr/bin/pyth ...

  5. (转)在Source Insight中看Python代码

    http://blog.csdn.net/lvming404/archive/2009/03/18/4000394.aspx SI是个很强大的代码查看修改工具,以前用来看C,C++都是相当happy的 ...

  6. 剑指offer——22表示数值的字符串

    题目描述 请实现一个函数用来判断字符串是否表示数值(包括整数和小数).例如,字符串"+100","5e2","-123","3.1 ...

  7. **JLink Warning: Mis-aligned memory write: Address: 0x20000000, NumBytes: 2, Alignment: 2 (Halfword-aligned)

    网上也有同学遇到这个问题,http://www.openedv.com/thread-113049-1-3.html 根据他的经验我也重新安装了Jlink驱动: 顺便注意Dialog DLL:TARM ...

  8. 【学术篇】SDOI2011 计算器

    好一道三合一...(然而被我做成了四合一) 其实1 2 3是独立的OvO 然后就可以逐个分析了... 1 快速幂..就不说了..(我省选的时候有这么水的20pts部分分么←_← 2 两种做法(写在标题 ...

  9. PHP算法之盛最多水的容器

    给定 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) .在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0).找出其中的两条线, ...

  10. 纯PHP Codeigniter(CI) ThinkPHP效率测试

    最近一直想做一个技术类的新闻站点,想做的执行效率高些,想用PHP做,一直纠结于用纯PHP做还是用CI或者THINKPHP.用纯PHP效率高,缺点 n多,比如安全方面.构架方面等等等等:用CI.thin ...