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

时间:2013-02-17 20:00:48

标签: asp.net-mvc-4

@ 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));
    }

4 个答案:

答案 0 :(得分:17)

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

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

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

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

答案 1 :(得分:12)

我意识到这个问题已经过时了,但根据我在这里阅读的内容,我想出了一个似乎对我有用的相当简单的解决方案。我在使用部分模板的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中)我只需要包含&#39; @ formToken&#39;在标题中:

$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 )

答案 2 :(得分: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。

答案 3 :(得分:0)

对于asp.net core使用依赖注入获取IAntiforgery然后调用GetAndStoreTokens

public class TestController
{
    public TestController(IAntiforgery antiforgery)
    {
        var tokens = antiforgery.GetAndStoreTokens(HttpContext);
    }
}