Asp.net mvc MVC3反伪造代币问题
我正在尝试为我的MVC3应用程序实现AntiForgeryToken。设置FormAuthentication cookie后,我遇到AntiForgeryToken问题。这里有一个简单的例子来解释我的问题 我有一个具有以下操作方法的主控制器:Asp.net mvc MVC3反伪造代币问题,asp.net-mvc,asp.net-mvc-3,antiforgerytoken,Asp.net Mvc,Asp.net Mvc 3,Antiforgerytoken,我正在尝试为我的MVC3应用程序实现AntiForgeryToken。设置FormAuthentication cookie后,我遇到AntiForgeryToken问题。这里有一个简单的例子来解释我的问题 我有一个具有以下操作方法的主控制器: public class HomeController : Controller { public ActionResult Logon() { return View(); } [HttpPost]
public class HomeController : Controller
{
public ActionResult Logon()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Logon(string userName, string password)
{
FormsAuthentication.SetAuthCookie(userName, false);
return View("About");
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult About(FormCollection form)
{
return View("PageA");
}
}
这是我的登录和关于视图的信息:
Logon.cshtml:
@using (Html.BeginForm("Logon", "Home"))
{
@Html.AntiForgeryToken()
<label> UserName :</label>
<input name = "userName" type="text"/>
<br />
<label> Password :</label>
<input name = "password" type="password"/>
<br />
<br />
<input type="submit" value="LogOn" />
}
@使用(Html.BeginForm(“登录”、“主页”))
{
@Html.AntiForgeryToken()
用户名:
密码:
}
关于.cshtml
@using (Html.BeginForm("About", "Home"))
{
@Html.AntiForgeryToken()
<p> This is conent of page About</p>
<input name = "moreInfo" type="text"/>
<input type="submit" value="SubmitAbout" />
}
@使用(Html.BeginForm(“关于”,“家”))
{
@Html.AntiForgeryToken()
这是第页的内容
}
我对“登录”post方法没有问题。它正在验证antiforgerytoken并呈现有关视图的信息。有趣的是,当我在“关于”视图上发布“我收到错误”时,所需的防伪令牌未提供或无效
有人能指出我做错了什么吗
感谢您的帮助。我似乎记得,一旦您登录,您的令牌现在已不同,因为您的用户名已更改此令牌,因此不再有效。我会再检查一遍,但几乎可以肯定我以前遇到过这种情况 但是,在上面的代码中,如果使用此模式,您将遇到其他问题。Post操作通常不用于显示视图,除非出现异常/验证错误,并且您正在重新显示页面。一般来说,你会重定向。我看到有人在上面的评论中提到了这一点,他们是正确的 但这并不意味着你不应该使用这些操作,但要小心在登录时忽略这些操作。这篇之前的文章暗示了用户名与令牌的使用:
我似乎记得,一旦你登录你的令牌现在是不同的,因为你的用户名我相信改变了这个令牌,因此将不再有效。我会再检查一遍,但几乎可以肯定我以前遇到过这种情况 但是,在上面的代码中,如果使用此模式,您将遇到其他问题。Post操作通常不用于显示视图,除非出现异常/验证错误,并且您正在重新显示页面。一般来说,你会重定向。我看到有人在上面的评论中提到了这一点,他们是正确的 但这并不意味着你不应该使用这些操作,但要小心在登录时忽略这些操作。这篇之前的文章暗示了用户名与令牌的使用:
如果请求中存在同名的cookie,则AntiForgeryToken帮助程序不会向响应添加任何cookie。此外,AntiForgeryToken帮助程序使用Principal.Identity.Name返回隐藏字段的值
AntiForgeryData formToken = new AntiForgeryData(cookieToken) {
Salt = salt,
Username = AntiForgeryData.GetUsername(httpContext.User)
};
因此,当您的登录视图使用Html.AntiForgeryToken时,将在响应和具有相同值的隐藏字段上设置一个新cookie。当您的登录视图使用隐藏字段发布此cookie时,不会引发异常,因为请求cookie和隐藏字段值都匹配。但是在About视图的情况下,不会向响应中添加额外的cookie,但是由于IIdentty,将为helper返回一个新的隐藏值。所以,当您发布关于操作的帖子时,将引发异常,因为cookie和隐藏值不匹配
这可能是AntiForgeryToken实现中的错误。如果请求中存在同名cookie,则AntiForgeryToken帮助程序不会向响应添加任何cookie。此外,AntiForgeryToken帮助程序使用Principal.Identity.Name返回隐藏字段的值
AntiForgeryData formToken = new AntiForgeryData(cookieToken) {
Salt = salt,
Username = AntiForgeryData.GetUsername(httpContext.User)
};
因此,当您的登录视图使用Html.AntiForgeryToken时,将在响应和具有相同值的隐藏字段上设置一个新cookie。当您的登录视图使用隐藏字段发布此cookie时,不会引发异常,因为请求cookie和隐藏字段值都匹配。但是在About视图的情况下,不会向响应中添加额外的cookie,但是由于IIdentty,将为helper返回一个新的隐藏值。所以,当您发布关于操作的帖子时,将引发异常,因为cookie和隐藏值不匹配
这可能是AntiForgeryToken实现中的一个错误。我做了一些测试,并确定即使在调用
FormsAuthentication.SetAuthCookie(…)
之后,httpContext.User.Identity.Name在请求期间仍然为空
因此,要解决此问题,您需要手动将当前用户设置为:
FormsAuthentication.SetAuthCookie(email, true);
this.HttpContext.User = new GenericPrincipal(new GenericIdentity(email), null);
这将设置调用Html.AntiForgeryToken()
时使用的正确的用户
请注意,对于正常的PRG模式网站,此代码不是必需的,因为在重定向之后,将加载正确的用户
另外,由于您的Logon
方法需要有效的用户名和密码,因此它实际上不易受到CSRF攻击,因此您可能不需要在该方法上使用ValidateAntiForgeryToken
。也许这就是为什么AntiForgeryToken依赖于用户名。CSRF攻击通常只利用已经通过身份验证的用户。我做了一些测试,并确定即使在调用FormsAuthentication.SetAuthCookie(…)
之后,问题是httpContext.User.Identity.Name在请求期间仍然为空
因此,要解决此问题,您需要手动将当前用户设置为:
FormsAuthentication.SetAuthCookie(email, true);
this.HttpContext.User = new GenericPrincipal(new GenericIdentity(email), null);
这将设置调用Html.AntiForgeryToken()
时使用的正确的用户
请注意,对于正常的PRG模式网站,此代码不是必需的,因为在重定向之后,将加载正确的用户
另外,由于您的Logon
方法需要有效的用户名和密码,因此它实际上不易受到CSRF攻击,因此您可能不需要在该方法上使用ValidateAntiForgeryToken
。也许这就是为什么AntiForgeryToken依赖于用户名。CSRF攻击通常是