关于加密:PHP:为确认电子邮件创建和存储令牌的最佳方式(3个选项)

PHP: Best way to create and store token for confirmation email (3 options)

我想在PHP中创建一个令牌,它可以作为密码重置请求的一部分用于确认电子邮件。

在网上搜索时,我发现了一个帖子,上面写着:

1
$token = md5(uniqid(mt_rand(), true));

有人能告诉我,与下面的相比,这里是否更适合这样做,并告诉我这里的区别是什么?

1
$token = bin2hex(openssl_random_pseudo_bytes(16));

1
$token = bin2hex(mcrypt_create_iv(128, MCRYPT_DEV_RANDOM));

另外,您能告诉我应该使用哪种数据类型将这个数据存储在数据库中吗(使用MySQL)?

感谢您的到来,迈克


不要将uniqid()用作任何安全关键代码中的随机值。这包括密码重置——攻击者可能能够预测uniqid()的值,允许他们猜测安全令牌并重置系统上任何用户的密码。

相反,使用bin2hex(openssl_random_pseudo_bytes(…))(在您的问题中看到)创建一个安全的随机令牌。php手册专门针对uniqid()上条目的脚注中的目的推荐此函数:

This function [that is, uniqid()] does not generate cryptographically secure tokens, in fact without being passed any additional parameters the return value is little different from microtime(). If you need to generate cryptographically secure tokens use openssl_random_pseudo_bytes().

由于bin2hex()是一个可打印的字符串,因此可以使用任何字符串类型将其存储在数据库中。在这里,VARCHAR应该是您的默认选择,这是完全合适的。

为了获得最大的安全性,您可能需要采取另外一个步骤。不要将令牌存储在数据库中,而是在数据库中存储令牌的哈希(例如,sha1($token)),然后将用户提供的值的哈希与存储的哈希进行比较。本质上,把它当作密码!这个额外的步骤将防止攻击者通过从数据库中读取用户的"忘记密码"令牌来获得对用户帐户的控制,因为攻击者能够读取您的数据库,但不能写入数据库。