java安全随机数_Java随机数的陷阱
前言
随机数我们应该不陌生,业务中我们用它来生成验证码,或者对重复性要求不高的id,甚至我们还用它在年会上搞抽奖。今天我们来探讨一下这个东西。如果使用不当会引发一系列问题。
Java中的随机数
我们需要在Java中随机生成一个数字。java开发中我们通常使用java.util.Random来搞,它提供了一种伪随机的生成机制。Jvm 通过传入的种子(seed)来确定生成随机数的区间,只要种子一样,获取的随机数的序列就是一致的。而且生成的结果都是可以预测的。是一种伪随机数的实现,而不是真正的随机数。来确定使用的但是有些用例直接使用可能会导致一些意想不到的问题。Random的一个普遍用法:
// Random 实例
Random random = new Random();
//调用 nextInt() 方法 此外还有nextDouble(), nextBoolean(), nextFloat(), ...
random.nextInt();
或者,我们可以使用java中的数学计算类:
Math.random();
Math类只包含一个Random实例来生成随机数:
publicstaticdoublerandom() {
Random rnd = randomNumberGenerator;
if (rnd == null) {
// 返回一个新的Random实例
rnd = initRNG();
}
returnrnd.nextDouble();
}
java.util.Random的用法是线程安全的。但是,在不同线程上并发使用相同的Random实例可能会导致争用,从而导致性能不佳。其原因是使用所谓的种子来生成随机数。种子是一个简单的数字,它为生成新的随机数提供了基础。我们来看看Random中的next(int bits)方法:
protectedintnext(intbits) {
long oldseed, nextseed;
AtomicLong seed = this.seed;
do {
oldseed = seed.get();
nextseed = (oldseed * multiplier addend) & mask;
} while (!seed.compareAndSet(oldseed, nextseed));
return(int)(nextseed >>> (48 - bits));}
首先,旧种子和新种子存储在两个辅助变量上。在这一点上,创造新种子的原则并不重要。要保存新种子,使用compareAndSet()方法将旧种子替换为下一个新种子,但这仅仅在旧种子对应于当前设置的种子的条件下才会触发。如果此时的值由并发线程操纵,则该方法返回false,这意味着旧值与例外值不匹配。因为是循环内进行的操作,那么会发生自旋,直到变量与例外值匹配。这可能会导致性能不佳和线程竞争。
多线程下的随机数
如果更多线程主动生成具有相同Random的实例的新随机数,则上述情况发生的概率越高。对于生成许多(非常多)随机数的程序,不建议使用这种方式。在这种情况下,您应该使用ThreadLocalRandom,它在1.7版本中添加到Java中。ThreadLocalRandom扩展了Random并添加选项以限制其使用到相应的线程实例。为此,ThreadLocalRandom的实例保存在相应线程的内部映射中,并通过调用current()来返回对应的Random。使用方式如下:
ThreadLocalRandom.current().nextInt()
安全的随机数
通过对Random的一些分析我们可以知道Random事实上是伪随机,是可以推导出规律的,而且依赖种子(seed)。如果我们搞抽奖或者其他一些对随机数敏感的场景时,用Random就不合适了,容易被人钻空子。JDK提供了SecureRandom来解决这个事情。
SecureRandom是强随机数生成器,它可以产生高强度的随机数,产生高强度的随机数依赖两个重要的因素:种子和算法。算法是可以有很多的,通常如何选择种子是非常关键的因素。 Random的种子是System.currentTimeMillis(),所以它的随机数都是可预测的, 是弱伪随机数。强伪随机数的生成思路:收集计算机的各种信息,键盘输入时间,内存使用状态,硬盘空闲空间,IO延时,进程数量,线程数量等信息,CPU时钟,来得到一个近似随机的种子,主要是达到不可预测性。说的更通俗就是,使用加密算法生成很长的一个随机种子,让你无法猜测出种子,也就无法推导出随机序列数。
总结
今天我们探讨了业务中经常使用的随机数的一些机制和一些场景下的一些陷阱,希望你在使用随机数的时候能避免这种陷阱。
【编辑推荐】
【责任编辑:华轩 TEL:(010)68476606】
点赞 0
java安全随机数_Java随机数的陷阱相关推荐
- java 随机数生成算法_Java随机数的生成算法
Java中随机数的生成算法主要有3种 1.Math.random()//产生一个0-1之间的随机数,类型为double类型 2.new Random() random.nextInextInt(100 ...
- java replaceall 括号_Java replaceAll的陷阱之括弧
大家都知道,replaceAll这个东西支持regular expression的.不过.. 如果你要replace 中括号怎么办? str.replaceAll("[]",&qu ...
- java 随机数生成实现_Java中生成随机数的实现方法总结
搜索热词 在实际开发工作中经常需要用到随机数.如有些系统中创建用户后会给用户一个随机的初始化密码.这个密码由于是随机的,为此往往只有用户自己知道.他们获取了这个随机密码之后,需要马上去系统中更改.这就 ...
- java获取10位随机数_Java基础:JAVA中BitSet使用详解
适用场景:整数,无重复: Bitset 基础 Bitset,也就是位图,由于可以用非常紧凑的格式来表示给定范围的连续数据而经常出现在各种算法设计中.上面的图来自c++库中bitset的一张图. 基本原 ...
- java生成永远不重复的随机数_java生成不重复随机数的方法
java生成不重复随机数的方法 发布时间:2020-07-01 11:00:00 来源:亿速云 阅读:225 作者:Leah java怎么实现生成不重复随机数 ?针对这个问题,这篇文章详细介绍了相对应 ...
- java 获取区间随机数_Java获取随机数的3种方法
主要介绍了Java获取随机数的3种方法,主要利用random()函数来实现 方法1 (数据类型)(最小值+Math.random()*(最大值-最小值+1))例: (int)(1+Math.rando ...
- java中的随机数_Java获取随机数
随机数在实际中使用很广泛,比如要随即生成一个固定长度的字符串.数字.或者随即生成一个不定长度的数字.或者进行一个模拟的随机选择等等.Java提供了最基本的工具,可以帮助开发者来实现这一切. 一.Jav ...
- java 获取区间随机数_Java获取随机数的几种方法
随机数在实际中使用很广泛,比如要随即生成一个固定长度的字符串.数字.或者随即生成一个不定长度的数字.或者进行一个模拟的随机选择等等.Java提供了最基本的工具,可以帮助开发者来实现这一切. 一.Jav ...
- java 怎么产生随机数_Java怎么产生随机数
一.利用random方法来生成随机数.在Java语言中生成随机数相对来说比较简单,因为有一个现成的方法可以使用.在Math类中,Java语言提供了一个叫做random的方法.通过这个方法可以让系统产生 ...
最新文章
- 【Visual C++】游戏开发笔记四十一 浅墨DirectX教程之九 为三维世界添彩:纹理映射技术(一)...
- 在ASP.NET2.0中的的UrlRewrite
- 华为手机业务网络推广外包持续受限,在当前市场下还能做些什么?
- word 2010中如何创建多级目录和多级列表
- Linux shutdown关机命令
- 初级php工程师应该具备什么,一名合格的PHP工程师需要掌握的知识结构
- mysql解释器_atitit.java解析sql语言解析器解释器的实现
- Maven打包时去掉项目版本号
- 安卓开发 登录用户信息缓存_在Linux上使用finger命令查询登录用户信息
- 查看华为应用商店APPID
- 我是学Java的,为什么要我装JDK
- git 远程代码回滚master
- PS中rename-item的一些高级应用
- 实例详解机器学习如何解决问题
- smarty缓存控制
- 刷机常识,双清,BL,REC,TWRP
- 计算机视觉课程-SIFT算法特征检测
- 惠普电脑BIOS设置图文详细介绍
- 单片机可以替代PLC吗?
- 简述面向过程与面向过程的思想