架构师_程序员_码农网

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

搜索
查看: 25367|回复: 4

[ASP.NET] mvc ajax带上AntiForgeryToken防止CSRF攻击

[复制链接]
发表于 2017-11-2 10:06:29 | 显示全部楼层 |阅读模式
经常看到在项目中ajax post数据到服务器不加防伪标记,造成CSRF攻击,在Asp.net Mvc里加入防伪标记很简单在表单中加入Html.AntiForgeryToken()即可。
Html.AntiForgeryToken()会生成一对加密的字符串,分别存放在Cookies 和 input 中。我们在ajax post中也带上AntiForgeryToken
MVC中的Html.AntiForgeryToken()是用来防止跨站请求伪造(CSRF:Cross-site request forgery)攻击的一个措施,它跟XSS(XSS又叫CSS:Cross-Site-Script),攻击不同,XSS一般是利用站内信任的用户在网 站内插入恶意的脚本代码进行攻击,而CSRF则是伪造成受信任用户对网站进行攻击。
首先,我们视图代码如下:

  1. @{
  2.     Layout = null;
  3. }
  4. <!DOCTYPE html>
  5. <html>
  6. <head>
  7.     <meta name="viewport" content="width=device-width" />
  8.     <title>A1</title>
  9.     <script src="~/Scripts/jquery-1.10.2.min.js"></script>
  10. </head>
  11. <body>
  12.     <div>
  13.         <button id="save" type="button">test</button>
  14.     </div>
  15.     <script type="text/javascript">
  16.         $(function () {
  17.             //获取防伪标记
  18.             var token = $('@Html.AntiForgeryToken()').val();
  19.             var headers = {};
  20.             //防伪标记放入headers
  21.             //也可以将防伪标记放入data
  22.             headers["__RequestVerificationToken"] = token;
  23.             $("#save").click(function () {
  24.                 $.ajax({
  25.                     type: 'POST',
  26.                     url: '/Home/Index',
  27.                     cache: false,
  28.                     headers: headers,
  29.                     data: { Name: "yangwen", Age: "1" },
  30.                     success: function (data) {
  31.                         alert(data)
  32.                     },
  33.                     error: function () {
  34.                         alert("Error")
  35.                     }
  36.                 });
  37.             })
  38.         });
  39.     </script>
  40. </body>
  41. </html>
复制代码
运行起来,生成的html代码如下:




  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4.     <meta name="viewport" content="width=device-width" />
  5.     <title>A1</title>
  6.     <script src="/Scripts/jquery-1.10.2.min.js"></script>
  7. </head>
  8. <body>
  9.     <div>
  10.         <button id="save" type="button">test</button>
  11.     </div>
  12.     <script type="text/javascript">
  13.         $(function () {
  14.             //获取防伪标记
  15.             var token = $('<input name="__RequestVerificationToken" type="hidden" value="h-MB0IrTwL2zXtG_1UExlbt5SL9nylyE2yRzT4en--Tjb4MP5-KX4N18bFTcDQ62992jJgFPIbE8w1P7AG8YuvVZW4YgKMXrcI-8uiS3qvg1" />').val();
  16.             var headers = {};
  17.             //防伪标记放入headers
  18.             //也可以将防伪标记放入data
  19.             headers["__RequestVerificationToken"] = token;
  20.             $("#save").click(function () {
  21.                 $.ajax({
  22.                     type: 'POST',
  23.                     url: '/Home/Index',
  24.                     cache: false,
  25.                     headers: headers,
  26.                     data: { Name: "yangwen", Age: "1" },
  27.                     success: function (data) {
  28.                         alert(data)
  29.                     },
  30.                     error: function () {
  31.                         alert("Error")
  32.                     }
  33.                 });
  34.             })
  35.         });
  36.     </script>
  37. </body>
  38. </html>
复制代码


我们点击test按钮,去请求测试一下,看下是否带上了防伪造的cookie,如下图:

QQ截图20171102100206.jpg

控制器中代码如下:

  1. [HttpPost]
  2.   [ValidateAntiForgeryToken]
  3.   public ActionResult Index(Person p)
  4.    {
  5.    return Json(true, JsonRequestBehavior.AllowGet);
  6.    }
  7.   }
  8. public class Person
  9.   {
  10.   public string Name { get; set; }
  11.   public int Age { get; set; }
  12.   }
