切记ajax中要带上AntiForgeryToken防止CSRF攻击

经常看到在项目中ajax post数据到服务器不加防伪标记,造成CSRF攻击

在Asp.net Mvc里加入防伪标记很简单在表单中加入Html.AntiForgeryToken()即可。

Html.AntiForgeryToken()会生成一对加密的字符串,分别存放在Cookies 和 input 中。

我们在ajax post中也带上AntiForgeryToken

<h2>Index</h2>
<form id="form1">
    <div class="form-horizontal">
        <h4>Persen</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <div class="form-group">
            @Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
            </div>
        </div>
        <div class="form-group">
            @Html.LabelFor(model => model.Age, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Age, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Age, "", new { @class = "text-danger" })
            </div>
        </div>
        <div class="form-group">
            <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 src="~/Scripts/jquery-1.10.2.min.js"></script>
<script src="~/Scripts/jquery.validate.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
<script type="text/javascript">
 $(function () {
  //var token = $('[name=__RequestVerificationToken]');
  //获取防伪标记
  var token = $('@Html.AntiForgeryToken()').val();
  var headers = {};
  //防伪标记放入headers
  //也可以将防伪标记放入data
  headers["__RequestVerificationToken"] = token;
  $("#save").click(function () {
   $.ajax({
    type: 'POST',
    url: '/Home/Index',
    cache: false,
    headers: headers,
    data: { Name: "yangwen", Age: "1" },
    success: function (data) {
     alert(data)
    },
    error: function () {
     alert("Error")
    }
   });
  })
 })
</script>

  

  

放在cookies里面的加密字符串

控制器中代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Helpers;
using System.Web.Mvc;
namespace WebApplication1.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }
        [HttpPost]
        [MyValidateAntiForgeryToken]
        public ActionResult Index(Person p)
        {
            return Json(true, JsonRequestBehavior.AllowGet);
        }
    }
    public class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }
    }
    public class MyValidateAntiForgeryToken : AuthorizeAttribute
    {
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            var request = filterContext.HttpContext.Request;
            if (request.HttpMethod == WebRequestMethods.Http.Post)
            {
                if (request.IsAjaxRequest())
                {
                    var antiForgeryCookie = request.Cookies[AntiForgeryConfig.CookieName];
                    var cookieValue = antiForgeryCookie != null
                     ? antiForgeryCookie.Value
                     : null;
                    //从cookies 和 Headers 中 验证防伪标记
                    //这里可以加try-catch
                    AntiForgery.Validate(cookieValue, request.Headers["__RequestVerificationToken"]);
                }
                else
                {
                    new ValidateAntiForgeryTokenAttribute()
                     .OnAuthorization(filterContext);
                }
            }
        }
    }
}

  这里注释掉ajax中防伪标记在请求

<script type="text/javascript">
    $("#save").click(function () {
        $.ajax({
            type: 'POST',
            url: '/Home/Index',
            cache: false,
            //  headers: headers,
            data: { Name: "yangwen", Age: "1" },
            success: function (data) {
                alert(data)
            },
            error: function () {
                alert("Error")
            }
        });
    })
</script>

  

默认返回500的状态码。

这里修改ajax中的防伪标记

<script type="text/javascript">
    $(function () {
        //var token = $('[name=__RequestVerificationToken]');
        //获取防伪标记
        var token = $('@Html.AntiForgeryToken()').val();
        var headers = {};
        //防伪标记放入headers
        //也可以将防伪标记放入data
        headers["__RequestVerificationToken"] = token + 11111111111111111111111111111111111;
        $("#save").click(function () {
            $.ajax({
                type: 'POST',
                url: '/Home/Index',
                cache: false,
                headers: headers,
                data: { Name: "yangwen", Age: "1" },
                success: function (data) {
                    alert(data)
                },
                error: function () {
                    alert("Error")
                }
            });
        })
    })

</script>

  

也是500的状态码。

以上内容就是本文的全部叙述,切记ajax中要带上AntiForgeryToken防止CSRF攻击。

posted on 2016-06-28 14:12  狼来了  阅读(367)  评论(0编辑  收藏  举报