2

Dies ist die Login-Funktion (nachdem ich den Benutzernamen und das Passwort zu validieren, ich Benutzerdaten in „user“ Variable und Call-Log-Funktion laden:IsAuthenticated ist falsch! seltsame Verhalten + Bewertung Frage

public static void Login(IUser user) 
{ 
    HttpResponse Response = HttpContext.Current.Response; 
    HttpRequest Request = HttpContext.Current.Request; 

    FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, 
     user.UserId.ToString(), DateTime.Now, DateTime.Now.AddHours(12), false, 
     UserResolver.Serialize(user)); 

    HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, 
     FormsAuthentication.Encrypt(ticket)); 
    cookie.Path = FormsAuthentication.FormsCookiePath; 

    Response.Cookies.Add(cookie); 

    string redirectUrl = user.HomePage; 

    Response.Redirect(redirectUrl, true); 
} 

UserResolver ist die folgende Klasse:

public class UserResolver 
{ 
    public static IUser Current 
    { 
     get 
     { 
      IUser user = null; 
      if (HttpContext.Current.User.Identity.IsAuthenticated) 
      { 
       FormsIdentity id = (FormsIdentity)HttpContext.Current.User.Identity; 
       FormsAuthenticationTicket ticket = id.Ticket; 
       user = Desrialize(ticket.UserData); 
      } 
      return user; 
     } 
    } 

    public static string Serialize(IUser user) 
    { 
     StringBuilder data = new StringBuilder(); 
     StringWriter w = new StringWriter(data); 
     string type = user.GetType().ToString(); 
     //w.Write(type.Length); 
     w.WriteLine(user.GetType().ToString()); 
     StringBuilder userData = new StringBuilder(); 
     XmlSerializer serializer = new XmlSerializer(user.GetType()); 
     serializer.Serialize(new StringWriter(userData), user); 
     w.Write(userData.ToString()); 
     w.Close(); 
     return data.ToString(); 
    } 

    public static IUser Desrialize(string data) 
    { 
     StringReader r = new StringReader(data); 
     string typeStr = r.ReadLine(); 
     Type type=Type.GetType(typeStr); 
     string userData = r.ReadToEnd(); 
     XmlSerializer serializer = new XmlSerializer(type); 
     return (IUser)serializer.Deserialize(new StringReader(userData)); 
    } 
} 

Und die global.asax implementiert die folgenden:

void Application_PostAuthenticateRequest(Object sender, EventArgs e) 
{ 
    IPrincipal p = HttpContext.Current.User; 
    if (p.Identity.IsAuthenticated) 
    { 
     IUser user = UserResolver.Current; 
     Role[] roles = user.GetUserRoles(); 
     HttpContext.Current.User = Thread.CurrentPrincipal = 
      new GenericPrincipal(p.Identity, Role.ToString(roles)); 
    } 
} 

Erste Frage: Bin ich es richtig?

Zweite Frage - seltsame Sache! Die Benutzervariable, die ich an die Anmeldung übergebe, hat 4 Mitglieder: Benutzername, Passwort, Name, Id. Wenn UserResolver.Current ausgeführt wurde, habe ich die Benutzerinstanz erhalten. Ich entschied, die Benutzerstruktur zu ändern - ich füge ein Array von Warehouse-Objekt hinzu. Seit dieser Zeit, als UserResolver.Current (nach der Anmeldung) ausgeführt wurde, war HttpContext.Current.User.Identity.IsAuthenticated falsch und ich konnte die Benutzerdaten nicht abrufen. Wenn ich das Warehouse [] aus der Benutzerstruktur entfernt habe, ist es wieder in Ordnung und HttpContext.Current.User.Identity.IsAuthenticated wird nach der Anmeldung wahr.

Was ist der Grund für dieses seltsame Verhalten?

Antwort

3

Erster, Sie muss nicht ein HttpContext.Current von Global.asax tun. Global.asax leitet sich von HttpApplication ab. Alles, was Sie tun müssen, ist die Context Eigenschaft zu bekommen. Dies könnte dazu beitragen, den Code ein wenig sauberer zu machen.

