在实际项目中碰到一个需要生成唯一不重复的16位随机码问题,该随机码还需要包含数字和大小写的英文字母,于是利用java中的SecureRandom
强随机函数来实现取值逻辑,网上提到的生成随机数的方法主要有三种:
- Math.random() 随机数
- java.util.Random 伪随机数(线性同余法生成)
- java.security.SecureRandom 真随机数
随机数,采用的是类似于统计学的随机数生成规则,其输出结果很容易预测,因此可能导致被攻击者击中。而真随机数,采用的是类似于密码学的随机数生成规则,其输出结果较难预测,若想要预防被攻击者攻击,最好做到使攻击者根本无法,或不可能鉴别生成的随机值和真正的随机值。在商业上,能经得起生产工业使用的一般推荐第三种生成方法,此处也是采用强随机数进行16位随机码的实现:
/**
* 生成16位不重复的随机数,含数字+大小写
* @return
*/
public static String getGUID() {
StringBuilder uid = new StringBuilder();
//产生16位的强随机数
Random rd = new SecureRandom();
for (int i = 0; i < 16; i++) {
//产生0-2的3位随机数
int type = rd.nextInt(3);
switch (type){
case 0:
//0-9的随机数
uid.append(rd.nextInt(10));
break;
case 1:
//ASCII在65-90之间为大写,获取大写随机
uid.append((char)(rd.nextInt(25)+65));
break;
case 2:
//ASCII在97-122之间为小写,获取小写随机
uid.append((char)(rd.nextInt(25)+97));
break;
default:
break;
}
}
return uid.toString();
}
实际执行100条循环耗时大约6ms,每条执行大约0.06ms,效率可以保证在高并发环境下的使用,但是难以保证该随机数在海量数据的情况下强唯一性,可能会存在一定的碰撞几率,尽管这种几率并不是太大。
网友评论