在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进行操作。
默认的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);
}
如果用这种方法,就要在后台多做点工作。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()
。其实思路大体上一样的,只是换成了另外一种形式。
版权声明:本文由十有三创作,采用知识共享许可协议:署名-相同方式共享 4.0 国际(CC BY-SA 4.0)。欢迎转载本文,转载请务必署名-保留作者名称及出处:https://shiyousan.com/post/636371783368334367。