我有一个表格帖子,一直给我一个反伪造令牌错误.
这是我的表格:
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
@Html.EditorFor(m => m.Email)
@Html.EditorFor(m => m.Birthday)
<p>
<input type="submit" id="Go" value="Go" />
</p>
}
Run Code Online (Sandbox Code Playgroud)
这是我的行动方法:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Join(JoinViewModel model)
{
//a bunch of stuff here but it doesn't matter because it's not making it here
}
Run Code Online (Sandbox Code Playgroud)
这是web.config中的machineKey:
<system.web>
<machineKey validationKey="mykey" decryptionKey="myotherkey" validation="SHA1" decryption="AES" />
</system.web>
Run Code Online (Sandbox Code Playgroud)
这是我得到的错误:
A required anti-forgery token was not supplied or was invalid.
Run Code Online (Sandbox Code Playgroud)
我已经读过,更改HttpContext上的用户会使令牌无效,但这不会发生在这里.我的Join操作上的HttpGet只返回视图:
[HttpGet]
public ActionResult Join()
{
return this.View();
}
Run Code Online (Sandbox Code Playgroud)
所以我不确定发生了什么.我一直在搜索,似乎所有东西都表明它是机器键更改(应用程序周期)或用户/会话更改.
还有什么可以继续?我该如何解决这个问题?
ASP.NET MVC的AntiForgeryToken机制基于当前HttpContext.User.它在您调用时使用该值来构造令牌Html.AntiForgeryToken().基本上没关系(请参阅此处最后一段中的解释)但是当您通过Ajax调用登录时会出现问题.
在我的代码中,当用户登录时,凭据在Ajax中作为Json对象发送(AntiForgeryToken隐藏字段值也在Json内发送),服务器验证用户,应用FormsAuthentication.SetAuthCookie(),并返回Json结果包含一些用户特定的数据.这样,我可以在登录时避免整页刷新.
问题是现在每个后续的Ajax请求都会失败ValidateAntiForgeryTokenAttribute,因为它现在需要一个与防伪cookie不兼容的防伪标记.
如何将有效的防伪标记放入客户端的隐藏字段中,以便登录后的每个Json请求都会成功?
我试图手动获取一个新的隐藏字段标记(AntiForgery.GetHtml()在操作上使用,提取标记字符串本身,将其返回到Json中的客户端并在JavaScript中手动将其放置在防伪隐藏字段中)但它不起作用 - ValidateAntiForgeryTokenAttribute服务器上的后续Ajax调用失败.事实上,每次调用AntiForgery.GetHtml()(基本上是Html.AntiForgeryToken()帮助程序所做的)都会产生一个不同的令牌,这会使前一个令牌失效.
我也试着设置HttpContext.User = new GenericPrincipal(new GenericIdentity(email), null);详见这里,但它不工作.
注意: 由于我的具体情况,此解决方案对我不起作用:Ajax 登录更改服务器上的用户身份,因此登录前生成的每个令牌都无效; 此解决方案也不适用,因为它解决了不同的问题.
我们有一个使用MVC3的网站和一个完全不依赖于表单身份验证的自定义身份验证方法 - 至少从我能说的方面来说.在web.config中我们设置
<authentication mode="None"></authentication>
Run Code Online (Sandbox Code Playgroud)
我们永远不会在代码中的任何地方使用/设置HttpContext.User.问题是在某些情况下使用@ Html.AntiForgeryToken()时,用户会收到以下错误消息:
A required anti-forgery token was not supplied or was invalid
Run Code Online (Sandbox Code Playgroud)
我们使用以下代码集中了OnAuthorization中的所有反伪造检查:
if (String.Compare(filterContext.HttpContext.Request.HttpMethod, "post", true) == 0)
{
var forgery = new ValidateAntiForgeryTokenAttribute();
forgery.OnAuthorization(filterContext);
}
Run Code Online (Sandbox Code Playgroud)
这就是异常发生的地方.我们在web.config中定义了一个machineKey,以防止在应用程序池回收时生成新密钥.这并没有解决问题.
接下来我们认为客户的浏览器可能没有发送cookie.我们开始记录cookie并注意到在某些情况下会发送RequestVerificationToken_Lw cookie,但在其他情况下则不会 - 尽管其他cookie(如Google Analytics提供的cookie)也会被发送.可能是浏览器中的某些内容正在剥离一些cookie并让其他人进入?
似乎反伪造令牌依赖于表单身份验证.是这样的吗?任何方式在不以可靠的方式使用表单身份验证时继续使用AntiForgeryToken.请记住,我上面描述的方法适用于超过90%的情况,但我们无法确定为什么它对某些人不起作用.
思考?
谢谢!