2015-09-09 3 views
0

En utilisant l'authentification par formulaire, je remplis le champ UserData avec un objet CustomIdentitySerializer sérialisé.Pourquoi la redirection de connexion échoue-t-elle dans MVC lors de l'utilisation de FormsAuthentication CustomIdentity et de la mise à jour de AuthTicket UserData?

L'utilisateur se connecte, et j'ai vérifié que Membership.ValidateUser() fonctionne très bien.

Je commence alors peuplant l'objet CustomIdentitySerializer et l'envoyer à une méthode UpdateAuthenticationTicket statique dans une UserContext statique classe pour tester la conservation des données - après le login()/User.Identity.IsAuthenticated:

// set auth ticket 
UserContext.UpdateAuthenticationTicket(user.Username, serializeModel); 

// get custom identity - user properties 
string userName = UserContext.Identity.UserName; 

// reset login attempts 
Session["_LoginAttempts"] = 0; 

return RedirectToAction("Index", "Dashboard"); 

Méthode d'assistance:

/// <summary> 
/// As we will want to update the UserData portion of the cookie while the 
/// user is logged, this will be reused 
/// 
/// Auth Ticket/Cookie's UserData property is the CustomIdentitySerializer object 
/// </summary> 
/// <param name="userName"></param> 
/// <param name="userData"></param> 
public static void UpdateAuthenticationTicket(string userName, CustomIdentitySerializer userData) 
{ 
    //var authUser = GetUser(userName); 
    JavaScriptSerializer serializer = new JavaScriptSerializer(); 
    string userDataSerialized = serializer.Serialize(userData); 

    FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(1, 
     userName, 
     DateTime.Now, 
     DateTime.Now.AddMinutes(30), 
     false, 
     userDataSerialized, 
     FormsAuthentication.FormsCookiePath); 

     // encrypt the ticket 
     string encTicket = FormsAuthentication.Encrypt(authTicket); 

     // create/set the cookie 
     HttpCookie faCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket); 
     HttpContext.Current.Response.Cookies.Add(faCookie); 

    } 

userData peut changer à travers l'heure de l'utilisateur sur le site, nous allons donc réutiliser cette méthode chaque fois que ces données doivent être modifiées.

Dans Global.asax.cs J'ai:

protected void Application_AuthenticateRequest(object sender, EventArgs e) 
{ 
    HttpCookie authCookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName]; 

    if (authCookie != null) 
    { 
     FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value); 

     var fromsIdentity = new FormsIdentity(authTicket); 

     // Get the GenericPrincipal identity 
     IIdentity ui = HttpContext.Current.User.Identity; 

     CustomIdentity customIdentity = new CustomIdentity(ui.Name); 
     CustomPrincipal customPrincipal = new CustomPrincipal(ui.Name); 

     string userData = ((FormsIdentity)(Context.User.Identity)).Ticket.UserData; 

     // Set custom principal 
     HttpContext.Current.User = customPrincipal; 
    } 
} 

/// <summary> 
/// Since we set current project and other custom user fields through the user experience, 
/// these are saved in the authticket/cookie's UserData field as a CustomIdentitySerializer object type 
/// </summary> 
/// <param name="sender"></param> 
/// <param name="e"></param> 
protected void Application_PostAuthenticateRequest(Object sender, EventArgs e) 
{ 
    if (HttpContext.Current.User.Identity.IsAuthenticated) 
    { 
     HttpCookie authCookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName]; 

     if (authCookie != null) 
     { 
      // get the current cookie 
      FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value); 
      var fromsIdentity = new FormsIdentity(authTicket); 
      JavaScriptSerializer serializer = new JavaScriptSerializer(); 
      CustomIdentitySerializer userData = serializer.Deserialize<CustomIdentitySerializer>(authTicket.UserData); 

      CustomPrincipal customPrincipal = new CustomPrincipal(HttpContext.Current.User.Identity.Name); 
      customPrincipal.CustomIdentity.FirstName = userData.FirstName; 
      customPrincipal.CustomIdentity.LastName = userData.LastName; 
      customPrincipal.CustomIdentity.CurrentProject = userData.CurrentProject; 

      HttpContext.Current.User = customPrincipal; 
     } 
    } 
} 

