ruby-on-rails – 產生獨特的,難以猜測的“優惠券”程式碼
我的Rails應用程式需要為使用者生成電子優惠券.每個優惠券都應該有一個獨特的優惠券程式碼,可以在我們的系統上兌換.
例如免費捲餅的優惠券.使用者A收到免費捲餅的優惠券,然後使用者B收到免費捲餅的優惠券. 2張優惠券應該有獨特的優惠券程式碼.
生成不容易偽造的程式碼的最佳方式是什麼?我不希望使用者以隨機數字輸入成功率很高,並兌換其他人的優惠券.
我想這個想法就像一張背面有唯一號碼的禮品卡是我正在尋找的.
程式碼需要不可估量,因為在給予使用者獎勵之前您可以執行的唯一驗證是檢查他們輸入的程式碼是否存在於“已發出”程式碼列表中.
>這意味著該格式的所有可能程式碼的數量遠遠大於要發行的程式碼數量.根據簡單地嘗試程式碼(考慮重複嘗試的指令碼)的簡單性,那麼您可能需要所有可能的程式碼超過已釋出的程式碼的百萬分之一或十億以上.這聽起來很高,但可能在相對較短的字串.
>這也意味著您使用的程式碼必須在所有可能的程式碼中儘可能隨機地選擇.這是必要的,以避免使用者弄清楚大多數有效的程式碼以“AAA”開頭.更復雜的使用者可能會發現您的“隨機”程式碼使用可攻擊的隨機數生成器(Ruby的預設rand()對於隨機資料是快速和統計的好的,但是以這種方式可以使用,所以不要使用它).
這樣一個安全程式碼的出發點是加密PRNG的輸出. Ruby具有securerandom庫,您可以使用它來獲取如下原始程式碼:
require 'securerandom' SecureRandom.hex # => "78c231af76a14ef9952406add6da5d42"
這段程式碼足夠長,可以覆蓋任何實際數量的憑證(每個人都有數百萬個),沒有任何有意義的重複機會或容易猜測.但是,從物理副本輸入是有點尷尬.
一旦你知道如何產生一個隨機的,幾乎無法估量的程式碼,你的下一個問題就是理解使用者體驗,並決定你可以以可用性的名義實際地危害安全性.您需要牢記終端使用者的價值,因此有可能嘗試獲取有效的程式碼.我不能為你答覆,但可以提出一些關於可用性的一般觀點:
>避免模糊字元在列印中,有時難以看到1,I和l之間的區別.我們經常明白它應該是從上下文,但是一個隨機的字串沒有這個上下文.通過測試0對O,5對S等,不得不嘗試一些程式碼的差異,這將是一個糟糕的使用者體驗.
>使用小寫字母或大寫字母,但不能同時使用.區分大小寫不會被使用者的百分之百的年齡所理解.
>匹配程式碼時接受變體.允許空格和破折號.也許甚至允許0和O表示同樣的事情.這最好是通過處理輸入文字來實現,因為它在正確的情況下,條帶分隔符等.
>在列印中,將程式碼分成幾個小部分,使用者更容易在字串中找到它們的位置,並一次輸入幾個字元.
>不要讓程式碼太長.我建議12個字元,3組4.
>這是一個有趣的一個 – 你可能想掃描程式碼可能的粗魯的話,或避免生成它們的字元.如果您的程式碼僅包含字元K,U,F,C,那麼很可能會冒犯使用者.這通常不是一個問題,因為使用者看不到大多數電腦保安程式碼,但這些程式碼將會打印出來!
把這些都放在一起,這就是我可以生成一個可用的程式碼:
# Random, unguessable number as a base20 string #.reverse ensures we don't use first character (which may not take all values) raw_string = SecureRandom.random_number( 2**80 ).to_s( 20 ).reverse # e.g. "3ecg4f2f3d2ei0236gi" # Convert Ruby base 20 to better characters for user experience long_code = raw_string.tr( '0123456789abcdefghij', '234679QWERTYUPADFGHX' ) # e.g. "6AUF7D4D6P4AH246QFH" # Format the code for printing short_code = long_code[0..3] + '-' + long_code[4..7] + '-' + long_code[8..11] # e.g. "6AUF-7D4D-6P4A"
這種格式有20 ** 12個有效的程式碼,這意味著你可以發出十億個你自己的程式碼,一個使用者只需猜到一個正確的程式碼就有四分之一的機會.在密碼學圈子中,這是非常糟糕的(這個程式碼對本地快速攻擊是不安全的),但是對於註冊使用者提供免費捲餅的網路表單,以及在哪裡你會注意到一個用指令碼嘗試四百萬次的人,這是可以的.
http://stackoverflow.com/questions/22333237/generating-unique-hard-to-guess-coupon-codes