2014-05-13 12 views
14

Przechowuję niestandardowe oświadczenia, takie jak prawdziwe nazwisko użytkownika, w pliku cookie ASP.NET Identity, aby uniknąć niepotrzebnych zapytań do bazy danych na każde żądanie. Przynajmniej to, co zakładam ten kod robi:Plik cookie tożsamości traci niestandardowe informacje o roszczeniach po pewnym czasie.

var identity = await user.GenerateUserIdentityAsync(UserManager); 
identity.AddClaim(new Claim(ClaimTypes.GivenName, user.FirstName))); 
// etc. 
AuthenticationManager.SignIn(new AuthenticationProperties {IsPersistent=true}, identity); 

Działa to dobrze, i mogę odzyskać te roszczenia z:

private static string GetClaim(string claimType) 
{ 
    var identity = (ClaimsPrincipal) Thread.CurrentPrincipal; 
    var claim = identity.Claims.SingleOrDefault(o => o.Type == claimType); 
    return claim == null ? null : claim.Value; 
} 

Obiekt identity.Claims zawiera następujące twierdzenia, zgodnie z oczekiwaniami:

http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier: ced2d16c-cb6c-4af0-ad5a-09df14dc8207 
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name: [email protected] 
http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider: ASP.NET Identity 
AspNet.Identity.SecurityStamp: 284c648c-9cc7-4321-b0ce-8a347cd5bcbf 
http://schemas.microsoft.com/ws/2008/06/identity/claims/role: Admin 
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname: My Name 

Problem polega na tym, że po pewnym czasie (zazwyczaj kilka godzin) moje oświadczenia niestandardowe wydają się zanikać - w tym przykładzie givenname już nie istnieje w wyliczeniu jon. Użytkownik nadal jest uwierzytelniany, a wszystkie domyślne roszczenia nadal istnieją.

Co się dzieje i jak mogę to naprawić? Jedyne, co mogę myśleć to to, że ciasteczko wygasa i jest ponownie wydawane za kulisami, ale nie wiem, dlaczego tak się stało.

+0

Witam @ James. Czy mogę zadać pytanie. Powiedziałeś, że robisz to, aby "unikać niepotrzebnych zapytań do bazy danych na każde żądanie". To sprawiło, że pomyślałem, że tożsamość musi mieć dostęp do bazy danych na każde żądanie. Czy to prawda? Zrobiłem bardzo prosty test i wydawało się, że nie mam dostępu do bazy danych (na podstawie braku danych wyjściowych z 'DbContext.Database.Log'), ale być może został on zbuforowany. Byłoby miło wiedzieć, że dostęp do bazy danych na żądanie HTTP byłby złą wiadomością. –

+0

@ JonSmith Jeśli nie zapisałem w pamięci prawdziwego nazwiska użytkownika (tj. W pliku cookie auth), musiałbym zapytać o tabelę klientów za każdym razem, gdy chcę wiedzieć, jak się nazywają. – James

+0

Witam @ James. OK, rozumiem to teraz. Miałem prawie ten sam problem, ale dodając go jako roszczenie do bazy danych automatycznie pojawił się w pliku cookie. Zakładam, że ciasteczko musi zawierać wszystkie informacje Użytkownika, a więc w jaki sposób ustawia IPrincipal bez potrzeby wyszukiwania. –

Odpowiedz

16

Tak, najprawdopodobniej problem jest związany z wygaśnięciem pliku cookie. Ponieważ nie dodałeś niestandardowych roszczeń do roszczeń użytkownika w bazie danych, są one tracone podczas odświeżania, ponieważ nie dodajesz roszczenia w wywołanej metodzie. można dodać roszczenia poprzez:

userManager.AddClaim(user.Id, new Claim(ClaimTypes.GivenName, user.FirstName)); 

czy można przenieść ten wnętrze metody, która jest wywoływana gdy plik cookie jest regenerowany (domyślnie jego user.GenerateUserIdentityAsync).

 app.UseCookieAuthentication(new CookieAuthenticationOptions { 
      AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, 
      LoginPath = new PathString("/Account/Login"), 
      Provider = new CookieAuthenticationProvider { 
       // Enables the application to validate the security stamp when the user logs in. 
       // This is a security feature which is used when you change a password or add an external login to your account. 
       OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
        validateInterval: TimeSpan.FromMinutes(30), 
        regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager)) 
      } 
     }); 
+1

Wielkie dzięki za radę. Wolałbym nie utrzymywać roszczeń do bazy danych, ponieważ wtedy imię użytkownika byłoby przechowywane dwa razy (w tabelach Użytkownicy i Roszczenia) i musiałem się martwić, że będę je aktualizować. Czy mógłbyś rozwinąć metodę "GenerateUserIdentityAsync"? Gdzie muszę uwzględnić podany fragment kodu i gdzie mogę dodać roszczenie "GivenName"? Dzięki jeszcze raz. – James

+3

Masz już metodę GenerateUserIdentity, która jest wywoływana przy logowaniu. Powinieneś po prostu przenieść kod, w którym dodajesz roszczenie do tej metody, i powinieneś być dobry –

+0

Mam podobne wymagania, ale moja nazwa użytkownika (i inne informacje o aplikacji) jest faktycznie przechowywany w osobnej bazie danych (nie tożsamości db), więc przy logowaniu, gdy wywoływana jest metoda GenerateUserIdentityAsync(), muszę wysłać zapytanie do mojego innego EF dbcontext w celu pobrania tych danych i dodać niestandardowe oświadczenia do tożsamości, poprawny? –

Powiązane problemy