如何在没有隐藏输入的情况下获得AntiForgeryToken值

问题描述 投票:28回答:3

@ 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));
    }
asp.net-mvc-4
3个回答
20
投票

MVC的反CSRF功能实际上取决于two标记:一个是隐藏的表单元素,另一个是cookie。因此,Html.AntiForgeryToken()帮助器不仅返回HTML代码段。 它还有设置此cookie的副作用。请注意,cookie值和表单值不相等,因为它们各自编码不同的信息。

如果使用AntiForgery.GetTokens API,则此方法将返回原始令牌,而不是生成HTML代码段。此方法的参数为:

  • oldCookieToken:如果请求已包含反CSRF cookie令牌,请在此处提供。此参数可以为空。
  • newCookieToken(输出参数):如果oldCookieToken为null或不表示有效的反CSRF cookie令牌,则该参数将填充您应放入响应cookie中的值。如果oldCookieToken表示有效的反CSRF令牌,则当方法返回时,newCookieToken将包含null,并且您不必设置响应cookie。
  • formToken(输出参数):此参数将填充回发到服务器时应存在于表单主体中的令牌。这是在调用Html.AntiForgeryToken()时最终被隐藏的输入元素包装的值。

如果使用此API手动生成cookie和形成令牌,则需要调用AntiForgery.Validate的the corresponding overload以验证令牌。


16
投票

我知道这个问题很旧,但是根据我在这里的读物,我想出了一个相当简单的解决方案,似乎对我有用。我在使用部分模板的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 )

0
投票

这有点旧,但是我没有找到真正的答案。我四处张望,找到了解决方案。我需要在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。

© www.soinside.com 2019 - 2024. All rights reserved.