【问题标题】:Log Out a User in MVC 5 Using a Custom ActionFilterAttribute使用自定义 ActionFilterAttribute 在 MVC 5 中注销用户
【发布时间】:2015-01-04 12:10:37
【问题描述】:

我有一个自定义的 ActionFilterAttribute,它可以确保 Session 中的值与数据库中的值匹配。如果值不匹配,它会将用户重定向到 AccountController 上的 Login 操作。

public class CheckSessionAttribute : ActionFilterAttribute, IAuthenticationFilter
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (filterContext.ActionDescriptor.GetCustomAttributes(typeof(AllowAnonymousAttribute), false).Any())
        {
            // If the action allows Anonymous users, no need to check the session
            return;
        }

        var session = filterContext.RequestContext.HttpContext.Session;
        var userName = filterContext.RequestContext.HttpContext.User.Identity.Name;

        var userStore = new ApplicationUserStore(new IdentityDb());
        var userManager = new ApplicationUserManager(userStore);

        var user = userManager.FindByNameAsync(userName).Result;

        if (userName == null || user == null || session == null || session["ActiveSessionId"] == null || 
            session["ActiveSessionId"].ToString() != user.ActiveSessionId.ToString())
        {
            session.RemoveAll();
            session.Clear();
            session.Abandon();

            filterContext.Result = new RedirectToRouteResult(
                new RouteValueDictionary(new
                {
                    action = "Login",
                    controller = "Account"
                }
            ));         
        }

        base.OnActionExecuting(filterContext);
    }
}

[Authorize]
public class AccountController : Controller
{
    [AllowAnonymous]
    public ActionResult Login(string returnUrl)
    {
        SignOutAndKillSession();
        ViewBag.ReturnUrl = returnUrl;
        return View();
    }

    private void SignOutAndKillSession()
    {
        AuthenticationManager.SignOut();
        Session.RemoveAll();
        Session.Clear();
        Session.Abandon();
    }
}

当我被重定向到登录操作后再次尝试登录时,出现以下异常:

The provided anti-forgery token was meant for a different claims-based user than the current user

我在 Login 操作中设置了一个断点,可以看到在调用 SignOutAndKillSession() 之前和之后,User.Identity.Name 仍然设置为正在注销的用户。我相信这是导致页面呈现时生成不正确的 AntiForgeryToken 的原因。

有人可以帮助我了解如何在注销用户时清除用户主体吗?

谢谢

【问题讨论】:

    标签: c# asp.net-mvc-5 session-cookies actionfilterattribute userprincipal


    【解决方案1】:

    对于遇到此问题的任何人,我通过使 MVC 5 在 CheckSessionAttribute 中创建的 cookie 过期来解决它。我还将属性从 ActionFilterAttribute 更改为 IAuthorizationFilter 属性

    public class CheckSessionAttribute : FilterAttribute, IAuthorizationFilter
    {
        public void OnAuthorization(AuthorizationContext filterContext)
        {
            if (filterContext.ActionDescriptor.GetCustomAttributes(typeof(AllowAnonymousAttribute), false).Any())
            {
                // If the action allows Anonymous users, no need to check the session
                return;
            }
    
            var session = filterContext.RequestContext.HttpContext.Session;
            var userName = filterContext.RequestContext.HttpContext.User.Identity.Name;
    
            var userStore = new ApplicationUserStore(new IdentityDb());
            var userManager = new ApplicationUserManager(userStore);
    
            var user = userManager.FindByNameAsync(userName).Result;
    
            if (userName == null || user == null || session == null || session["ActiveSessionId"] == null ||
                session["ActiveSessionId"].ToString() != user.ActiveSessionId.ToString())
            {
                session.RemoveAll();
                session.Clear();
                session.Abandon();
    
                ExpireCookie("ASP.NET_SessionId", filterContext);
                ExpireCookie("__RequestVerificationToken", filterContext);
                ExpireCookie(".AspNet.ApplicationCookie", filterContext);
    
                filterContext.Result = new RedirectToRouteResult(
                    new RouteValueDictionary(new
                    {
                        action = "Login",
                        controller = "Account"
                    }
                ));
            }
    
            return;
        }
    
        private void ExpireCookie(string name, AuthorizationContext filterContext)
        {
            if (filterContext.RequestContext.HttpContext.Request.Cookies[name] != null)
            {
                filterContext.RequestContext.HttpContext.Response.Cookies[name].Value = string.Empty;
                filterContext.RequestContext.HttpContext.Response.Cookies[name].Expires = DateTime.Now.AddMonths(-20);
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2014-12-24
      • 2019-08-30
      • 1970-01-01
      • 1970-01-01
      • 2016-08-14
      • 2014-01-06
      • 1970-01-01
      • 1970-01-01
      • 2014-03-03
      相关资源
      最近更新 更多