使用MVC 5.1.1/VS 2013 Professional/.Net 4.5
我偶尔会收到错误(来自本地主机和生产 IIS 7):
System.Web.Mvc.HttpAntiForgeryException: The anti-forgery cookie token and form field token do not match.
问题似乎是当我注销用户时,有时当我再次进行身份验证时,就会出现错误。
我的验证码看起来像这样:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginViewModel model)
{
if (ModelState.IsValid)
{
var user = _uow.UserRepository.FindLogin(model.Email, model.Password);
if (user != null)
{
var claims = new List<Claim>();
claims.Add(new Claim(ClaimTypes.Email, user.Email));
claims.Add(new Claim(ClaimTypes.NameIdentifier, user.UserID.ToString()));
claims.Add(new Claim(ClaimTypes.Role, user.UserLevel.ToString()));
var id = new ClaimsIdentity(claims, DefaultAuthenticationTypes.ApplicationCookie);
var ctx = Request.GetOwinContext();
var authenticationManager = ctx.Authentication;
authenticationManager.SignIn(new AuthenticationProperties { IsPersistent = true }, id);
}
else
{
ModelState.AddModelError("", "Invalid Email Address or Password.");
}
}
return View(model);
}
使用注销方法更新:
[HttpGet]
[AllowAnonymous]
public ActionResult LogOut(LoginViewModel model)
{
Session.Abandon();
return SignOffUser();
}
private ActionResult SignOffUser()
{
AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
return RedirectToAction("Index", "Home");
}
注销表单视图
@if (Request.IsAuthenticated)
{
using (Html.BeginForm(null, null, FormMethod.Post, new {id = "logoutForm", @class = "navbar-right"}))
{
@Html.AntiForgeryToken()
....
}
}
您可能需要注意的另一件事是,在注销页面上,您无需验证伪造令牌。
尝试改变这个:
[HttpGet]
[AllowAnonymous]
public ActionResult LogOut(LoginViewModel model)
{
对此
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult LogOut(LoginViewModel model)
{
我敢打赌,页面上的令牌正在发生变化,并且由于它未经验证,ASP.NET 不知道它是否真正正确。
E:刚刚注意到,它实际上应该是注销时的httppost
显示您的注销表单(视图)。
如果您从视图中调用控制器中的注销方法,但在表单内没有生成 antiforgerytoken,则会发生这种情况。
您的表格应如下所示
@using(Html.BeginForm("Action","Controller"))
{
@Html.antiforgerytoken()
....
}
那么您通过视图调用的操作应该如下所示
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult MyAction()
{
return content("hello user! Antiforgerytoken has been validated1");
}
PS:无论你的表单调用什么操作方法,如果你想要有需要验证的防伪令牌,那么表单和操作方法应该像我上面提到的那样。
尝试在 web.config 中(在 system.web 下)明确设置机器密钥:
<machineKey validationKey="971E32D270A381E2B5954ECB4762CE401D0DF1608CAC303D527FA3DB5D70FA77667B8CF3153CE1F17C3FAF7839733A77E44000B3D8229E6E58D0C954AC2E796B" decryptionKey="1D5375942DA2B2C949798F272D3026421DDBD231757CA12C794E68E9F8CECA71" validation="SHA1" decryption="AES" />
这是一个生成唯一 Machnie 密钥的网站 http://www.developerfusion.com/tools/generatemachinekey/