Como posso implementar uma ligação de Reset de senha
tenho actualmente um sistema em que, se um utilizador se esqueceu da sua senha, pode reiniciá-la clicando num link de senha que se esqueceu. Ele será levado para uma página onde insira seu nome de usuário/email e, em seguida, um email será enviado para o usuário, eu queria saber como posso implementar um link de redefinição de senha no e-mail assim que uma vez que o usuário clica no link, ele/ela é levado a uma página que irá permitir-lhes para redefinir sua senha.
Este é o código no meu controlador.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");
}
Este é o meu procedimento actual armazenado que envia ao Utilizador um 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
1 answers
Crie uma tabela que tenha uma estrutura como
create table ResetTickets(
username varchar(200),
tokenHash varbinary(16),
expirationDate datetime,
tokenUsed bit)
, em Seguida, em seu código quando o usuário clicar em repor palavra-passe de botão você irá gerar um token aleatório, em seguida, colocar uma entrada na tabela com o valor de hash que token
e uma data de expiração de algo como DATEADD(day, 1, GETDATE())
e acrescenta que o valor do token no url de e-mail para o usuário para a página de redefinição de senha.
www.example.com/passwordReset?username=Karan&token=ZB71yObR
Na página de reset da senha, você pega no nome do utilizador e no token passado, volta a usar o token. compare isso com a tabela ResetTickets
, e se a data de expiração ainda não tiver passado e o token ainda não tiver sido usado, então leve o Usuário para uma página que lhes permita digitar uma nova senha.
Coisas com que ter cuidado:
- certifique-se de expirar o token, não deixe um e-mail de dois anos atrás reiniciar a senha.
- certifique-se de marcar o token como usado, não deixe que outros usuários do computador use o histórico do navegador para reiniciar outros senha.
-
certifique-se que gera o símbolo aleatório com segurança . Não use
Rand
e use-o para gerar o item, dois utilizadores que reinicializam ao mesmo tempo obteriam o mesmo item (eu poderia repor a minha senha e a sua senha ao mesmo tempo e, em seguida, usar o meu item para repor a sua conta). Em vez disso, faça uma estáticaRNGCryptoServiceProvider
e use o métodoGetBytes
a partir disso, a classe é Segura thread para que você não precisa se preocupar com dois threads usando a mesma instância. - Be claro que parameteriza as tuas perguntas . no seu código actual, se eu digitasse no userid {[8] } iria apagar todos os utilizadores da sua base de dados. Veja o link SO post para mais informações sobre como corrigi-lo.
-
certifique-se que anula o item, a sua Página
passwordReset
só aceita a versão não lavada, e nunca armazena a versão não lavada em lado nenhum (incluindo os registos de E-mail das mensagens enviadas para os utilizadores). Isso impede que um atacante que tenha acesso ao banco de dados de fazer um token para algum outro usuário, lendo o valor que foi enviado no e-mail, em seguida, enviando o mesmo valor ele mesmo (e talvez obter acesso a um usuário administrador que pode fazer mais coisas do que apenas ler valores).