2011-03-09 74 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