处理密码重置的安全方法可能如下所示:
密码重置请求:
>用户打开密码重置请求表单并输入电子邮件地址(无需输入两次,只需进行语法验证).
>您的应用程序会检查数据库中是否存在该电子邮件.如果它存在,它会创建一个令牌,该令牌应该是随机的,而不是来自诸如userid或timestamp之类的信息.令牌的散列将与用户ID和有效期一起存储在数据库中的单独表中.每个电子邮件都会向用户发送带有令牌的链接.
>该应用程序显示已发送电子邮件的确认.此页面可以包含电子邮件地址,因此用户可以检查他是否有拼写错误(毕竟没有关于电子邮件是否在数据库中的信息,因此攻击者无法测试其存在).
重设密码:
>用户单击该链接并打开重置表单.在此表格上,他可以输入两次新密码.必须将令牌作为隐藏输入标记包含在表单中.
>提交表单后,应用程序会检查他的令牌.如果匹配且未过期,则可以更改密码并且用户可以直接登录(然后您可以为他提供登录表单).最后应该停用令牌,我自己更喜欢保留该条目,因此当他再次单击该链接时,我可以通知用户该令牌已被使用.
您将遇到的一个问题是,您必须在数据库中找到令牌的哈希值.存储令牌有两种可能的方法:
>使用SHA512之类的哈希算法对令牌进行哈希处理,而不使用盐.如果令牌非常强,则这是安全的(最小长度20,0-9 a-z A-Z).从理论上讲,在将数据输入数据库之前,必须检查这种哈希是否已经存在,实际上这可以忽略不计.我实现了一个可以处理这种令牌的password-reset class.>您使用BCrypt和salt散列令牌.这允许更短的令牌,但您无法在数据库中搜索散列令牌.相反,您必须在链接中包含row-id才能找到令牌.