忘记密码请求(Java)

忘记密码请求(Java),java,passwords,token,reset,uuid,Java,Passwords,Token,Reset,Uuid,对你们大多数人来说,这是一个很常见的话题。我正在用Java构建一个webapp,使用Spring+Spring Security+Hibernate+MySQL+等等 我正在实施“重置密码”模块。我已经知道了流程,并且有了所有的表单和相应的控制器。我只是想知道,在编写代码之前,我是否从正确的方向开始,然后继续改进它 MySQL表: PASSWORD_CHANGE_REQUESTS ( TOKEN VARCHAR(126) NOT NULL, USERNAME VAR

对你们大多数人来说,这是一个很常见的话题。我正在用Java构建一个webapp,使用Spring+Spring Security+Hibernate+MySQL+等等

我正在实施“重置密码”模块。我已经知道了流程,并且有了所有的表单和相应的控制器。我只是想知道,在编写代码之前,我是否从正确的方向开始,然后继续改进它

MySQL表

PASSWORD_CHANGE_REQUESTS ( 
       TOKEN VARCHAR(126) NOT NULL,
       USERNAME VARCHAR(50) NOT NULL,         
       CREATION_TIME DATETIME NOT NULL,        
       PRIMARY KEY(TOKEN)          
) 
我看到一些帖子建议使用EXPIRE\u DATE字段。真的值得吗

唯一令牌:

我使用的是一个Spring SHA编码器,用户名+时间戳作为参数(+必需的salt值),它返回字符串,例如:92C303B9740DA59418C32D04B6EC6F4CA61637

此方法是否真的为URL生成唯一标记?还是有更好的方法

在Java中,时间戳的生成方式如下:

 Date date = new Date();
 SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy h:mm:ss");
 String timestamp = sdf.format(date);

如果黑客获得了对用户电子邮件的控制权并找到其中一个链接,密码更改请求的过期将非常有用。如果用户不再在您的系统中使用该电子邮件帐户,至少可以防止他们在您的系统中重置密码,因为请求可能已过期。显然,如果他们获得了对用于您系统的电子邮件帐户的控制权,那么过期将不会有多大好处,因为他们可以简单地再次请求重置。无论哪种方式,为用户提供额外的安全性都是一件相对简单的事情


在生成唯一令牌方面,我认为您的策略相当不错。为了使生成冲突令牌变得更加困难,您可以使用类似于
System.nanoTime()
System.currentTimeMillis()
的方法来获得更精确的时间。您当前的方法意味着,如果在同一秒内调用它,您将获得一个非唯一令牌。虽然这可能很少见,但毫秒或纳秒的情况更为罕见。

我建议将字段EXPIRE\u DATE添加到DB中。 1-为了方便起见,您可能需要EXPIRE_DATE字段,以便在根据数据库中的值验证令牌时,一次性执行选择和检查有效性。 2-对于数据库清理,只需运行脚本即可轻松截断过期记录

您还可以通过检查当前时间来验证令牌在应用程序层是否已过期,但这似乎更麻烦。此外,数据库清理将依赖于某些应用程序逻辑或脚本逻辑来确定记录是否已过期并准备好删除

Spring HSA编码器应该适合您的目的,但是它的用途主要是对密码进行编码,而不是生成唯一的令牌。对于唯一的令牌,您可以查看JavaUUID

你可以在这里读更多


谢谢您的回答。我已经添加了过期日期列。你说得对,它会增加一点安全性,而且我不必每次都计算它。关于时间戳,当然是毫秒/纳秒。。。当我开始更快地点击时,我意识到了这一点,同时令牌没有改变。现在没关系了。正如@myqyl4在他的回答中提到的,您也可以使用JavaUUID。最有可能的是,这两种方法都能很好地为你工作。UUID是生成唯一标识符的一种非常安全的方法,在大约2.52亿年后,
System.currentTimeMillis()
将溢出并破坏您的唯一ID生成器作为另一种安全措施,它可能有助于在使用密码更改请求后删除它们,或者至少将它们标记为已使用。这将增加额外的安全级别。是的,我已经考虑过了。虽然我仍然不知道我是同时做这两件事(标记为used,然后运行脚本并删除所有标记的内容)还是直接删除记录:DThanks获取信息。你和Marc刚刚给了我到期字段所需的确认。顺便说一下,我已经实现了UUID函数。也谢谢你的链接!