C# 使用自定义ActionFilterAttribute注销MVC 5中的用户

C# 使用自定义ActionFilterAttribute注销MVC 5中的用户,c#,asp.net-mvc-5,session-cookies,actionfilterattribute,userprincipal,C#,Asp.net Mvc 5,Session Cookies,Actionfilterattribute,Userprincipal,我有一个自定义ActionFilterAttribute,确保会话中的值与数据库中的值匹配。如果值不匹配,它会将用户重定向到AccountController上的登录操作 public class CheckSessionAttribute : ActionFilterAttribute, IAuthenticationFilter { public override void OnActionExecuting(ActionExecutingContext filterContext)

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

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
我在登录操作中设置了一个断点,可以看到User.Identity.Name在调用SignOutAndKillSession()前后仍然设置为正在注销的用户。我相信这就是导致页面呈现时生成错误AntiForgeryToken的原因

有人能帮我找出在注销用户时如何清除用户主体吗


感谢所有遇到此问题的人,我通过在CheckSessionAttribute中使MVC 5创建的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);
        }
    }
}