@ Html.AntiForgeryToken()呈现隐藏的输入
<input name="__RequestVerificationToken" type="hidden" value="GuiNIwhIJZjINHhuS_8FenaFDXIiaE" />
如何仅获取令牌值?没有像这样的丑陋代码:
public static IHtmlString AntiForgeryTokenValue(this HtmlHelper htmlHelper) {
var field = htmlHelper.AntiForgeryToken().ToHtmlString();
var beginIndex = field.IndexOf("value=\"") + 7;
var endIndex = field.IndexOf("\"", beginIndex);
return new HtmlString(field.Substring(beginIndex, endIndex - beginIndex));
}
MVC的反CSRF功能实际上取决于two标记:一个是隐藏的表单元素,另一个是cookie。因此,Html.AntiForgeryToken()帮助器不仅返回HTML代码段。 它还有设置此cookie的副作用。请注意,cookie值和表单值不相等,因为它们各自编码不同的信息。
如果使用AntiForgery.GetTokens API,则此方法将返回原始令牌,而不是生成HTML代码段。此方法的参数为:
如果使用此API手动生成cookie和形成令牌,则需要调用AntiForgery.Validate的the corresponding overload以验证令牌。
我知道这个问题很旧,但是根据我在这里的读物,我想出了一个相当简单的解决方案,似乎对我有用。我在使用部分模板的AngularJS SPA上使用它,其中只有一些涉及POST提交。
我将此代码放在视图的顶部:
@{
string cookieToken, formToken;
string oldCookieToken = Request.Cookies[AntiForgeryConfig.CookieName] == null ? null : Request.Cookies[AntiForgeryConfig.CookieName].Value;
AntiForgery.GetTokens( oldCookieToken, out cookieToken, out formToken );
if( oldCookieToken == null )
{
Request.Cookies.Add( new HttpCookie( AntiForgeryConfig.CookieName, cookieToken ) );
}
else
{
Request.Cookies[AntiForgeryConfig.CookieName].Value = cookieToken;
}
}
然后在任何需要表单的防伪令牌的地方(例如,在ajax或angularjs POST中,我只在标头中包含'@formToken':
$http.post(route, JSON.stringify(args), {
headers: {
'@AntiForgeryConfig.CookieName': '@formToken',
'Content-Type': 'application/json; charset=utf-8',
},
});
[请注意,因为在此示例中,我期望从我的操作方法返回JSON数据,所以我还必须基于标头(而不是表单字段)实现防伪验证。 http://johan.driessen.se/posts/Updated-Anti-XSRF-Validation-for-ASP.NET-MVC-4-RC.上有一篇很好的帖子。这是实现:
[AttributeUsage( AttributeTargets.Method | AttributeTargets.Class,
AllowMultiple = false, Inherited = true )]
public sealed class ValidateJsonAntiForgeryTokenAttribute
: FilterAttribute, IAuthorizationFilter
{
public void OnAuthorization( AuthorizationContext filterContext )
{
if( filterContext == null )
{
throw new ArgumentNullException( "filterContext" );
}
var httpContext = filterContext.HttpContext;
var cookie = httpContext.Request.Cookies[AntiForgeryConfig.CookieName];
AntiForgery.Validate( cookie != null ? cookie.Value : null,
httpContext.Request.Headers[AntiForgeryConfig.CookieName] );
}
}
这是它的用法:
[HttpPost]
[ValidateJsonAntiForgeryToken]
public JsonResult RecordVisit( VisitInfo info )
这有点旧,但是我没有找到真正的答案。我四处张望,找到了解决方案。我需要在javascript对象中使用formtoken,因此此帮助程序派上了用场。
public static class AntiForgeryHtmlExtensions
{
public static string AntiForgeryFormToken(this HtmlHelper helper)
{
string cookieToken, formToken;
AntiForgery.GetTokens(null, out cookieToken, out formToken);
HttpContext.Current.Response.Cookies.Set(new HttpCookie(AntiForgeryConfig.CookieName, cookieToken));
return formToken;
}
}
正如@Levi提到的,调用GetTokens具有副作用,因此我们必须在返回令牌之前设置response-cookie。