2013-02-17 45 views
20

@ Html.AntiForgeryToken() 呈现隐藏输入如何获得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)); 
    } 

回答

13

MVC的反CSRF能力实际上取决于令牌:一个是隐藏的表单元素,另一个是一个cookie。所以Html.AntiForgeryToken()助手不仅仅返回一个HTML代码片段。 它也有设置这个cookie的副作用。请注意,Cookie值和表单值不相同,因为它们分别对不同的信息进行编码。

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

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

如果使用此API来手动生成的Cookie和形式令牌,你需要调用AntiForgery.Validate的the corresponding overload为了验证令牌。

+3

我知道sideeffect,但我的问题是关于没有任何HTML表单复杂的JS应用。我发送ajax请求来获取表单标记和cookie标记,之后,我只是发送我的ajax请求与表单标记。但是现在我不知道如何设置cookie和获取表单标记而没有html垃圾分析的简单方法。 – 2013-02-21 09:02:41

+3

我发现在'HtmlHelper'中暴露生成的防伪表单标记的'Name'和'Value'对于像JavaScript这样的ExtJs框架是必须的。我不能简单地写HTML元素,而是需要扩展ExtJs组件并处理客户端模型或使用现有的只需要名称和值而不是整个输入元素的Hiddenfield ...'AntiForgery.GetTokens':require玩弄cookie; 'AntiForgery.Validate':已经由'[ValidateAntiForgeryToken]'属性内部调用...我最终使用OP HtmlHelper扩展来获取名称和值。 – CallMeLaNN 2013-05-22 03:11:24

10

我意识到这个问题很陈旧,但基于我在这里读到的内容,我想出了一个相当简单的解决方案,似乎对我很有用。我在使用部分模板的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)