28

@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

5 回答 5

20

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

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

  • oldCookieToken:如果请求中已经包含反 CSRF cookie 令牌,请在此处提供。此参数可能为空。
  • newCookieToken(out 参数):如果oldCookieToken为 null 或不代表有效的反 CSRF cookie 令牌,则此参数将填充您应放入响应 cookie 的值。如果oldCookieToken代表一个有效的 anti-CSRF 令牌,那么newCookieToken在方法返回时将包含 null,您不必设置响应 cookie。
  • formToken(out 参数):此参数将填充回发回服务器时应出现在表单正文中的令牌。这是在调用 Html.AntiForgeryToken() 时最终被隐藏输入元素包装的值。

如果您使用此 API 手动生成 cookie 和表单令牌,则需要调用AntiForgery.Validate的相应重载来验证令牌。

于 2013-02-20T07:31:36.477 回答
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 )
于 2015-05-13T16:02:42.840 回答
0

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

于 2020-04-01T05:08:46.410 回答
0

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

public class TestController
{
    public TestController(IAntiforgery antiforgery)
    {
        var tokens = antiforgery.GetAndStoreTokens(HttpContext);
    }
}
于 2021-03-09T23:46:45.490 回答
0

如果使用核心,您可以在布局或剃须刀页面中执行此操作,如下所示:

@inject Microsoft.AspNetCore.Http.IHttpContextAccessor HttpContextAccessor
@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Antiforgery
@{
    var afToken = Antiforgery.GetAndStoreTokens(HttpContextAccessor.HttpContext!).RequestToken;
}

<html lang="en">
<head></head>
<body>
    <script type="text/javascript">
        window.XCSRF = '@afToken';
        console.log(window.XCSRF);
    </script>

现在您可以使用 javascript window.XCSRF变量访问令牌

于 2022-02-15T11:49:11.740 回答