2011-03-09 77 views
3

我一直在讨论关于nonce生成和PHP的各种问题,但没有发现关于管理nonce的“once”方面的细节的任何讨论。在Apache/PHP中管理临时数据

这是我的情况。

我有一些PHP需要访问一个web服务,并且请求web服务需要我的PHP生成一个随机数并签名请求(即,我没有请求来自web服务的随机数)。这部分很容易。

我正在努力寻找一种很好的解决方案,以防止在可能出现多个会话时重用随机数。

正如我所看到的,我可以做三件事。

一个是将随机数/时间戳对存储在数据库中,然后执行逻辑来检查数据库中是否存在现时,过期等。这还需要TRANSACTIONLOCK TABLE以确保线程安全。呸。

二,是存储nonces在APC(无法在我的情况下使用memcached),并让TTL处理到期。在这种情况下,线程安全是否需要在sem_acquire()/sem_release()中包装逻辑或者是apc_add()真正的线程安全?我主要关心的是如何处理这种情况,如果apc_add()apc_store()实际上因缓存已满而失败。

三,是用Cache_Lite代替APC。

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

谢谢。

回答

7

一个是将nonce/timestamp对存储在数据库中,然后实现逻辑来检查数据库是否存在现时现有数据,过期旧数据等。这还需要一个TRANSACTION或LOCK TABLE用于线程安全。呸。

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

创建一个表,其中包含随机数,创建时间,最长生命周期以及消耗时间的字段。使随机数为主键或唯一。要分配一个随机数,插入表中。如果你得到一个重复的关键错误(或者使用一个事务并得到一个死锁或类似的问题),那么捕获它并产生一个新的随机数。

如果您使用的是an adequate randomness generator like openssl_random_pseudo_bytes并且正在为nonce收集足够的字节,那么碰撞的可能性非常小。

当您需要将nonce标记为已使用时,为nonce行执行一个简单的UPDATE,同时要求消耗的列为空。更新将返回修改的行数(如果使用事务,则返回死锁)。如果修改后的行数为零或者发生了死锁,那么其他事件已经将nonce标记为已使用,并且可以向用户返回适当的错误。

请记住,正确的数据库引擎是设计来处理这种无稽之谈。不要重新发明轮子。

+0

谢谢。我没有想到这种方法。 – mpdonadio 2011-03-10 13:42:52

+0

你会推荐'date_consumed'作为'DATETIME'或'TIMESTAMP'吗? – binnyb 2015-09-01 14:42:28