如何取消验证当前用户ASP.net mvc Identity
如何取消验证当前用户ASP.net mvc Identity
当用户进入我的网站时,他们会看到登录页面。一旦成功登录,他们可以注销并允许其他用户登录。然而,如果用户在已登录的情况下点击返回按钮,会返回到登录页面。此时,新用户将无法登录,我会收到一个防伪令牌错误。我尝试了在登录页面注销任何用户的方法。我尝试了不同的注销方式。我甚至尝试了Session.Abandon();
\nAccount controller:\n
// GET: /Account/Login [AllowAnonymous] public ActionResult Login(string returnUrl) { EnsureLoggedOut(); ViewBag.ReturnUrl = returnUrl; // Store the originating URL so we can attach it to a form field var viewModel = new LoginViewModel { ReturnUrl = returnUrl }; return View(viewModel); } // POST: /Account/Login [HttpPost] [AllowAnonymous] [ValidateAntiForgeryToken] public async TaskLogin(LoginViewModel model, string returnUrl) { if (!ModelState.IsValid) { return View(model); } ApplicationUser user = new ApplicationUser(); try { user = DBcontext.Users.Where(u => u.Email.Equals(model.Email)).Single(); // where db is ApplicationDbContext instance } catch (InvalidOperationException) { // the user is not exist return View("The user does not exist."); } var result = await SignInManager.PasswordSignInAsync(user.UserName, model.Password, model.RememberMe, shouldLockout: false); SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: false); switch (result) { case SignInStatus.Success: return RedirectToLocal(returnUrl); case SignInStatus.LockedOut: return View("Lockout"); case SignInStatus.RequiresVerification: return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = model.RememberMe }); case SignInStatus.Failure: default: ModelState.AddModelError("", "Invalid login attempt."); return View(model); } } // POST: /Account/LogOff [HttpPost] [ValidateAntiForgeryToken] public ActionResult LogOff() { Session.Abandon(); AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie); return RedirectToAction("Index", "Home"); } private ActionResult RedirectToLocal(string returnUrl) { if (Url.IsLocalUrl(returnUrl)) { return Redirect(returnUrl); } return RedirectToAction("Index", "Home"); } }
\nLogin View:\n@model LoginViewModel\n@{ViewBag.PageId = \"extr-page\";\nViewBag.PageClass = \"animated fadeInDown\";}\n@section topright{ Need an account? Create account \n}\n @{ Html.RenderPartial(\"_LoginText\"); }\n
\n @{ Html.RenderPartial(\"_SocialMedia\"); }\n\n我希望当用户点击返回按钮并进入登录页面时,上一个用户会被注销。
问题出现的原因是因为在ASP.NET MVC Identity中,当用户点击后退按钮返回到登录页面时,之前用户的cookie并没有被销毁。这个问题在Chrome中出现,但在IE中没有出现。解决方法是在登录页面的Get方法上添加OutputCache特性,设置NoStore为true,Duration为0,Location为OutputCacheLocation.None。同时,在登录页面显示后,调用一个方法来登出用户,并清除用户的认证信息和会话。为了确保用户不保留任何认证信息,还需要在此方法中清除principal。以下是解决问题的代码:
问题1:
在Login的Get方法中添加OutputCache特性,代码如下:
[AllowAnonymous] [OutputCache(NoStore = true, Duration = 0, Location = OutputCacheLocation.None)] public ActionResult Login(string returnUrl) { EnsureLoggedOut(); // Store the originating URL so we can attach it to a form field var viewModel = new LoginViewModel { ReturnUrl = returnUrl }; return View(viewModel); }
问题2:
在EnsureLoggedOut方法中添加代码来清除principal,代码如下:
private void EnsureLoggedOut() { if (AuthenticationManager.User.Identity.IsAuthenticated) { //SignOut the current user AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie, DefaultAuthenticationTypes.ExternalCookie); Session.Abandon(); // Second we clear the principal to ensure the user does not retain any authentication HttpContext.User = new GenericPrincipal(new GenericIdentity(string.Empty), null); } }
问题的出现原因是页面被缓存,为匿名用户生成的防伪令牌无法与已登录用户进行验证。
解决方法是在登录的GET请求上添加OutputCache
(在Core中为ResponseCache
)属性,并设置正确的头部信息以禁止页面缓存。
[OutputCache(NoStore = true, Duration = 0, Location = OutputCacheLocation.None)] public ActionResult Login(string returnUrl) { ... }
在登录页面检查User.IsAuthenticated
,如果为true
,则防伪令牌仍会引发错误。尝试if(User.IsAuthenticated){ EnsureLoggedOut(); RedirectToAction("Login"); }
,这样会生成一个新的请求。
这是一个很好的做法。非常感谢您的帮助。我已经在下面发布了解决方案。