ASP.NET MVC 获取及手动更新AntiForgeryToken防伪标记

在ASP.NET MVC中是可以通过代码手动控制防伪标记(AntiForgeryToken)的更新。另外在介绍更新令牌的具体方法前,会先说明如何获取防伪令牌,毕竟要以此为基础才能实现。

在ASP.NET MVC中,默认只要在视图页面中使用@Html.AntiForgeryToken(),就会自动生成表单令牌和Cookie令牌。但是我们后台如果想要实现手动获取,就要使用System.Web.Helpers.AntiForgery这个类,有兴趣查看源码的朋友会发现,其实@Html.AntiForgeryToken()内部调用的方法和AntiForgery这个类是一样的。

主要是通过AntiForgery.GetHtml()或者AntiForgery.GetTokens(string oldCookieToken,out string newCookieToken,out string formToken)这两个静态方法获取对应的表单和Cookie令牌。不过要注意的是,一旦调用了GetHtml方法,会自动生成对应的Cookie令牌,然后直接返回一段带有表单令牌值隐藏字段的Html代码,返回的值是这种形式的:

<input name="__RequestVerificationToken" type="hidden" value="8_nUk_3z0svQr9qcvRBi9SWMZ2-SYmuy9kRe9OgRobGULkb2Z4JZxRZFhR0ndeoy9hmDLDru7MFk-W4xrnL5z5T6VbkfXK7fyRk-egQBGm41">

隐藏字段的name名称一般固定为"__RequestVerificationToken",值是经过加密后的防伪令牌。 这个隐藏字段一般要放置在所需提交的表单中,最后提交的时候会和Cookie令牌进行对比验证。

如果使用GetTokens方法,传入对应的参数后可以获取加密后的表单和Cookie令牌,但是这里要自己存储对应的值。

接下来开始介绍手动更新AntiForgeryToken的方法,主要是通过AJAX进行操作。

方法一、使用GetHtml的方法获取表单令牌并更新

默认的View视图代码如下(有一个使用防伪标记的表单):

@using (Html.BeginForm("TokenTest", "Home", FormMethod.Post, new { id = "formLogin" }))
{
    <div id="divAntiForgeryToken">@Html.AntiForgeryToken()</div>
    //此处省略其他表单代码
    <input type="submit" value="提交" />
}

View中Js关键代码如下:

//注意引用jQuery库
//一定不能使用异步!async要设置成false
$.ajax({
    url: '/Home/RefreshToken', async: false, type: 'GET', success: function (data) {                        
        //方法一:直接更新HTML代码
        $("#divAntiForgeryToken").empty().append(data);
        //方法二:替换隐藏字段值
        //var tokenValue = $('<div />').html(data).find('input[type="hidden"]').val();
        //$('input[name="__RequestVerificationToken"]').val(tokenValue);
    }
});

这里需要注意,此处只列举出关键代码,具体在什么时候刷新令牌就要根据自己的需求来,比如点击某个按钮,或者表单提交的时候。另外之所以设置async: false,是为了能保证令牌能进行同步更新,特别是与身份验证和授权有关的情况!

Controller控制台的令牌刷新操作方法代码如下:

public ActionResult RefreshToken()
{            
    var tokenHtml = System.Web.Helpers.AntiForgery.GetHtml().ToString();
    return Content(tokenHtml);
}

方法二,使用GetTokens方法灵活控制令牌

如果用这种方法,就要在后台多做点工作。View的代码和方法一一样就可以了,主要在于后台的控制器代码:

public ActionResult RefreshToken()
{
    string cookieToken;
    string formToken;
    System.Web.Helpers.AntiForgery.GetTokens(null, out cookieToken, out formToken);
    string cookieName = "__RequestVerificationToken";
    if (Response.Cookies.AllKeys.Contains(cookieName))
    {
        Response.Cookies[cookieName].Value = cookieToken;
    }
    else
    {
        Response.Cookies.Add(new HttpCookie(cookieName, cookieToken));
    }
    return Content(formToken);
}

View中的Js部分也要稍作修改:

$.ajax({
    url: '/Home/RefreshToken', async: false, type: 'GET', success: function (data) {
        $('input[name="__RequestVerificationToken"]').val(data);
    }
});

总结下,从源码上来看,其实GetHtml方法内部是调用了GetTokens方法的,所以两者并没有什么区别!从使用角度来看,方法一比较便捷,内部已经帮我们做好了相关处理,只需要在表单中放入对应的令牌即可。方法二还需要自己保存Cookie令牌,但是如果需要灵活操作就可以可考虑方法二。

另外上面的方法只是个思路,我还看过国外程序员通过加载PartialView来刷新防伪标识的,PartialView中只包含这段代码:@Html.AntiForgeryToken()。其实思路大体上一样的,只是换成了另外一种形式。




原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/99047.html

(0)
上一篇 2021年8月21日
下一篇 2021年8月21日

相关推荐

发表回复

登录后才能评论