//this is all you need in your global.asax 
    void Application_PostAuthenticateRequest(Object sender, EventArgs e) 
    { 
     if(Context.User.Identity.IsAuthenticated) 
     { 
      var user = UserResolver.Current; 
      Context.User = Thread.CurrentPrincipal = new UserWrapperPrincipal(user, Context.User.Identity); 
     } 
    } 

    //this helper class separates the complexity 
    public class UserWrapperPrincipal: IPrincipal, IUser 
    { 
     private readonly IUser _user; 
     private readonly IIdentity _identity; 

     public UserWrapperPrincipal(IUser user, IIdentity identity) 
     { 
      _user = user; 
      _identity = identity; 
     } 

     private IList<string> RoleNames 
     { 
      get { return _user.GetUserRoles().Select(role => role.ToString()); } 
     } 

     public IIdentity Identity { get { return _identity; } } 

     public bool IsInRole(string role) { return RoleNames.Contains(role); } 

    } 

Basierend auf Ihrem Fehler, wie es scheint, das Problem, dass entweder Ihre Serialisierung Funktion oder Ihre Deserialisieren Funktion die Daten korrumpiert. Der Problembereich ist jedoch wahrscheinlich nicht diese Funktionen. Entweder gibt es ein Problem beim Serialisieren des Warehouse-Objekts (das Serialisieren komplexer Typen kann manchmal schwierig sein) oder bei der Serialisierung des tatsächlichen Arrays. Da Sie den Standard .NET XmlSerializer verwenden, gibt es einen guten Artikel zum Anpassen und Steuern der Art und Weise, wie verschiedene Objekte unter http://www.diranieh.com/NETSerialization/XMLSerialization.htm verfügbar sind.

Oder sind Sie sicher, dass dies der beste Weg für Sie ist, diese Daten in Ihrer Anwendung zu speichern? Das Speichern einer Benutzer-ID und eines Namens ist sinnvoll. Wenn Sie in Ihrem Cookie serialisierte Arrays komplexer Objekte speichern, kann dies bedeuten, dass Sie das Problem zunächst nicht korrekt angehen.

+0

Ich kann keine Entschlüsselung finden ..Warum funktioniert das jetzt und wo sollte ich das Decrypt platzieren? .. Danke – Naor

+0

Mach dir keine Sorgen über die Entschlüsselung - ich habe ein wenig nachgedacht und es sieht so aus, als ob es automatisch vom FormsAuthenticationModule erledigt wird. – smartcaveman

+0

Sie haben mir sicherlich geholfen, obwohl ich nicht ausführlich darüber recherchiert habe. Ich werde dir die Belohnung geben. Wenn ich irgendwelche Fragen habe, werde ich sie hier fragen. Vielen Dank. – Naor

1

Ich vermute, dass Ihr Code in einem Anmeldevorgang irgendwo ist und Ihr Gebäude eine benutzerdefinierte Formulare Auth.

Sie müssen auch dann aus dem Cookie auf jeder Seite Anfrage

das Benutzerobjekt bauen
public class AuthHttpModule : IHttpModule { 
    public virtual void Init(HttpApplication app) { 
     app.AuthenticateRequest += new EventHandler(app_AuthenticateRequest); 
    } 
    private void app_AuthenticateRequest(object source, EventArgs e) { 
     HttpCookie cookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName]; 
     if (cookie == null) { 
      HttpContext.Current.User = null; 
     } else { 
      cookie = HttpContext.Current.Response.Cookies[FormsAuthentication.FormsCookieName]; 
      FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(cookie.Value); 
      HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(new FormsIdentity(ticket), new string[0]); 
     } 
     bool result = HttpContext.Current.Request.IsAuthenticated; 
    } 
} 

EDIT

versuchen, dies zu Ihrem globalen

void Application_AuthenticateRequest(Object sender, EventArgs e) 
    HttpCookie cookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName]; 
    if (cookie != null) { 
     FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(cookie.Value); 
     HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(new FormsIdentity(ticket), new string[0]); 
    } 
} 
+0

Aber ich mache es in der global.asax – Naor

+0

können Sie Ihre globale oder eine verkürzte Version, vor allem die Ereignisse, die Sie verwenden – djeeg

+0

Ich habe meine Frage aktualisiert. – Naor