所以我想要一种方法来生成一个身份验证令牌以传递回客户端,然后它可以使用它来传递每个请求。
然而,生成以前从未使用过的唯一令牌的最佳做法是什么。
我需要保证唯一性,所以我不能完全基于php uniqid(),因为两个用户在同一时间登录的可能性很小(机会非常小但不能抓住机会)。
将uniqid()值加上用户名吗?
是不好的做法当时钟返回/前进时,uniqid()的时间戳是否容易受到重复值的影响?
答案 0 :(得分:0)
我猜你已经有了一个存储这些令牌的数据库,以便你可以检查它是否是正确的。如果这是真的,你可以按照自己喜欢的方式生成令牌(即uniqid(),随机字符串,......无论你喜欢什么),并检查数据库中是否已存在。如果它不存在你就可以使用它,否则你可以生成一个新的并再次进行检查。
答案 1 :(得分:0)
您可以使用UUID,Universally Unique IDentifier。规格为rfc4122。
摘录:
使用UUID的主要原因之一是没有集中化 管理它们需要权限(尽管一种格式使用 IEEE 802节点标识符,其他不标识。结果,生成 按需可以完全自动化,并用于各种 目的。这里描述的UUID生成算法非常支持 如果,每台机器的高分配率高达每秒1000万 必要的,以便它们甚至可以用作交易ID。
UUID生成器
有各种语言的UUID生成器,只需确保实现使用RFC-4122规范中的算法。其中很多只是为UUID的每个十六进制八位字节使用一个随机数,这将导致冲突。
答案 2 :(得分:0)
很多归结为代码可以变成多长时间,你需要多大程度的独特性,不可预测的难度,以及你是否有一个有效代码列表。
<强>长度强>
首先:简单数学意味着如果你必须能够生成无数个唯一的独特随机字符串,那么你就不能限制所述字符串的长度(它会变得无限...... )。
如果必须将使用的值存储在数据库中,则通常需要最大长度。
无论如何,无限长度的琴弦会产生很多危险。
多么独特?
显然,仅仅使用时间并不是很独特,但是你可以添加一些东西来使碰撞越来越不可能,同时让它更难以预测。
如果您有(当前)有效代码的列表,您始终可以针对现有数据库验证生成的代码,并在与当前有效代码发生冲突时重新生成新代码。
显然,一个简单的不断增加的计数器将保证唯一性,但它并不方便,因为它没有长度限制,非常可预测等。
难以预测
通常可以猜到的身份验证代码是一种糟糕的安全理念。所以你需要防范这一点。
全部合并
要将它们全部组合起来,您可以创建以下字符串的串联:
你不需要全部,订单等都取决于你。越多越好。
一旦你有了这个字符串,你选择一个哈希函数,哈希输出的时间越长,冲突的可能性就越小,但代码将在你的数据库中使用的存储空间越多。
现在一个不错的选择是sha-1或sha-256(md5有点太破碎了,无法用于任何新的东西)。
这为您提供了一个长度固定的代码,即使您只是在输入中更改一位,也几乎无法预测攻击者,并且几乎不可能导致冲突,所以代码会发生显着变化。
多么小?这不太可能,请看这里的数学:https://crypto.stackexchange.com/questions/24732/probability-of-sha256-collisions-for-certain-amount-of-hashed-values
如果您需要完全排除这种可能性并且不允许无限长度的代码,您只能根据使用的代码进行检查,如果找到它,您可以生成一个新代码。
<强> TL; DR 强>
您可以添加其他时间,例如连接的远程端的IP地址,伪随机数,进程ID,保密的固定字符串等,将其混合并使用例如哈希值进行哈希处理。 sha-256,你有一个很难预测代码的固定长度。
存在碰撞的风险,但如果你给它足够的输入,它就会非常小,以消除它:检查使用中的代码列表。
答案 3 :(得分:-2)
这种方法对我有用......
$token = md5(date['u']);
使用自纪元(1970年1月1日)以来的秒数,因此几乎可以保证您获得唯一的一次性值。 MD5将其转换为32个字符的字符串。 2个相同值的可能性仍然不是很大,但非常接近于零。
使用日期w /'u'参数不会因DST而出现问题。