如何取消验证当前用户ASP.net mvc Identity

19 浏览
0 Comments

如何取消验证当前用户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 Task Login(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

\n Sign In\n

\n @Html.HiddenFor(m => m.ReturnUrl)\n @Html.AntiForgeryToken()\n @Html.ValidationBootstrap()\n

\n

\n \n \n

\n

\n \n \n Forgot password?\n

\n

\n \n

\n

\n

\n \n

\n

\n @{ Html.RenderPartial(\"_SocialMedia\"); }\n\n我希望当用户点击返回按钮并进入登录页面时,上一个用户会被注销。

0
0 Comments

问题出现的原因是因为在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);
    }
}

0
0 Comments

问题的出现原因是页面被缓存,为匿名用户生成的防伪令牌无法与已登录用户进行验证。

解决方法是在登录的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"); },这样会生成一个新的请求。

这是一个很好的做法。非常感谢您的帮助。我已经在下面发布了解决方案。

0