3

我一直在讨论关于 nonce 生成和 PHP 的各种问题,但没有找到任何关于管理 nonce 的“once”方面的细节的讨论。

这是我的情况。

我有一些 PHP 需要访问 Web 服务,而对 Web 服务的请求需要我的 PHP 生成一个随机数并对请求进行签名(即,我不是从 Web 服务请求随机数)。那部分很容易。

当可能有多个会话正在进行时,我正在努力寻找一个好的解决方案来防止重复使用随机数。

在我看来,我可以做三件事。

一种是在数据库中存储随机数/时间戳对,然后实现逻辑来检查数据库是否存在现有随机数、过期旧随机数等。这也需要一个TRANSACTIONorLOCK TABLE线程安全。呸。

二是把nonce存入APC的store中(我的情况下不能使用memcached),让TTL处理过期。在这种情况下,线程安全需要将逻辑包装在sem_acquire()/中sem_release()还是apc_add()真正的线程安全?我对此的主要关注是如果缓存已满apc_add()或实际上失败了如何处理这种情况。apc_store()

三、是用Cache_Lite代替APC。

还有其他选择吗?据我所知,OpenID 使用 Cache_Lite 管理随机数,所以我怀疑这是最好的解决方案,但我想在提交之前检查所有选项。

谢谢。

4

1 回答 1

7

一种是在数据库中存储 nonce/timestamp 对,然后执行逻辑来检查数据库中是否存在现有的 nonce,过期旧的等等。这还需要一个 TRANSACTION 或 LOCK TABLE 以确保线程安全。呸。

您可以在没有表锁定的情况下执行此操作。只要您使用的数据存储符合 ACID 标准,它就会为您完成所有艰苦的工作。这意味着如果您使用 MySQL,则使用 InnoDB 表。

创建一个表,其中包含 nonce、创建时间、最长生命周期和使用时间的字段。使 nonce 成为主键或唯一的。要分配随机数,请插入表中。如果您遇到重复键错误(或使用事务并遇到死锁或类似问题),请捕获它并生成新的随机数。

如果您使用的是足够的随机生成器,openssl_random_pseudo_bytes并且正在为随机数收集足够的字节,那么一开始发生冲突的可能性就很小。

当您需要将 nonce 标记为已使用时,请对 nonce 行执行简单的 UPDATE ,还要求已使用的列为 null。更新将返回修改的行数(如果您使用事务,则返回死锁)。如果修改的行数为零或者您遇到死锁,则其他东西已经将 nonce 标记为已使用,您可以向用户返回适当的错误。

请记住,适当的数据库引擎旨在处理这种废话。不要重新发明轮子。

于 2011-03-09T18:03:47.513 回答