編程過程中經常會有產生隨機數的需求,java.util.Random是我經常使用的,舉例如下:
// 固定seed
Random t = new Random(100);
for (int i = 0; i < 5; i++) {
System.out.println(t.nextInt(100) +" ");
}
// 以系統時鐘作爲seed
Random timeRandom = new Random();
for (int i = 0; i < 5; i++) {
System.out.println(timeRandom.nextInt(100) +" ");
}
僞隨機數和真隨機數
先了解一下這2個概念:
- 真隨機數,通過物理實驗得出,比如擲錢幣、骰子、轉輪、使用電子元件的噪音、核裂變等
- 僞隨機數,通過一定算法和種子得出。軟件實現的是僞隨機數
而僞隨機數也分爲強僞隨機數和弱僞隨機數兩類:
- 強僞隨機數,難以預測的隨機數,例如java.security.SecureRandom
- 弱僞隨機數,易於預測的隨機數,例如java.util.Random
也就是說我們程序裏用的都是僞隨機數,而弱僞隨機數(比如基於固定seed或者系統時鐘seed)是可預測(重複)的,參考如下代碼,seed固定爲100的Random實例,產生的隨機數序列是一模一樣的,也就是說如果一旦黑客知道了你的seed,完全可以預測程序的下一個隨機數是什麼。
//固定seed
Random t = new Random(100);
for (int i = 0; i < 5; i++) {
System.out.println(t.nextInt(100) +" ");
}
Random t2 = new Random(100);
for (int i = 0; i < 5; i++) {
System.out.println(t2.nextInt(100) +" ");
}
這個會有什麼危害呢?如果隨機數影響了程序的校驗邏輯,比如用於產生隨機的短信的驗證碼,如果被不法分子獲取了seed,那就可以破解驗證碼的校驗流程了,後果非常嚴重。但是也不是所有的場景都要用強僞隨機數,不是安全場景的隨機數,使用Random就好,如果想了解詳細的細節,請參考文章:http://netsecurity.51cto.com/art/201605/511983.htm
RandomUtils簡介
commons-lang3裏有RandomUtils工具類,它裏面提供裏多個函數可以方便的的產生隨機數,生成int,long,double,boolean,float,bytes幾種類型,能滿足基本的隨機數產生需求,如下圖:
由於是產生隨機數的靜態工具類,類初始化時內部已經創建了java.util.Random實例,其他的靜態工具方法都是基於這個實例產生的隨機數,所以其本質上也是僞隨機數,而且是弱僞隨機數(基於系統時間的seed):
private static final Random RANDOM = new Random();
歡迎關注我的個人的博客www.zhijianliu.cn, 虛心求教,有錯誤還請指正輕拍,謝謝
版權聲明:本文出自志健的原創文章,未經博主允許不得轉載