Comment puis-je mettre en œuvre un Lien de Réinitialisation de mot de passe
J'ai actuellement un système où, si un utilisateur a oublié son mot de passe, ils peuvent réinitialiser en cliquant sur un lien mot de passe oublié. Ils vont être redirigé vers une page où ils entrent dans leur nom d'utilisateur/e-mail et un email sera envoyé à l'utilisateur, je voulais savoir comment puis-je mettre en œuvre une réinitialisation de mot de passe lien dans le courriel une fois que l'utilisateur clique sur le lien, il est redirigé vers une page qui leur permettra de réinitialiser leur mot de passe.
C'est le code dans mon contrôleur
public ActionResult ForgotPassword()
{
//verify user id
string UserId = Request.Params ["txtUserName"];
string msg = "";
if (UserId == null)
{
msg = "You Have Entered An Invalid UserId - Try Again";
ViewData["ForgotPassword"] = msg;
return View("ForgotPassword");
}
SqlConnection lsql = null;
lsql = DBFactory.GetInstance().getMyConnection();
String sqlstring = "SELECT * from dbo.[USERS] where USERID = '" + UserId.ToString() + "'";
SqlCommand myCommand = new SqlCommand(sqlstring, lsql);
lsql.Open();
Boolean validUser;
using (SqlDataReader myReader = myCommand.ExecuteReader())
{
validUser = false;
while (myReader.Read())
{
validUser = true;
}
myReader.Close();
}
myCommand.Dispose();
if (!validUser)
{
msg = "You Have Entered An Invalid UserId - Try Again";
ViewData["ForgotPassword"] = msg;
lsql.Close();
return View("ForgotPassword");
}
//run store procedure
using (lsql)
{
SqlCommand cmd = new SqlCommand("Stock_Check_Test.dbo.RESET_PASSWORD", lsql);
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter paramUsername = new SqlParameter("@var1", UserId);
cmd.Parameters.Add(paramUsername);
SqlDataReader rdr = cmd.ExecuteReader();
while (rdr.Read())
{
if (Convert.ToInt32(rdr["RC"]) == 99)
{
msg = "Unable to update password at this time";
ViewData["ForgotPassword"] = msg;
lsql.Close();
return View("ForgotPassword");
}
}
}
msg = "new password sent";
ViewData["ForgotPassword"] = msg;
lsql.Close();
return View("ForgotPassword");
}
C'est ma procédure stockée qui l'envoie à l'utilisateur un e-mail
ALTER PROCEDURE [dbo].[A_SEND_MAIL]
@var1 varchar (200), -- userid
@var2 varchar (200) -- email address
AS
BEGIN
declare @bodytext varchar(200);
set @bodytext = 'Password Reset for user: ' +@var1 + ' @' + cast (getDate() as varchar) + ' ' ;
EXEC msdb.dbo.sp_send_dbmail
@profile_name='Test',
@recipients=@var2,
@subject='Password Reset',
@body=@bodytext
END
GO
- Vous générez une longue chaîne de caractères aléatoires et de le stocker à côté de l'identifiant utilisateur (et une date d'expiration), naviguez jusqu'à la réinitialisation.aspx?id=longstring et de l'utiliser pour identifier l'utilisateur et d'afficher une page de réinitialisation, de la suppression/invalider la chaîne de caractères en cas de succès.
- Vous avez besoin de paramétrer TOUTES vos questions. La première requête ici est grande ouverte à l'injection sql. Aussi, vous devriez vraiment spécifier uniquement les colonnes dont vous avez besoin au lieu d'utiliser *.
Vous devez vous connecter pour publier un commentaire.
Créer une table qui a une structure comme
Ensuite dans votre code lorsque l'utilisateur clique sur le bouton réinitialiser mot de passe, vous allez générer un jeton aléatoire puis mettre une entrée dans la table avec la valeur de hachage de la
token
et une date d'expiration de quelque chose commeDATEADD(day, 1, GETDATE())
et ajoute que le jeton de la valeur de l'url que vous e-mail de l'utilisateur pour la réinitialisation du mot de passe de la page.Sur la page de réinitialisation de mot de passe vous prendre le nom d'utilisateur et un jeton passé, hacher le jeton à nouveau, puis la comparer avec la
ResetTickets
table, et si la date d'expiration n'a pas encore passé et le jeton n'a pas encore été utilisé, puis prendre l'utilisateur vers une page qui leur permet d'entrer un nouveau mot de passe.Choses à être prudent quant à l':
Rand
et l'utiliser pour générer le jeton, deux utilisateurs qui reset en même temps obtenir le même (j'ai pu réinitialiser mon mot de passe et de votre mot de passe en même temps, puis utiliser mon jeton de réinitialisation de votre compte). Au lieu de faire un statiqueRNGCryptoServiceProvider
et l'utilisation de laGetBytes
méthode de cela, la classe est thread-safe, donc vous n'avez pas besoin de s'inquiéter à propos de deux threads à l'aide de la même instance.'; delete dbo.[USERS] --
il aurait pour effet de supprimer tous les utilisateurs de votre base de données. Voir le rattachement post pour plus d'infos sur comment résoudre le problème.passwordReset
page accepte uniquement les unhashed version, et vous ne jamais stocker les unhashed version partout (y compris e-mail les journaux de messages sortants pour les utilisateurs). Cela empêche un attaquant qui a accès en lecture à la base de données de faire un jeton pour un autre utilisateur, la lecture de la valeur qui a été envoyé dans l'e-mail, puis de l'envoyer à la même valeur de lui-même (et peut-être obtenir l'accès à un utilisateur de l'administrateur qui peut faire plus de choses que juste lire les valeurs).