编程过程中经常会有产生随机数的需求,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, 虚心求教,有错误还请指正轻拍,谢谢
版权声明:本文出自志健的原创文章,未经博主允许不得转载