2016-10-15 3 views
2

Ich kämpfe derzeit ein wenig mit meiner benutzerdefinierten CredentialsAuthProvider Implementierung. Zuerst ist es wichtig zu sagen, dass ich einen WPF-Client als Referenz für meine API schreibe.Servicestack - Authentifizierungsfragen

  1. Ein Browser speichert Cookies und Sie können konfigurieren, wie Sie mit ihnen umgehen, z. löschen, wenn der Browser geschlossen ist. Auf Windows-Desktop haben Sie Environment.SpecialFolder.Cookies, wo Windows Cookies speichert. Aber von ServiceStack konnte ich nichts finden. Speichern Sie also nichts in einer Windows Desktop App? Ich sah, dass es eine client.CookieContainer gibt, wo ich nach dem Login drei Cookies finde.
  2. Kann ich irgendwie Eigenschaften zu diesem Cookie während der Authentifizierung hinzufügen? Wenn das so ist, wie? Derzeit verwende ich AuthenticationResponse.Meta Wörterbuch zusätzliche Informationen zu übertragen:

    public override object Authenticate(IServiceBase authService, IAuthSession session, Authenticate request) 
    { 
        var authResponse = (AuthenticateResponse)base.Authenticate(authService, session, request); 
        authResponse.Meta = new Dictionary<string, string>(); 
        authResponse.Meta.Add("Test", "TestValue"); 
        return authResponse; 
    } 
    
  3. Und schließlich: Ist eine Instanz meiner CredentialsAuthProvider Klasse Thread abgeleitet sicher? In TryAuthenticate(...) Ich mache eine DB-Verbindung und ein Objekt abrufen, die alle Informationen einschließlich Hash-Passwort usw. enthält. Aber ich kann diese Informationen nur für das Sitzungsobjekt in OnAuthenticated(....) ausfüllen und/oder Authenticate(...) übersteuert. Wenn möglich, möchte ich keinen weiteren DB-Aufruf machen, um das gleiche Objekt erneut abzurufen. So ist es sicher ein Mitglied user füllen es in TryAuthenticate und Wiederverwendung in anderen überschrieben Methoden zu erklären, wie so:

    public class BediCredentialsAuthProvider : CredentialsAuthProvider 
    { 
        private AppUser user = null; 
    
        public override object Authenticate(IServiceBase authService, IAuthSession session, Authenticate request) 
        { 
         var authResponse = (AuthenticateResponse)base.Authenticate(authService, session, request); 
         authResponse.Meta = new Dictionary<string, string>(); 
         authResponse.Meta.Add("ValueA", user.ValueA); 
         // ... add more properties from user object 
         return authResponse; 
        } 
    
        public override bool TryAuthenticate(IServiceBase authService, string userName, string password) 
        { 
         AppUser user = null; 
         using (var session = NhSessionFactories.OpenSession(TopinConstants.TopInDbFactory)) 
         { 
          using (var transaction = session.BeginTransaction()) 
          { 
           try 
           { 
            var appUserRepo = new AccountManagementRepository(session); 
            user = appUserRepo.GetAppUser(userName); // get user from database using NHibernate 
            transaction.Commit(); 
            session.Close(); 
           } 
           catch (Exception ex) 
           { 
            Log.Error($"Error retrieving user {user} to authenticate. Error: {ex}"); 
            throw; 
           } 
          } 
         } 
         // do some logic to test passed credentials and return true or false 
         } 
    
        public override IHttpResult OnAuthenticated(IServiceBase authService, IAuthSession session, IAuthTokens tokens, 
                  Dictionary<string, string> authInfo) 
        { 
         session.DisplayName = user.DisplayName; 
         session.FirstName = user.Firstname; 
         session.LastName = user.Lastname; 
         session.Email = user.EmailAddress; 
         // etc..... 
         return base.OnAuthenticated(authService, session, tokens, authInfo); 
        } 
    } 
    

Antwort

2

Sie können ServiceStack Service Client-Plätzchen bevölkern wie würden Sie einen Browser, außer es behält nur Dauer Session Ids, wo Sie mit RememberMe=true, zB authentifizieren müssen:

var response = client.Post(new Authenticate { 
    provider = "credentials", 
    UserName = ..., 
    Password = ..., 
    RememberMe = true, 
}); 

Welche der authentifizierte Benutzer Session spart gegen die ss-pid permanente Cookie in der HttpWebRequest Cookie und wird bei jeder weiteren Anfrage gesendet.

var httpRes = authService.Request.Response; 
httpRes.SetPermanentCookie(cookieName, cookieValue); 

ist eine Instanz meiner abgeleiteten CredentialsAuthProvider Klasse Thread-sicher:

Sie können Ihre eigenen permanenten Cookies in OnAuthenticated von authService mit eingestellt?

die keine gleiche AuthProvider Singleton-Instanz wird verwendet, um jede Anforderung zu authentifizieren, so dass Sie auf der Instanz keine gespeicherten Variablen nicht aufrechterhalten kann selbst und entfernen müssen:

//private AppUser user = null; //Instance variables are not ThreadSafe 

Wenn Sie Elemente übergeben möchten und greifen Sie auf sie in der gesamten Request-Pipeline zu, die Sie in IRequest.Items Dictionary speichern können, zB:

authService.Request.Items["AppUser"] = user;