本篇文章更新時間:2019/02/16
如有資訊過時或語誤之處,歡迎使用 Contact 功能通知。
一介資男的 LINE 社群開站囉!歡迎入群聊聊~
如果本站內容對你有幫助,歡迎使用 BFX Pay 加密貨幣 或 新台幣 贊助支持。
這主題看似容易其實很有深度。從為甚麼要有這個「亂碼」開始,就是希望可以在做某件事的時候讓「重複」(碰撞)的機率減低,而最好的狀況就是不存在碰撞。
寫程式的人可能多少都用過「隨機」函數,但其實這方法並不是真的隨機,沒有想像中那般真的無法預測,也無法單靠它來避免碰撞。
不過有些變形的操作倒是能「盡量」避免,無法完全保證不碰撞。下面是研究的參考資料整理:
條件
- 短字串
- 碰撞機率低
不需資料關聯類型
這邊概念就是射後不理,產生出來就不理他了。可以透過使用多次隨機方法組合產生,至於碰撞機率這個問題就很不一定了。方法可以參考這篇Creating collision free “random” string 討論以及 PHP 7 的方法「random_bytes」!(其他像是單純使用 uniqid 方法反而要小心,可以參考文件討論串)
至於結果字串短不短還真是要看怎麼實作了,這邊只提到底層方法。
需要資料關聯
上個部分連結討論中都有一些解法,但如果需要有點規律跟甚至是做資料關聯呢?最好的案例就是縮網址系統!
如何在確定有某種排序下將序號做重新編碼避免資料太容易曝光、可預測,以及縮短資料長度?
參考這篇文章:「Generating IDs like Youtube or Bit.ly using PHP」教學如何使用 PHP 產生出像 YouTube 或 Bitly 的亂碼字串。
原理即是透過改變進位法,把數字的 10 進位法去延伸更高進位的概念做字串替換。將原本數字 0~9 的變化強化到 0~9, a~z, A~Z 的 62 進位。
但 PHP 進位方法 base_convert 只支援 2~36 的處理,也就是要做到 62 進位處理就需要自己來了,感謝 Taylor Otwell 大大的支援得以產出這算法。
好,到這邊還差一步,轉換前需要一個「不重複」數字序號來轉換,如果使用資料庫自動累加產生的主鍵編號,直接套入沒問題,那想要一樣先射後不理之後再說的呢?
保險起見,可以使用 microtime 方法來因應快速大量產生編碼的情況,避免單純以 timestamp 處理會有重複問題!(呼叫時間區間太短)
list($usec, $sec) = explode(" ", microtime());
Math::to_base($usec * 10000000 + time(), 62);
透過這個進位處理方法,將字串每一個位元的可能性拉大,自然是縮短又解決序號太容易猜測的好辦法!