Java 创建用于电子邮件确认的唯一id

Java 创建用于电子邮件确认的唯一id,java,passwords,Java,Passwords,我需要为电子邮件确认创建一个唯一的ID,因此当客户单击链接时,会将他们带到一个页面来输入他们的电子邮件,一旦他们输入电子邮件,就会向他们发送一封电子邮件。 电子邮件中包含一个链接,通过进入该链接,他们可以更改密码。 这就是过程,但我需要你确认我的步骤,首先我生成一个随机数,并将其添加到与用户id关联的数据库中,如果该页面已打开,那么我允许他们更改密码,对吗?我已经使用了PHP。我通常会创建一些跟踪信息的散列,我可以稍后验证。例如,在电子邮件地址或用户ID上使用MD5或SHA1哈希。或者,如果需要

我需要为电子邮件确认创建一个唯一的ID,因此当客户单击链接时,会将他们带到一个页面来输入他们的电子邮件,一旦他们输入电子邮件,就会向他们发送一封电子邮件。 电子邮件中包含一个链接,通过进入该链接,他们可以更改密码。
这就是过程,但我需要你确认我的步骤,首先我生成一个随机数,并将其添加到与用户id关联的数据库中,如果该页面已打开,那么我允许他们更改密码,对吗?

我已经使用了PHP。我通常会创建一些跟踪信息的散列,我可以稍后验证。例如,在电子邮件地址或用户ID上使用MD5或SHA1哈希。或者,如果需要,可以将两者结合使用:

Java脚本:
hex\u md5(随机数+用户id+其他内容)

PHP:
md5($email.$userID.$unique\u server\u key)

这应该给你一个唯一的关键点来跟踪他们。将其保存在数据库中以及用于生成它的变量中,以便以后可以跟踪它。我强烈建议使用PHP版本,因为它的服务器端有助于防止恶意用户知道您的令牌生成算法

JavaScript哈希库:

编辑: 对不起,我也用错了语言。对于java,您需要使用加密库来生成散列。尝试此代码(未经测试,我只是键入)


我相信这是MD5的正确用法。我只使用变量user_id和email,因为它们都已保存在数据库中。最好使用数据库中的多个常量。抱歉,如果我对java有点生疏。

请使用java.util.UUID进行此操作。

您的过程几乎是正确的。不过,您应该注意以下几点:

1) 使密钥不可预测,这样即使知道代码,也没有人能创建它自己的有效密钥。由于您将密钥存储在数据库中,因此可以创建“真正随机”的密钥,这比使用已知值(如电子邮件和用户ID)要好得多。密码重置功能通常是web应用程序安全性中最薄弱的环节

// this (untested) code reads from the OS random source to create a random id
function createRandomKey($length)
{
  $buffer = mcrypt_create_iv($length, MCRYPT_DEV_URANDOM);
  $encodedBuffer = base64_encode($buffer);
  return substr($encodedBuffer, 0, $length);
}
2) 不要将此随机密钥直接存储在数据库中,而是将其作为密码进行处理,并从中存储哈希值。这有助于防止攻击者读取您的数据库(SQL注入),即使这样,他也不会免费获得所有密钥

3) 给每把钥匙一个有效期,这样“忘记”的钥匙就不能再使用了

4) 密码重置密钥应在使用后删除,因此在成功更改密码后将其从数据库中删除

编辑:


对不起,我错过了您问题中的Java标记,我的示例是PHP。不幸的是,我不能用Java提供一个例子,但原理是一样的。

我相信仍然有可能不是唯一的。(即使它很小)你的代码可能会被宇宙辐射或你的服务器被陨石击中而改变,也有可能that@user112933564位足够给宇宙中的每个分子编号。UUID有128位,足以对2^64个宇宙中的每个分子进行编号。在什么时候,你开始认为你的反对是徒劳的?每次你产生“随机数”时,你需要检查它是否已经被生成并且没有被使用。这是为了确保您永远不会有重复的ID。(即使机会很小,IMO)您的变量
$unique\u server\u key
每个服务器都是唯一的,还是每个密码重置操作都是唯一的?每个服务器都是唯一的。它是可选的,只是起到了盐的作用。这是用户无法猜测的部分。如果我知道用户的电子邮件和用户ID,我可以尝试创建自己的哈希,但是添加了salt部分后,我真的无法生成一个匹配的哈希。假设在
MySql
中出现
到期日期,但令牌仍然未被使用,如何/哪个服务应负责处理
令牌的删除?@TheCoder-这取决于您,您可以1)保留过期令牌2)在用户尝试使用过期令牌时删除它们3)安装cron作业定期删除过期令牌。我更喜欢解决方案1,因此我可以通知用户重置已过期,并应生成新令牌。偶尔我会删除超过一年的代币。如果我忘记了一些网站/应用上的密码,这也是我获得相同验证代币的原因吗?他们会重新发送我以前的(未使用的)令牌。@编码器-听起来他们在用户表中有一个字段用于重置令牌,但我不建议这样做。我更喜欢使用专用表重置令牌的解决方案,该表独立于用户表。在那里,您可以放置任意数量的令牌,带有用户ID和到期日期,并且您不必触摸用户行。@代码器-只是意味着我不会将令牌放在用户表中。但是您需要userid,因此这已经是与user表的关系。
import java.security.*;
.....
string hash = unique_salt_key.concat(user_id).concat(email);
byte[] hashBytes = hash.getBytes("UTF-8");
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] emailCrypt = md.digest(hashBytes);
string emailToken = new String(emailCrypt)



How to decrypt it again to get user_id and email?
import java.security.*;
.....
string hash = unique_salt_key.concat(user_id).concat(email);
byte[] hashBytes = hash.getBytes("UTF-8");
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] emailCrypt = md.digest(hashBytes);
string emailToken = new String(emailCrypt)



How to decrypt it again to get user_id and email?