复制代码
我们需要每个控制器里面里面加上ValidateAntiForgeryToken特性,如果用户没有带上AntiForgeryToken,我们可以返回给用户一个友好的提示,参考如下:

  1. public class MyValidateAntiForgeryToken : AuthorizeAttribute
  2.     {
  3.         public override void OnAuthorization(AuthorizationContext filterContext)
  4.         {
  5.             var request = filterContext.HttpContext.Request;
  6.             if (request.HttpMethod == WebRequestMethods.Http.Post)
  7.             {
  8.                 if (request.IsAjaxRequest())
  9.                 {
  10.                     var antiForgeryCookie = request.Cookies[AntiForgeryConfig.CookieName];
  11.                     var cookieValue = antiForgeryCookie != null
  12.                      ? antiForgeryCookie.Value
  13.                      : null;
  14.                     //从cookies 和 Headers 中 验证防伪标记
  15.                     //这里可以加try-catch
  16.                     AntiForgery.Validate(cookieValue, request.Headers["__RequestVerificationToken"]);
  17.                 }
  18.                 else
  19.                 {
  20.                     new ValidateAntiForgeryTokenAttribute()
  21.                      .OnAuthorization(filterContext);
  22.                 }
  23.             }
  24.         }
  25.     }
复制代码






上一篇:asp.net mvc BindAttribute绑定特性
下一篇:CMMI与Agile敏捷开发比较之一:两者的本质区别
码农网,只发表在实践过程中,遇到的技术难题,不误导他人。
 楼主| 发表于 2017-11-2 11:05:37 | 显示全部楼层
上面方法,必须自定义特性,不能使用默认的ValidateAntiForgeryToken特性

默认的特性是在form表单里面去取值,然后判断的

QQ截图20171102110256.jpg

自己用jQuery封装了一个post方法,带有防伪造验证的,代码如下:

  1. @{
  2.     ViewBag.Title = "Home Page";
  3.     Layout = null;
  4. }

  5. <html xmlns="http://www.w3.org/1999/xhtml">
  6. <head>
  7.     <title>页面一</title>
  8.     <script src="~/Scripts/jquery-1.10.2.min.js"></script>
  9.     <script>
  10.         //mvc 防止CSRF攻击
  11.         ; (function ($) {
  12.             $.postCSRF = function (url, postData, succCallback, errorCallback, type, dataType) {
  13.                 var dataType = dataType || "json";
  14.                 var headers = {};
  15.                 var token = $("input[name='__RequestVerificationToken']").val();
  16.                 if (token != undefined && token != "")
  17.                 {
  18.                     headers["__RequestVerificationToken"] = token;
  19.                 };
  20.                 $.ajax({
  21.                     type: "post",
  22.                     url: url,
  23.                     data: postData,
  24.                     cache: false,
  25.                     headers: headers,
  26.                     dataType: dataType,
  27.                     success: function (res) {
  28.                         if (succCallback) {
  29.                             succCallback(res);
  30.                         }
  31.                     },
  32.                     error: function (res)
  33.                     {
  34.                         if (errorCallback) {
  35.                             errorCallback(res);
  36.                         }
  37.                     }
  38.                 });
  39.             }
  40.         })(jQuery);
  41.         $(function () {
  42.             $("#my").click(function () {
  43.                 $.postCSRF("/Home/Test1","aaa=1", function (data) {
  44.                     $("#test").append(data.msg + "</br>");
  45.                 });
  46.             });
  47.         });
  48.     </script>
  49. </head>
  50. <body>
  51.     @Html.AntiForgeryToken()
  52.     <h1>by http://www.itsvse.com</h1>
  53.     <div id="test"></div>
  54.     <button id="my" type="button">my</button>
  55. </body>
  56. </html>
复制代码


码农网,只发表在实践过程中,遇到的技术难题,不误导他人。
 楼主| 发表于 2017-11-2 11:17:36 | 显示全部楼层
IsAjaxRequest判断是否是ajax请求

本质上IsAjaxRequest()是判断header里面有没有X-Requested-With字段以及它是否是XMLHttpRequest

看文档没用,要看源代码。
码农网,只发表在实践过程中,遇到的技术难题,不误导他人。
 楼主| 发表于 2021-2-20 19:22:26 | 显示全部楼层
ASP.NET CSRF 攻击Ajax请求封装
https://www.itsvse.com/thread-8077-1-1.html
码农网,只发表在实践过程中,遇到的技术难题,不误导他人。
发表于 2021-12-9 18:37:56 | 显示全部楼层
testtesttesttest
码农网,只发表在实践过程中,遇到的技术难题,不误导他人。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

免责声明:
码农网所发布的一切软件、编程资料或者文章仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。如有侵权请邮件与我们联系处理。

Mail To:help@itsvse.com

QQ|手机版|小黑屋|架构师 ( 鲁ICP备14021824号-2 )|网站地图

GMT+8, 2024-11-8 00:42

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表