2017-08-20 4 views
0

J'ai un nom de ActionFilter de Log que log IP de l'utilisateur et d'autres détails lors de la connexion de l'utilisateur sur le site afin de faire ce travail que j'écris code suivant:état d'authentification dans ASP.NET MVC ActionFilters

public class Log : ActionFilterAttribute 
{ 
    public IAppUserManager UserManager { get; set; } 

    public override void OnResultExecuted(ResultExecutedContext filterContext) 
    { 
     var status = filterContext.Controller.TempData.Any(pair => pair.Key == "status" && (int)pair.Value == 200); 

     if (filterContext.HttpContext.User != null && filterContext.HttpContext.User.Identity.IsAuthenticated && status) 
     { 
      var logIp = new AddIpAddressDto() 
      { 
       Browser = filterContext.HttpContext.Request.GetBrowser(), 
       Ip = filterContext.HttpContext.Request.GetIp(), 
       Os = filterContext.HttpContext.Request.UserAgent.GetOs(), 
       UrlReferrer = filterContext.HttpContext.Request.UrlReferrer?.ToString(), 
       UserId = Guid.Parse(filterContext.HttpContext.User.Identity.GetUserId()), 
       UserName = filterContext.HttpContext.User.Identity.GetUserName(), 
      }; 
      UserManager.Log(logIp); 
     } 
     base.OnResultExecuted(filterContext); 
    } 
} 

cette code travail lorsque filterContext.HttpContext.User.Identity.IsAuthenticated est ture.

Le filtre Log déclare sur l'action de connexion:

[AllowAnonymous] 
[Route("sign-in", Name = "signInRoute")] 
[HttpPost, ValidateAntiForgeryToken] 
[Log] 
public virtual async Task<ActionResult> Login(LoginDto login, string returnTo) 
{ 
    var signInStatus = await _signInManager 
     .PasswordSignInAsync(user.UserName, login.Password, login.RememberMe, true) 
      .ConfigureAwait(false); 

    switch (signInStatus) // is Success 
    { 
     case SignInStatus.Success: 
       TempData["status"] = 200; 
       return RedirectToLocal(returnTo); 
     case SignInStatus.LockedOut: 
       // todo return time of louckout 
       break; 
     case SignInStatus.RequiresVerification: 
       return RedirectToAction("ConfirmEmail"); 
     case SignInStatus.Failure: 
       return View(CleanPassWordInLogin(login)); 
      default: 
       throw new ArgumentOutOfRangeException(); 
    } 
} 

Action Connexion fonctionne très bien et est signInStatussuccès mais après action excuted IsAuthenticated est faux.

Pour résoudre ce problème, je l'ai essayé les éléments suivants:

  • Utilisé HttpContext.Current.GetOwinContext();
  • défini par le code suivant dans IoC (de StructureMap 4.5.2)

    config.For<HttpContextBase>().Use(() => new HttpContextWrapper(HttpContext.Current));

  • Essayé OnActionExecuted, OnActionExecuting, OnResultExecuting

  • occasion IAuthenticationManager dans Identity 2,0

Comment puis-je résoudre ce problème?

Répondre

1

Après l'exécution de SignInManager.PasswordSignInAsync, le cookie d'authentification sera créé avec les informations utilisateur. Donc User.Identity informations seront remplies par les revendications du cookie d'authentification, qui ne sont pas encore analysées (ce cookie sera analysé dans la deuxième requête au serveur, pas dans la même demande de connexion). C'est pourquoi vous ne pouvez pas utiliser User.Identity juste après PasswordSignInAsync. À ce moment précis, vous n'avez qu'une seule option pour trouver l'ID utilisateur:

string userId = UserManager.FindByName(model.Email)?.Id;