2016-07-30 14 views
1

Ich habe ASP.Net MVC5-Anwendung. Beim Erstellen einer Anwendung, wenn Sie "Individual Authentication Visual Studio" auswählen, verwenden Sie Gerüst und fügen Code für "Anmelden", "Benutzer erstellen", "Passwort vergessen" usw. hinzu. Ich verwende diese Standardimplementierung der ForgotPassword-Funktionalität. So funktioniert das vergessene Passwort.Wo speichert AspnetIdentity UserTokens?

1> Benutzer klicken Sie auf Passwort vergessen Link.

2> Der Benutzer gibt seine E-Mail-Adresse ein.

3> Anwendung erstellt neues Token und sendet eine E-Mail mit der Rückgabe-URL mit Token in der Abfragezeichenfolge.

4> Der Benutzer klickt auf den Link in der E-Mail und wird zur Seite ResetPassword weitergeleitet.

5> Der Benutzer gibt ein neues Passwort ein und drückt submit.

6> Anwendung Validiert den Benutzer und das Token und setzt das Passwort zurück.

Frage.

1> Nach dem Empfang der E-Mail-Benutzer kann nicht sofort auf den Link klicken, er kann nach irgendwann oder sogar nach wenigen Tagen klicken. Zwischen wo speichert ASP.NET-Anwendung das Token? Ich sehe es nicht in der Datenbank.

2> Gibt es einen Verfall des Tokens?

3> Auf Passwort vergessen Bildschirm Benutzer gibt seine E-Mail und klicken Sie auf Senden, um E-Mail mit Token zu erhalten. Sagen wir, er macht das dreimal. Er erhält also 3 E-Mails mit 3 verschiedenen Token. Dann klickt er auf den Link von einer beliebigen E-Mail und setzt das Passwort zurück. Was passiert mit unbenutzten Tokens in anderen 2 E-Mails, sind sie noch gültig? Kann der Benutzer auf einen Link in einer anderen E-Mail klicken und das Passwort zurücksetzen?

+0

Können Sie meine Antwort überprüfen? Habe ich etwas verpasst ? –

Antwort

2

Wenn Sie sich den von ASP.Net Identity erstellten Benutzer ansehen, sehen Sie eine Spalte SecurityStamp, die im Grunde Hash ist und in allen passwortbezogenen Szenarien verwendet wird. In der Tat wird es geändert, wenn ein Benutzer sein Passwort ändert.

Wenn Sie auf das Zurücksetzen des Passworts klicken, wird SecurityStamp mit diesem Benutzer verknüpft, um das Token zu generieren, das in E-Mail gesendet wird. Sehen Sie den Quellcode in GenerateAsync Methode hier (es gibt 2 Anbieter)

https://github.com/aspnet/Identity/blob/dev/src/Microsoft.AspNetCore.Identity/TotpSecurityStampBasedTokenProvider.cs

public virtual async Task<string> GenerateAsync(string purpose, UserManager<TUser> manager, TUser user) 
    { 
     if (manager == null) 
     { 
      throw new ArgumentNullException(nameof(manager)); 
     } 
     var token = await manager.CreateSecurityTokenAsync(user); 
     var modifier = await GetUserModifierAsync(purpose, manager, user); 
     return Rfc6238AuthenticationService.GenerateCode(token, modifier).ToString("D6", CultureInfo.InvariantCulture); 
} 

oder

https://github.com/aspnet/Identity/blob/dev/src/Microsoft.AspNetCore.Identity/DataProtectionTokenProvider.cs

