我正在做一个允许用户重置密码的模块。我注意到大多数网站如何提供确认链接,其中包含具有唯一哈希的查询字符串。
我的问题是:每次同一个用户请求忘记密码时,如何生成这个唯一的哈希?我应该将此哈希存储在数据库中并稍后将其用于验证吗?会安全吗?或者我应该创建某种生成一次性密码的算法?如何生成 OTP?
我正在做一个允许用户重置密码的模块。我注意到大多数网站如何提供确认链接,其中包含具有唯一哈希的查询字符串。
我的问题是:每次同一个用户请求忘记密码时,如何生成这个唯一的哈希?我应该将此哈希存储在数据库中并稍后将其用于验证吗?会安全吗?或者我应该创建某种生成一次性密码的算法?如何生成 OTP?
是的你应该
关于重置令牌(或任何您想称呼它的名称)的生成似乎有很多困惑。请阅读我链接到的答案,不要用散列和弱种子重新发明轮子。
只需使用一些带有用户 ID、用户盐的哈希函数(你给用户的密码加盐,对吗?)和伪随机数据应该没问题:
$pwd_reset_hash = hash ( 'sha256' , $user_id . $user_salt, uniqid("",true));
将其存储在数据库中(连同请求时间)作为该用户的重置键
user_id pwd_reset_hash time_requested
===========================================
123 ae12a45232... 2010-08-24 18:05
当用户尝试使用它时,检查哈希值是否与用户匹配并且时间是最近的(例如“重置代码在 3 小时内有效”或类似的东西)
使用或过期时将其从数据库中删除
要走的路确实是生成某种随机的东西并将其存储在数据库中。一旦更改密码,您就从表中删除相关记录,以便无法再次使用该链接。
正如在其他回复中已经说过的那样,对用户 ID 执行 SHA1 或 MD5,结合微时间和一些盐字符串通常是一个安全的选择。
1) 要生成唯一的哈希,混合当前时间、用户 ID 和一些盐(文本)。例如,如果您的网站是 mysite.com,则使用以下代码:
$hash = md5(time() . $userid . 'mysite');
这将创建一个不错的哈希。
2)是的,将其存储在数据库中。
3) 是的,只要你在一段固定的时间后过期哈希,它就会是安全的。
4) 不,生成一次性密码通常会惹恼用户。