Je pense que cela peut avoir à faire avec le fournisseur principal ne sont pas correctement défini ou réécrite. Après la définition de la valeur de cookie, la touche Application_AuthenticateRequest est atteinte, suivie par Application_PostAuthenticateRequest. Ce processus se produit deux fois, puis revient à la page de connexion.

Il semble que le code Application_AuthenticateRequest ne soit pas utile, car je n'y ai pas défini de propriétés.

Le problème est que, une fois que l'utilisateur est connecté, le RedirectToAction revient à http://localhost:1982/Account/Login?ReturnUrl=%2fDashboard plutôt qu'à la page appropriée.

Y a-t-il des problèmes prévisibles dans la mise à jour du cookie de la classe UserContext statique?

Une assistance sur ce s'il vous plaît sur la façon de nettoyer cela et de travailler?

Merci.

- MISE À JOUR -

En regardant l'objet authCookie dans Application_PostAuthenticateRequest, Expires est réglé sur {1/1/0001 12:00:00 AM}. Quoi qu'il en soit, l'expiration du cookie authTicket est correcte - 30 minutes après la création. Donc, ce cookie est là.

Quoi d'autre?

- MISE À JOUR -

En regardant la version cookie, je remarque une différence. Dès que je mets le cookie dans UpdateAuthenticationTicket, je vérifie:

authTicket.Version = 

et

FormsAuthentication.Decrypt (HttpContext.Current.Request.Cookies [FormsAuthentication.FormsCookieName] .Value).Version = 2

Vous ne savez pas pourquoi il existe deux versions, si quelqu'un peut expliquer cela aussi? J'ai essayé de régler le cookie avec version = 2 - même problème.

+0

Avez-vous vérifié que le cookie est configuré (en vérifiant les cookies de réponse) et envoyé au navigateur (en vérifiant ce que le navigateur a pour les cookies)? –

+0

Oui, j'ai vérifié que le nom de cookie par défaut '.ASPXAUTH' est en train d'être défini - je le vois dans le navigateur. Je le mets avec 'HttpContext.Current.Response.Cookies.Add (faCookie);' – ElHaix

+0

Dans 'UpdateAuthenticationTicket' j'ai également ajouté 'FormsAuthentication.SetAuthCookie (userName, false);' - pas de changement. – ElHaix

Répondre

0

En plus de déconner avec cela, je me suis déplacé le code au-dessus de Application_PostAuthenticateRequest à Application_AuthenticateRequest et tout semble fonctionner correctement maintenant:

protected void Application_AuthenticateRequest(object sender, EventArgs e) 
{ 

    HttpCookie authCookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName]; 

    if (authCookie != null && HttpContext.Current.User.Identity.IsAuthenticated) 
    { 

     if (authCookie != null) 
     { 
      // get the current cookie 
      FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value); 
      var fromsIdentity = new FormsIdentity(authTicket); 
      JavaScriptSerializer serializer = new JavaScriptSerializer(); 
      CustomPrincipal customPrincipal = new CustomPrincipal(HttpContext.Current.User.Identity.Name); 
      CustomIdentitySerializer userData = serializer.Deserialize<CustomIdentitySerializer>(authTicket.UserData); 
      if (userData != null) 
      { 
       customPrincipal.CustomIdentity.FirstName = userData.FirstName; 
       customPrincipal.CustomIdentity.LastName = userData.LastName; 
       customPrincipal.CustomIdentity.CurrentProject = userData.CurrentProject; 
      } 

      HttpContext.Current.User = customPrincipal; 
     } 
    } 
} 

Quelqu'un peut-il s'il vous plaît expliquer pourquoi il en est, comme tant de références que je ont trouvé pour cela indiquer de mettre ce code dans Application_PostAuthenticateRequest ???