public virtual async Task<string> GenerateAsync(string purpose, UserManager<TUser> manager, TUser user) 
    { 
     if (user == null) 
     { 
      throw new ArgumentNullException(nameof(user)); 
     } 
     var ms = new MemoryStream(); 
     var userId = await manager.GetUserIdAsync(user); 
     using (var writer = ms.CreateWriter()) 
     { 
      writer.Write(DateTimeOffset.UtcNow); 
      writer.Write(userId); 
      writer.Write(purpose ?? ""); 
      string stamp = null; 
      if (manager.SupportsUserSecurityStamp) 
      { 
       stamp = await manager.GetSecurityStampAsync(user); 
      } 
      writer.Write(stamp ?? ""); 
     } 
     var protectedBytes = Protector.Protect(ms.ToArray()); 
     return Convert.ToBase64String(protectedBytes); 
    } 

Sobald ein Benutzer auf den Link klickt und neues Passwort einreicht Token, die in einer E-Mail gesendet werden, werden ebenfalls gesendet und gegen den SecurityStamp validiert.

public virtual async Task<bool> ValidateAsync(string purpose, string token, UserManager<TUser> manager, TUser user) 
    { 
     if (manager == null) 
     { 
      throw new ArgumentNullException(nameof(manager)); 
     } 
     int code; 
     if (!int.TryParse(token, out code)) 
     { 
      return false; 
     } 
     var securityToken = await manager.CreateSecurityTokenAsync(user); 
     var modifier = await GetUserModifierAsync(purpose, manager, user); 
     return securityToken != null && Rfc6238AuthenticationService.ValidateCode(securityToken, code, modifier); 
} 

Oder

public virtual async Task<bool> ValidateAsync(string purpose, string token, UserManager<TUser> manager, TUser user) 
    { 
     try 
     { 
      var unprotectedData = Protector.Unprotect(Convert.FromBase64String(token)); 
      var ms = new MemoryStream(unprotectedData); 
      using (var reader = ms.CreateReader()) 
      { 
       var creationTime = reader.ReadDateTimeOffset(); 
       var expirationTime = creationTime + Options.TokenLifespan; 
       if (expirationTime < DateTimeOffset.UtcNow) 
       { 
        return false; 
       } 

       var userId = reader.ReadString(); 
       var actualUserId = await manager.GetUserIdAsync(user); 
       if (userId != actualUserId) 
       { 
        return false; 
       } 
       var purp = reader.ReadString(); 
       if (!string.Equals(purp, purpose)) 
       { 
        return false; 
       } 
       var stamp = reader.ReadString(); 
       if (reader.PeekChar() != -1) 
       { 
        return false; 
       } 

       if (manager.SupportsUserSecurityStamp) 
       { 
        return stamp == await manager.GetSecurityStampAsync(user); 
       } 
       return stamp == ""; 
      } 
     } 
     // ReSharper disable once EmptyGeneralCatchClause 
     catch 
     { 
      // Do not leak exception 
     } 
     return false; 
} 

Sobald es erfolgreich das Token-Identity-System weiter aktualisiert die Benutzerdaten mit neuen SecurityStamp.Mit all dieser Antwort auf Ihre Fragen

Ans 1 - Token ist nicht gespeichert und Link in E-Mail ist sofort aktiv. Ich habe ein vollständig getestetes Produktionssystem und weder ich noch die Benutzer müssen warten, bis der Link aktiv ist.

Ans 2- Ich denke, der Standardwert ist 1 Tag. Sie können es ändern, indem Sie

if (dataProtectionProvider != null) 
{ 
    manager.UserTokenProvider = 
    new DataProtectorTokenProvider<ApplicationUser> 
     (dataProtectionProvider.Create("ASP.NET Identity")) 
     {      
     TokenLifespan = TimeSpan.FromHours(1) //Any custom TimeSpan 
     }; 
} 

Am 3 in Create Methode der ApplicationUserManager Klasse unter Code hinzufügen - Nur 1 wird das heißt arbeiten je nachdem, was Benutzer zum ersten Mal ändert, weil nach, dass die Sicherheit Stempel klickt und es wird das Token in anderen 2 E-Mail ungültig machen.

Hoffe, das hilft.

+0

A Danke für die ausführliche Antwort – LP13