2

У меня есть собственный ActionFilterAttribute, который гарантирует, что значение в сеансе соответствует значению в базе данных. Если значения не совпадают, он перенаправляет пользователя на действие «Вход» в AccountController.Выйти из пользователя в MVC 5 Использование пользовательского ActionFilterAttribute

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. Имя по-прежнему настроено на пользователя, который выходит из системы, до И после вызова SignOutAndKillSession(). Я считаю, что именно это приводит к созданию некорректного AntiForgeryToken при создании страницы.

Может ли кто-нибудь помочь мне узнать, как очистить пользователя-пользователя при выходе из системы?

Благодаря

ответ

1

Для всех, кто натыкается на этот вопрос, я решил ее истекающий куки, созданные MVC 5 внутри CheckSessionAttribute. Я также изменил атрибут из атрибута 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); 
     } 
    } 
} 
Смежные вопросы