ASP.NET MVC 防止CSRF攻击

CSRF:跨站请求伪造。

A和B都在访问淘宝,A下订单买一台手机,将生成的链接通过QQ发送给B,然后B不明就里的打开了链接,就算是支付成功了(假定购买东西不需要二次密码验证,只需要登录淘宝网站就可以了。登录网站之后,会生成一个cookie在浏览器中,再次浏览该网页,因为cookie没有失效,所以不需要再次登录进行确认)。

 

在前台表单中使用@Html.AntiForgeryToken(),这样服务器在渲染页面的时候,会生成一个默认名为__RequestVerificationToken的cookie,并在页面上生成一个隐藏域,name也是__RequestVerificationToken;

在后台action上添加ValidateAntiForgeryToken特性。作用有2;1、请求的是否包含一个约定的AntiForgery名的cookie。2、请求是否有一个Request.Form["约定的AntiForgery名"],约定的AntiForgery名的cookie和Request.Form值是否匹配。

只针对Post方法有效,Get方法无效。

表单提交,防止CSRF攻击。

复制代码
@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
    <p>
        <label>
            Username:</label><input name="username" /></p>
    <p>
        <label>
            Password:</label><input name="password" type="password" /></p>
    <input type="submit" value="登录" />
}
复制代码

 

        [ValidateAntiForgeryToken]
        public ActionResult DoSth(string username, string password)
        {
            return Content("ASP.NET MVC中,表单提交防止CSRF。");
        }

 


 

使用AJAX提交。防止CSRF攻击

前台代码

复制代码
@using (Html.BeginForm("Login", "Home"))
{
    <p>
        <label>
            Username:</label><input name="username" /></p>
    <p>
        <label>
            Password:</label><input name="password" type="password" /></p>
    <input type="submit" value="登录" />
    <input type="button" id="btn1" value="异步登录" />
}
<script src="../../JS/jquery-1.7.1.min.js" type="text/javascript"></script>
<script type="text/javascript">
    $(function () {
        $("#btn1").click(function () {
            $.ajax({
                type: "Post",
                url: '@Url.Action("Login", "Home")',
                data: { "username": "vichin", "password": "123" }, //post请求,不需要key
                success: function (res) {
                    alert(res);
                },
                error: function (msg) {
                    alert(msg.responseText);
                }, headers: {
                    token: $('@Html.AntiForgeryToken()').val()
                    //如果页面上使用了,那么页面上就会生成name为__RequestVerificationToken的隐藏域。
                    //可以使用$('[name=__RequestVerificationToken]').val()来获取。
                }
            });
        });
    })
</script>
复制代码

在后台代码中,需要增加过滤器。然后在请求的action上应用该过滤器。

复制代码
    public class MyAntiForgeryTokenAttribute : 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 中 验证防伪标记
                    AntiForgery.Validate(cookieValue, request.Headers["__RequestVerificationToken"]);//这里可以加try-catch
                }
                else
                {
                    new ValidateAntiForgeryTokenAttribute().OnAuthorization(filterContext);
                }
            }
        }
    }
复制代码
        [MyAntiForgeryToken]
        public ActionResult Login(string username, string password)
        {
            return Content("ASP.NET MVC中,表单提交防止CSRF。");
        }

 

posted @   水墨晨诗  阅读(253)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示