欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

ASP.NET MVC Ajax 伪造请求

程序员文章站 2022-07-27 23:48:00
1.前言 CSRF(Cross-site request forgery)跨站请求伪造,ASP.NET MVC 应用通过使用AJAX请求来提升用户体验,浏览器开发者工具可以一览众山小,就很容易伪造了请求对应用进行攻击,从而泄露核心数据,导致安全问题。微软自带AntiForgeryToken可以解决, ......

1.前言

          CSRF(Cross-site request forgery)跨站请求伪造,ASP.NET MVC 应用通过使用AJAX请求来提升用户体验,浏览器开发者工具可以一览众山小,就很容易伪造了请求对应用进行攻击,从而泄露核心数据,导致安全问题。微软自带AntiForgeryToken可以解决,而且语法简单(AJAX请求发起时传递给后台一个字符串,然后在Filter中进行校验)

2.场景如下

为了验证一个来自form post请求,还需要在目标action上增加自定义[AntiForgeryToken]特性,下面会介绍到这个自定义特性用法

    /// <summary>
    /// 首页
    /// </summary>
    public class HomeController : Controller
    {

        /// <summary>
        /// 用户登录了111111
        /// </summary>
        /// <returns></returns>
        public ActionResult Index()
        {
            return View();
        }

        /// <summary>
        /// Your application description page.
        /// </summary>
        /// <returns></returns>
        public ActionResult About()
        {
            ViewBag.Message = "Your application description page.";
            return View();
        }

        /// <summary>
        /// Your contact page.
        /// </summary>
        /// <param name="name">姓名</param>
        /// <returns></returns>
        public ActionResult Contact(string name)
        {
            ViewBag.Message = "Your contact page.";
            return View();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public ActionResult Person()
        {
            return View();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="Name"></param>
        /// <param name="Age"></param>
        /// <returns></returns>
        [HttpPost]
        [AntiForgeryToken]
        public ActionResult UserInfo(string Name,string Age)
        {
            return Json(Name + Age);
        }

    }

前端html中如何防范?

一句语法糖解决所有问题,通过在html页面上或者script中使用 Html.AntiForgeryToken(),然后赋值给ajax中headers

html页面上

1.html中使用@Html.AntiForgeryToken(),然后通过jquery中name,获取隐藏域value的值,再赋值给ajax中headers

2.var headToken=$('input[name="__RequestVerificationToken"]').val();

script中

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Person</title>
    <script src="~/Scripts/jquery-3.3.1.min.js"></script>
    <script src="~/Scripts/jquery.validate.js"></script>
    <script src="~/Scripts/jquery.validate.unobtrusive.js"></script>
</head>
<body>
    <form id="form1">
    @*@Html.AntiForgeryToken()*@ <div class="form-horizontal"> <div class="form-group"> <div> 姓名:<input type="text" name="name" value="" id="name" /> 密码: <input type="text" name="age" value="" id="age" /> </div> <div class="col-md-offset-2 col-md-10"> <input type="button" id="save" value="Create" class="btn btn-default" /> </div> </div> </div> </form> <script> $(function () { //获取防伪标记 var token = $('@Html.AntiForgeryToken()').val(); var headers = {}; //防伪标记放入headers //也可以将防伪标记放入data headers["__RequestVerificationToken"] = token; $("#save").click(function () { $.ajax({ type: 'POST', url: '/Home/UserInfo', cache: false, headers: headers, data: { Name: $("#name").val(), Age: $("#age").val() }, success: function (data) { alert(data) }, error: function () { alert("Error") } }); }) }); </script> </body> </html>

3.自定义AuthorizeAttribute属性

它主要检查

(1)请求的是否包含一个约定的AntiForgery名的cookie

(2)请求Headers是否有一个["__RequestVerificationToken"],并且不能为空,约定的AntiForgery名的cookie和Headers中的值是否匹配

public class AntiForgeryToken : AuthorizeAttribute
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="filterContext"></param>
        public override void OnAuthorization(AuthorizationContext filterContext)
        {

            var request = filterContext.HttpContext.Request;

            if (request.IsAjaxRequest())
            {
                var antiForgeryCookie = request.Cookies[AntiForgeryConfig.CookieName];

                var cookieValue = antiForgeryCookie != null ? antiForgeryCookie.Value : null;
                var headerValue = request.Headers["__RequestVerificationToken"];
                //获取head中的值  如果为空直接拒绝不往下走
                if (string.IsNullOrEmpty(headerValue))
                {
                    base.OnAuthorization(filterContext);
                    return;
                }

                //从cookies 和 Headers 中 验证防伪标记
                AntiForgery.Validate(cookieValue,headerValue);

            }
        }
    }