c# - forgot - Come faccio a implementare la reimpostazione della password con ASP.NET Identity per ASP.NET MVC 5.0?




password recovery mvc (2)

Microsoft sta creando un nuovo sistema di Membership chiamato ASP.NET Identity (anch'esso predefinito in ASP.NET MVC 5). Ho trovato il progetto di esempio , ma questo non è implementato una reimpostazione della password.

Nell'argomento relativo alla reimpostazione della password è stato trovato questo articolo: Implementazione della conferma utente e della reimpostazione della password con un'unica identità ASP.NET - Dolore o piacere , non è utile per me, perché non utilizzare il recupero della password incorporato.

Poiché stavo osservando le opzioni, penso che sia necessario generare un token di ripristino, che invierò all'utente. L'utente può quindi impostare la nuova password utilizzando il token, sovrascrivendo quella precedente.

Ho trovato IdentityManager.Passwords.GenerateResetPasswordToken / IdentityManager.Passwords.GenerateResetPasswordTokenAsync(string tokenId, string userName, validUntilUtc) , ma non sono riuscito a capire cosa potrebbe significare il parametro tokenId .

Come implementare la reimpostazione della password in ASP.NET con MVC 5.0?


Ho capito: il tokenid è un'identità scelta liberamente, che identifica un'opzione password. Per esempio,

1. sembra il processo di recupero della password, fase 1 (si basa su: https://.com/a/698879/208922 )

[HttpPost]
[ValidateAntiForgeryToken]
[AllowAnonymous]
//[RecaptchaControlMvc.CaptchaValidator]
public virtual async Task<ActionResult> ResetPassword(
                                              ResetPasswordViewModel rpvm)
{
    string message = null;
    //the token is valid for one day
    var until = DateTime.Now.AddDays(1);
    //We find the user, as the token can not generate the e-mail address, 
    //but the name should be.
    var db = new Context();
    var user = db.Users.SingleOrDefault(x=>x.Email == rpvm.Email);

    var token = new StringBuilder();

    //Prepare a 10-character random text
    using (RNGCryptoServiceProvider 
                        rngCsp = new RNGCryptoServiceProvider())
    {
        var data = new byte[4];
        for (int i = 0; i < 10; i++)
        {
            //filled with an array of random numbers
            rngCsp.GetBytes(data);
            //this is converted into a character from A to Z
            var randomchar = Convert.ToChar(
                                      //produce a random number 
                                      //between 0 and 25
                                      BitConverter.ToUInt32(data, 0) % 26 
                                      //Convert.ToInt32('A')==65
                                      + 65
                             );
            token.Append(randomchar);
        }
    }
    //This will be the password change identifier 
    //that the user will be sent out
    var tokenid = token.ToString();

    if (null!=user)
    {
        //Generating a token
        var result = await IdentityManager
                                .Passwords
                                .GenerateResetPasswordTokenAsync(
                                              tokenid, 
                                              user.UserName, 
                                              until
                           );

        if (result.Success)
        {
            //send the email
            ...
        }
    }
    message = 
        "We have sent a password reset request if the email is verified.";
    return RedirectToAction(
                   MVC.Account.ResetPasswordWithToken(
                               token: string.Empty, 
                               message: message
                   )
           );
}

2 E poi quando l'utente inserisce il token e la nuova password:

[HttpPost]
[ValidateAntiForgeryToken]
[AllowAnonymous]
//[RecaptchaControlMvc.CaptchaValidator]
public virtual async Task<ActionResult> ResetPasswordWithToken(
                                            ResetPasswordWithTokenViewModel 
                                                        rpwtvm
                                        )
{
    if (ModelState.IsValid)
    {
        string message = null;
        //reset the password
        var result = await IdentityManager.Passwords.ResetPasswordAsync(
                                                   rpwtvm.Token, 
                                                   rpwtvm.Password
                           );
        if (result.Success)
        { 
            message = "the password has been reset.";
            return RedirectToAction(
                        MVC.Account.ResetPasswordCompleted(message: message)
                   );
        }
        else
        {
            AddErrors(result);
        }
    }
    return View(MVC.Account.ResetPasswordWithToken(rpwtvm));
}

Proposta di scheletro per campionare il progetto su github, se qualcuno ne ha bisogno può essere testato. L'invio di e-mail non è stato ancora scritto, probabilmente con l'aggiunta a breve.


Sembra un sacco di problemi ... Che vantaggio offre quanto sopra:

  1. l'utente che fa clic sul collegamento "Recupera account"
  2. questo invia una stringa codificata a 64 byte di un valore di tick di datetime (chiamalo psuedo-hash) in un'email
  3. fare clic sul collegamento indietro nell'e-mail a un controller / percorso di azione che
  4. corrisponde alla posta elettronica e il suo server di origine a psuedo-hash, decodifica lo psuedo-hash, convalida il tempo trascorso dall'invio e
  5. offre una vista per l'utente per impostare una nuova password
  6. con una password valida, il codice rimuove la vecchia password utente e assegna il nuovo.
  7. Una volta completato, con successo o no, elimina lo psuedo-hash.

Con questo flusso, MAI mai inviare una password dal tuo dominio.

Per favore, chiunque, provatemi come questo sia meno sicuro.





password-recovery