How to generate a random alpha-numeric string?
我一直在寻找一个简单的Java算法来生成伪随机字母数字字符串。在我的情况下,它将被用作唯一的会话/密钥标识符,在
理想情况下,我可以根据我的独特性需求指定长度。例如,生成的长度为12的字符串可能类似于
算法
要生成随机字符串,请连接从可接受符号集随机抽取的字符,直到字符串达到所需的长度。
实施下面是一些生成随机标识符的非常简单和非常灵活的代码。阅读以下信息了解重要的应用说明。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | import java.security.SecureRandom; import java.util.Locale; import java.util.Objects; import java.util.Random; public class RandomString { /** * Generate a random string. */ public String nextString() { for (int idx = 0; idx < buf.length; ++idx) buf[idx] = symbols[random.nextInt(symbols.length)]; return new String(buf); } public static final String upper ="ABCDEFGHIJKLMNOPQRSTUVWXYZ"; public static final String lower = upper.toLowerCase(Locale.ROOT); public static final String digits ="0123456789"; public static final String alphanum = upper + lower + digits; private final Random random; private final char[] symbols; private final char[] buf; public RandomString(int length, Random random, String symbols) { if (length < 1) throw new IllegalArgumentException(); if (symbols.length() < 2) throw new IllegalArgumentException(); this.random = Objects.requireNonNull(random); this.symbols = symbols.toCharArray(); this.buf = new char[length]; } /** * Create an alphanumeric string generator. */ public RandomString(int length, Random random) { this(length, random, alphanum); } /** * Create an alphanumeric strings from a secure generator. */ public RandomString(int length) { this(length, new SecureRandom()); } /** * Create session identifiers. */ public RandomString() { this(21); } } |
使用实例
为8个字符的标识符创建不安全的生成器:
1 | RandomString gen = new RandomString(8, ThreadLocalRandom.current()); |
为会话标识符创建安全生成器:
1 | RandomString session = new RandomString(); |
创建一个具有易于阅读的打印代码的生成器。字符串比完整的字母数字字符串长,以补偿使用较少的符号:
1 2 | String easy = RandomString.digits +"ACEFGHJKLMNPQRUVWXYabcdefhijkprstuvwx"; RandomString tickets = new RandomString(23, new SecureRandom(), easy); |
用作会话标识符
生成可能是唯一的会话标识符还不够好,或者您可以只使用一个简单的计数器。攻击者在使用可预测的标识符时劫持会话。
长度和安全性之间存在紧张关系。更短的标识符更容易猜测,因为可能性更小。但是更长的标识符消耗更多的存储和带宽。较大的符号集有帮助,但如果URL中包含标识符或手工重新输入,则可能会导致编码问题。
会话标识符的随机性或熵的基本来源应该来自为加密设计的随机数生成器。然而,初始化这些生成器有时计算起来很昂贵或很慢,因此应该尽可能地重新使用它们。
用作对象标识符并非每个应用程序都需要安全性。随机分配可以是多个实体在共享空间中生成标识符而不需要任何协调或分区的有效方法。协调可能很慢,尤其是在集群或分布式环境中,当实体最终共享的共享太小或太大时,拆分空间会导致问题。
如果攻击者可能能够查看和操作标识符(大多数Web应用程序中都是这样),则应采用其他方法保护在不采取措施使其不可预测的情况下生成的标识符。应该有一个单独的授权系统来保护对象,这些对象的标识符可以被攻击者在没有访问权限的情况下猜到。
考虑到预期的标识符总数,还必须注意使用足够长的标识符,以避免发生冲突。这被称为"生日悖论"。碰撞概率P约为n2/(2q x),其中n是实际生成的标识符数量,q是字母表中不同符号的数量,x是标识符的长度。这应该是一个非常小的数字,比如2&8209;50或更少。
计算结果表明,500k15字符标识符之间发生碰撞的可能性约为2&8209;52,这可能比宇宙射线等未检测到的错误要小。
与UUID比较根据它们的规范,UUID的设计并不是不可预测的,不应该用作会话标识符。
标准格式的uuid占用了很大的空间:36个字符的熵只有122位。(并非"随机"UUID的所有位都是随机选择的。)随机选择的字母数字字符串只需21个字符就可以包含更多的熵。
UUID不灵活;它们具有标准化的结构和布局。这是他们的主要美德,也是他们的主要弱点。当与外部合作时,UUID提供的标准化可能会有所帮助。对于纯粹的内部使用,它们可能效率低下。
Java提供了一种直接执行此操作的方法。如果你不想要破折号,它们很容易去掉。只需使用EDOCX1[0]
1 2 3 4 5 6 7 8 9 10 11 12 |
输出:
1 | uuid = 2d7428a6-b58c-4008-8575-f05549f16316 |
1 2 3 4 5 6 7 8 9 | static final String AB ="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; static SecureRandom rnd = new SecureRandom(); String randomString( int len ){ StringBuilder sb = new StringBuilder( len ); for( int i = 0; i < len; i++ ) sb.append( AB.charAt( rnd.nextInt(AB.length()) ) ); return sb.toString(); } |
如果您愿意使用Apache类,那么可以使用
例子:
1 2 3 4 5 6 | RandomStringGenerator randomStringGenerator = new RandomStringGenerator.Builder() .withinRange('0', 'z') .filteredBy(CharacterPredicates.LETTERS, CharacterPredicates.DIGITS) .build(); randomStringGenerator.generate(12); // toUpperCase() if you want |
由于通用语言3.6,
在一行中:
您可以为此使用Apache库:randomstringutils
1 | RandomStringUtils.randomAlphanumeric(20).toUpperCase(); |
这在没有任何外部库的情况下很容易实现。
1。密码伪随机数据生成首先,您需要一个加密prng。Java具有EDOCX1×0,因为它通常使用机器上的最佳熵源(例如EDCOX1×1)。在这里阅读更多。
1 2 3 |
注意:EDCOX1×0是Java中产生随机字节的最慢但最安全的方式。但是,我建议不要在这里考虑性能,因为它通常不会对应用程序产生真正的影响,除非您必须每秒生成数百万个令牌。
2。可能值的所需空间接下来,您必须决定您的令牌需要"多独特"。考虑熵的唯一目的是确保系统能够抵御蛮力攻击:可能值的空间必须如此之大,以至于任何攻击者只能在非滑稽的时间1中尝试可忽略的一部分值。唯一的标识符,如随机
对于简单的需求,8或12字节的长度可能就足够了,但是对于16字节,您就处于"安全方面"。
基本上就是这样。最后一件事是考虑编码,这样它就可以表示为可打印的文本(读,一个
典型编码包括:
Base64 每个字符编码6bit,产生33%的开销。幸运的是,Java 8 +和Android中有标准的实现。使用较老的Java,您可以使用众多的第三方库中的任何一个。如果希望令牌是URL安全的,请使用URL安全版本的rfc4648(大多数实现通常都支持该版本)。带填充的16字节编码示例:XfJhfv3C0P6ag7y9VQxSbw== 。Base32 每个字符编码5bit,产生40%的开销。这将使用A-Z 和2-7 ,使其具有合理的空间效率,同时不区分大小写的字母数字。JDK中没有标准实现。不带填充的16字节编码示例:WUPIL5DQTZGMF4D3NX5L7LNFOY 。EDOCX1(hex)每个字符编码4位,每个字节需要2个字符(即16字节创建长度为32的字符串)。因此,hex比
Base32 的空间效率低,但在大多数情况下(url)使用安全,因为它只使用0-9 和A 到F 。编码16字节的示例:4fa3dd0f57cb3bf331441ed285b27735 。请参见此处有关转换为十六进制的SO讨论。
额外的编码,如base85和异国情调的base122存在更好/更差的空间效率。您可以创建自己的编码(这基本上是这个线程中的大多数答案),但是如果您没有非常具体的需求,我建议您不要使用它。请参阅维基百科文章中的更多编码方案。
4。总结和示例- 使用
SecureRandom 。 - 使用至少16个字节(2^128)的可能值
- 根据您的要求进行编码(如果您需要字母数字,通常为
hex 或Base32 )
不要
- …使用您自己的BREW编码:如果其他人看到您使用的标准编码而不是奇怪的用于一次创建字符的循环,那么他们可以更好地维护和可读。
- …使用uuid:它不能保证随机性;您浪费了6比特的熵,并且有冗长的字符串表示。
示例:十六进制令牌生成器
1 2 3 4 5 6 7 8 | public static String generateRandomHexToken(int byteLength) { SecureRandom secureRandom = new SecureRandom(); byte[] token = new byte[byteLength]; secureRandom.nextBytes(token); return new BigInteger(1, token).toString(16); //hex encoding } //generateRandomHexToken(16) -> 2189df7475e96aa3982dbeab266497cd |
示例:base64令牌生成器(URL安全)
1 2 3 4 5 6 7 8 | public static String generateRandomBase64Token(int byteLength) { SecureRandom secureRandom = new SecureRandom(); byte[] token = new byte[byteLength]; secureRandom.nextBytes(token); return Base64.getUrlEncoder().withoutPadding().encodeToString(token); //base64 encoding } //generateRandomBase64Token(16) -> EEcCCAYuUcQk7IuzdaPzrg |
示例:JAVA CLI工具
如果您想要一个随时可用的cli工具,您可以使用dice:https://github.com/patrickfav/dice
使用美元应简单如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
它输出类似这样的结果:
1 2 3 4 5 | DKL1SBH9UJWC JH7P0IT21EA5 5DTI72EO6SFU HQUMJTEBNF7Y 1HCR6SKYWGT7 |
令人惊讶的是,这里没有人建议这样做,但:
1 2 3 | import java.util.UUID UUID.randomUUID().toString(); |
容易的。
这样做的好处是UUID很好而且很长,而且保证几乎不可能发生碰撞。
维基百科对此有很好的解释:
" ...only after generating 1 billion UUIDs every second for the next 100 years, the probability of creating just one duplicate would be about 50%."
http://en.wikipedia.org/wiki/universally_unique_identifier random_uid_probability_of_duplicates
前4位是版本类型,2位是变量,所以随机得到122位。因此,如果您愿意,可以从末尾截断以减小UUID的大小。这是不推荐的,但你仍然有大量的随机性,足够你的500K记录容易。
这里是Java语言:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | import static java.lang.Math.round; import static java.lang.Math.random; import static java.lang.Math.pow; import static java.lang.Math.abs; import static java.lang.Math.min; import static org.apache.commons.lang.StringUtils.leftPad public class RandomAlphaNum { public static String gen(int length) { StringBuffer sb = new StringBuffer(); for (int i = length; i > 0; i -= 12) { int n = min(12, abs(i)); sb.append(leftPad(Long.toString(round(random() * pow(36, n)), 36), n, '0')); } return sb.toString(); } } |
下面是一个运行示例:
1 2 |
一个简单而简短的解决方案,但只使用小写和数字:
1 2 |
它的大小大约是12位数,以36为基数,因此无法进一步改进。当然,您可以附加多个实例。
Java 8中的另一种选择是:
1 2 3 4 5 6 7 8 9 10 | static final Random random = new Random(); // Or SecureRandom static final int startChar = (int) '!'; static final int endChar = (int) '~'; static String randomString(final int maxLength) { final int length = random.nextInt(maxLength + 1); return random.ints(length, startChar, endChar + 1) .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append) .toString(); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 | public static String generateSessionKey(int length){ String alphabet = new String("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"); //9 int n = alphabet.length(); //10 String result = new String(); Random r = new Random(); //11 for (int i=0; i<length; i++) //12 result = result + alphabet.charAt(r.nextInt(n)); //13 return result; } |
使用UUID是不安全的,因为UUID的某些部分根本不是随机的。@erickson的过程非常整洁,但不会创建相同长度的字符串。以下代码段应该足够:
1 2 3 4 5 6 7 8 9 10 11 | /* * The random generator used by this class to create random keys. * In a holder class to defer initialization until needed. */ private static class RandomHolder { static final Random random = new SecureRandom(); public static String randomKey(int length) { return String.format("%"+length+"s", new BigInteger(length*5/*base 32,2^5*/, random) .toString(32)).replace('\u0020', '0'); } } |
为什么选择
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | import java.util.Random; public class passGen{ //Verison 1.0 private static final String dCase ="abcdefghijklmnopqrstuvwxyz"; private static final String uCase ="ABCDEFGHIJKLMNOPQRSTUVWXYZ"; private static final String sChar ="!@#$%^&*"; private static final String intChar ="0123456789"; private static Random r = new Random(); private static String pass =""; public static void main (String[] args) { System.out.println ("Generating pass..."); while (pass.length () != 16){ int rPick = r.nextInt(4); if (rPick == 0){ int spot = r.nextInt(25); pass += dCase.charAt(spot); } else if (rPick == 1) { int spot = r.nextInt (25); pass += uCase.charAt(spot); } else if (rPick == 2) { int spot = r.nextInt (7); pass += sChar.charAt(spot); } else if (rPick == 3){ int spot = r.nextInt (9); pass += intChar.charAt (spot); } } System.out.println ("Generated Pass:" + pass); } } |
所以这只需要在字符串中添加密码…是的,很好。看看……很简单。我写的
我找到了生成随机十六进制编码字符串的解决方案。提供的单元测试似乎符合我的主要用例。尽管如此,它比提供的其他一些答案稍微复杂一些。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | /** * Generate a random hex encoded string token of the specified length * * @param length * @return random hex string */ public static synchronized String generateUniqueToken(Integer length){ byte random[] = new byte[length]; Random randomGenerator = new Random(); StringBuffer buffer = new StringBuffer(); randomGenerator.nextBytes(random); for (int j = 0; j < random.length; j++) { byte b1 = (byte) ((random[j] & 0xf0) >> 4); byte b2 = (byte) (random[j] & 0x0f); if (b1 < 10) buffer.append((char) ('0' + b1)); else buffer.append((char) ('A' + (b1 - 10))); if (b2 < 10) buffer.append((char) ('0' + b2)); else buffer.append((char) ('A' + (b2 - 10))); } return (buffer.toString()); } @Test public void testGenerateUniqueToken(){ Set set = new HashSet(); String token = null; int size = 16; /* Seems like we should be able to generate 500K tokens * without a duplicate */ for (int i=0; i<500000; i++){ token = Utility.generateUniqueToken(size); if (token.length() != size * 2){ fail("Incorrect length"); } else if (set.contains(token)) { fail("Duplicate token generated"); } else{ set.add(token); } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | import java.util.Date; import java.util.Random; public class RandomGenerator { private static Random random = new Random((new Date()).getTime()); public static String generateRandomString(int length) { char[] values = {'a','b','c','d','e','f','g','h','i','j', 'k','l','m','n','o','p','q','r','s','t', 'u','v','w','x','y','z','0','1','2','3', '4','5','6','7','8','9'}; String out =""; for (int i=0;i<length;i++) { int idx=random.nextInt(values.length); out += values[idx]; } return out; } } |
根据需要更改字符串。
字符串是不可变的。这里,
1 2 3 4 5 6 7 8 9 10 | public static String getRandomString(int length) { final String characters ="abcdefghijklmnopqrstuvwxyzABCDEFGHIJLMNOPQRSTUVWXYZ1234567890!@#$%^&*()_+"; StringBuilder result = new StringBuilder(); while(length > 0) { Random rand = new Random(); result.append(characters.charAt(rand.nextInt(characters.length()))); length--; } return result.toString(); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | import java.util.*; import javax.swing.*; public class alphanumeric{ public static void main(String args[]){ String nval,lenval; int n,len; nval=JOptionPane.showInputDialog("Enter number of codes you require :"); n=Integer.parseInt(nval); lenval=JOptionPane.showInputDialog("Enter code length you require :"); len=Integer.parseInt(lenval); find(n,len); } public static void find(int n,int length) { String str1="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; StringBuilder sb=new StringBuilder(length); Random r = new Random(); System.out.println(" \t Unique codes are "); for(int i=0;i<n;i++){ for(int j=0;j<length;j++){ sb.append(str1.charAt(r.nextInt(str1.length()))); } System.out.println(" "+sb.toString()); sb.delete(0,length); } } } |
对于"简单"解决方案,不太喜欢这些答案:
我要一个简单的),纯Java,一个线性(熵是基于随机字符串长度和给定字符集):
1 2 3 4 5 6 7 8 9 10 | public String randomString(int length, String characterSet) { return IntStream.range(0, length).map(i -> new SecureRandom().nextInt(characterSet.length())).mapToObj(randomInt -> characterSet.substring(randomInt, randomInt + 1)).collect(Collectors.joining()); } @Test public void buildFiveRandomStrings() { for (int q = 0; q < 5; q++) { System.out.println(randomString(10,"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"));//charachterSet can basically be anything } } |
或者(更易读的老方法)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | public String randomString(int length, String characterSet) { StringBuilder sb = new StringBuilder(); //consider using StringBuffer if needed for (int i = 0; i < length; i++) { int randomInt = new SecureRandom().nextInt(characterSet.length()); sb.append(characterSet.substring(randomInt, randomInt + 1)); } return sb.toString(); } @Test public void buildFiveRandomStrings() { for (int q = 0; q < 5; q++) { System.out.println(randomString(10,"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")); //charachterSet can basically be anything } } |
但另一方面,你也可以使用具有相当好熵的uuid(https://en.wikipedia.org/wiki/universally_unique_identifier collisions):
1 | UUID.randomUUID().toString().replace("-","") |
希望有帮助。
您提到"简单",但是为了防止其他人正在寻找满足更严格安全要求的东西,您可能需要看看JPWGen。jpwgen在UNIX中是根据pwgen建模的,并且是非常可配置的。
可以使用UUID类及其getLeastSignificantBits()消息获取64位随机数据,然后将其转换为基数36数字(即由0-9、a-z组成的字符串):
这将生成一个长达13个字符的字符串。我们使用math.abs()来确保没有负号潜入。
这里是一个scala解决方案:
1 2 3 | (for (i <- 0 until rnd.nextInt(64)) yield { ('0' + rnd.nextInt(64)).asInstanceOf[Char] }) mkString("") |
如果强制密码包含数字、字母和特殊字符,则可以使用以下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | private static final String NUMBERS ="0123456789"; private static final String UPPER_ALPHABETS ="ABCDEFGHIJKLMNOPQRSTUVWXYZ"; private static final String LOWER_ALPHABETS ="abcdefghijklmnopqrstuvwxyz"; private static final String SPECIALCHARACTERS ="@#$%&*"; private static final int MINLENGTHOFPASSWORD = 8; public static String getRandomPassword() { StringBuilder password = new StringBuilder(); int j = 0; for (int i = 0; i < MINLENGTHOFPASSWORD; i++) { password.append(getRandomPasswordCharacters(j)); j++; if (j == 3) { j = 0; } } return password.toString(); } private static String getRandomPasswordCharacters(int pos) { Random randomNum = new Random(); StringBuilder randomChar = new StringBuilder(); switch (pos) { case 0: randomChar.append(NUMBERS.charAt(randomNum.nextInt(NUMBERS.length() - 1))); break; case 1: randomChar.append(UPPER_ALPHABETS.charAt(randomNum.nextInt(UPPER_ALPHABETS.length() - 1))); break; case 2: randomChar.append(SPECIALCHARACTERS.charAt(randomNum.nextInt(SPECIALCHARACTERS.length() - 1))); break; case 3: randomChar.append(LOWER_ALPHABETS.charAt(randomNum.nextInt(LOWER_ALPHABETS.length() - 1))); break; } return randomChar.toString(); } |
这是AbacusUtil的一行代码
1 |
随机并不意味着它必须是唯一的。要获取唯一字符串,请使用:
1 2 | N.uuid() // e.g.:"e812e749-cf4c-4959-8ee1-57829a69a80f". length is 36. N.guid() // e.g.:"0678ce04e18945559ba82ddeccaabfcd". length is 32 without '-' |
1 2 3 4 5 6 7 8 9 10 11 |
使用Apache库可以在一行中完成
1 2 | import org.apache.commons.lang.RandomStringUtils; RandomStringUtils.randomAlphanumeric(64); |
这是文档http://commons.apache.org/lang/api-2.3/org/apache/commons/lang/randomstringutils.html
我认为这是这里最小的解决方案,或几乎是最小的解决方案之一:
1 2 3 4 5 6 7 8 9 10 11 | public String generateRandomString(int length) { String randomString =""; final char[] chars ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890".toCharArray(); final SecureRandom random = new SecureRandom(); for (int i = 0; i < length; i++) { randomString = randomString + chars[random.nextInt(chars.length)]; } return randomString; } |
代码工作得很好。如果您使用此方法,我建议您使用10个以上的字符。碰撞发生在5个字符/30362次迭代中。这花了9秒。
1 2 3 4 5 6 7 8 |
1 2 3 4 5 6 7 8 9 10 11 12 13 | public static String getRandomString(int length) { char[] chars ="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRST".toCharArray(); StringBuilder sb = new StringBuilder(); Random random = new Random(); for (int i = 0; i < chars.length; i++) { char c = chars[random.nextInt(chars.length)]; sb.append(c); } String randomStr = sb.toString(); return randomStr; } |
也许这有帮助
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | package password.generater; import java.util.Random; /** * * @author dell */ public class PasswordGenerater { /** * @param args the command line arguments */ public static void main(String[] args) { int length= 11; System.out.println(generatePswd(length)); // TODO code application logic here } static char[] generatePswd(int len){ System.out.println("Your Password"); String charsCaps="ABCDEFGHIJKLMNOPQRSTUVWXYZ"; String Chars="abcdefghijklmnopqrstuvwxyz"; String nums="0123456789"; String symbols="!@#$%^&*()_+-=.,/';:?><~*/-+"; String passSymbols=charsCaps + Chars + nums +symbols; Random rnd=new Random(); char[] password=new char[len]; for(int i=0; i<len;i++){ password[i]=passSymbols.charAt(rnd.nextInt(passSymbols.length())); } return password; } } |
最佳随机串生成器方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | public class RandomStringGenerator{ private static int randomStringLength = 25 ; private static boolean allowSpecialCharacters = true ; private static String specialCharacters ="!@$%*-_+:"; private static boolean allowDuplicates = false ; private static boolean isAlphanum = false; private static boolean isNumeric = false; private static boolean isAlpha = false; private static final String alphabet ="abcdefghijklmnopqrstuvwxyz"; private static boolean mixCase = false; private static final String capAlpha ="ABCDEFGHIJKLMNOPQRSTUVWXYZ"; private static final String num ="0123456789"; public static String getRandomString() { String returnVal =""; int specialCharactersCount = 0; int maxspecialCharacters = randomStringLength/4; try { StringBuffer values = buildList(); for (int inx = 0; inx < randomStringLength; inx++) { int selChar = (int) (Math.random() * (values.length() - 1)); if (allowSpecialCharacters) { if (specialCharacters.indexOf("" + values.charAt(selChar)) > -1) { specialCharactersCount ++; if (specialCharactersCount > maxspecialCharacters) { while (specialCharacters.indexOf("" + values.charAt(selChar)) != -1) { selChar = (int) (Math.random() * (values.length() - 1)); } } } } returnVal += values.charAt(selChar); if (!allowDuplicates) { values.deleteCharAt(selChar); } } } catch (Exception e) { returnVal ="Error While Processing Values"; } return returnVal; } private static StringBuffer buildList() { StringBuffer list = new StringBuffer(0); if (isNumeric || isAlphanum) { list.append(num); } if (isAlpha || isAlphanum) { list.append(alphabet); if (mixCase) { list.append(capAlpha); } } if (allowSpecialCharacters) { list.append(specialCharacters); } int currLen = list.length(); String returnVal =""; for (int inx = 0; inx < currLen; inx++) { int selChar = (int) (Math.random() * (list.length() - 1)); returnVal += list.charAt(selChar); list.deleteCharAt(selChar); } list = new StringBuffer(returnVal); return list; } } |
您可以创建一个包含所有字母和数字的字符数组,然后从该字符数组中随机选择并创建自己的字符串密码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | char[] chars = new char[62]; // sum of letters and numbers int i = 0; for(char c = 'a'; c <= 'z';c++) { // for letters chars[i++] = c; } for(char c = '0'; c <= '9';c++) { // for numbers chars[i++] = c; } for(char c = 'A'; c <= 'Z';c++) { // for capital letters chars[i++] = c; } int numberOfCodes = 0; String code =""; while (numberOfCodes < 1) {//enter how much you want to generate at one time int numChars = 8; //Enter how many digits you want in your password for(i = 0; i < numChars; i++) { char c = chars[(int)(Math.random() * chars.length)]; code = code + c; } System.out.println("Code is :" + code); } |
这里是基于流的Java 8解决方案。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | public String generateString(String alphabet, int length) { return generateString(alphabet, length, new SecureRandom()::nextInt); } // nextInt = bound -> n in [0, bound) public String generateString(String source, int length, IntFunction<Integer> nextInt) { StringBuilder sb = new StringBuilder(); IntStream.generate(source::length) .boxed() .limit(length) .map(nextInt::apply) .map(source::charAt) .forEach(sb::append); return sb.toString(); } |
像它一样使用它
1 2 3 4 |
函数
上面大量使用了StringBuilder。我想这很简单,但是需要每个字符调用一个函数,增加一个数组等等…如果使用StringBuilder,建议指定字符串所需的容量,即,
1 | new StringBuilder(int capacity); |
这里有一个不使用StringBuilder或字符串附加的版本,并且没有字典。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | public static String randomString(int length) { SecureRandom random = new SecureRandom(); char[] chars = new char[length]; for(int i=0;i<chars.length;i++) { int v = random.nextInt(10 + 26 + 26); char c; if (v < 10) { c = (char)('0' + v); } else if (v < 36) { c = (char)('a' - 10 + v); } else { c = (char)('A' - 36 + v); } chars[i] = c; } return new String(chars); } |
我开发了一个应用程序来为我的项目开发一个自动生成的字母数字字符串。在这个字符串中,前三个字符是按字母顺序排列的,后七个是整数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | public class AlphaNumericGenerator { public static void main(String[] args) { java.util.Random r = new java.util.Random(); int i = 1, n = 0; char c; String str=""; for (int t = 0; t < 3; t++) { while (true) { i = r.nextInt(10); if (i > 5 && i < 10) { if (i == 9) { i = 90; n = 90; break; } if (i != 90) { n = i * 10 + r.nextInt(10); while (n < 65) { n = i * 10 + r.nextInt(10); } } break; } } c=(char)n; str= String.valueOf(c)+str; } while(true){ i = r.nextInt(10000000); if(i>999999) break; } str=str+i; System.out.println(str); } } |
另一个解决方案……
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | public static String generatePassword(int passwordLength) { int asciiFirst = 33; int asciiLast = 126; Integer[] exceptions = { 34, 39, 96 }; List<Integer> exceptionsList = Arrays.asList(exceptions); SecureRandom random = new SecureRandom(); StringBuilder builder = new StringBuilder(); for (int i=0; i<passwordLength; i++) { int charIndex; do { charIndex = random.nextInt(asciiLast - asciiFirst + 1) + asciiFirst; } while (exceptionsList.contains(charIndex)); builder.append((char) charIndex); } return builder.toString(); } |
效率高,短。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | /** * Utility class for generating random Strings. */ public interface RandomUtil { int DEF_COUNT = 20; Random RANDOM = new SecureRandom(); /** * Generate a password. * * @return the generated password */ static String generatePassword() { return generate(true, true); } /** * Generate an activation key. * * @return the generated activation key */ static String generateActivationKey() { return generate(false, true); } /** * Generate a reset key. * * @return the generated reset key */ static String generateResetKey() { return generate(false, true); } static String generate(boolean letters, boolean numbers) { int start = ' ', end = 'z' + 1, count = DEF_COUNT, gap = end - start; StringBuilder builder = new StringBuilder(count); while (count-- != 0) { int codePoint = RANDOM.nextInt(gap) + start; switch (getType(codePoint)) { case UNASSIGNED: case PRIVATE_USE: case SURROGATE: count++; continue; } int numberOfChars = charCount(codePoint); if (count == 0 && numberOfChars > 1) { count++; continue; } if (letters && isLetter(codePoint) || numbers && isDigit(codePoint) || !letters && !numbers) { builder.appendCodePoint(codePoint); if (numberOfChars == 2) count--; } else count++; } return builder.toString(); } } |
这里有一个简单的一行程序,使用UUID作为字符库,可以指定(几乎)任何长度。(是的,我知道以前有人建议使用UUID)
1 2 3 |
此外,您还可以从ASCII表生成任何小写或大写字母,甚至是特殊字符的思想数据。例如,从A(12月65日)到Z(12月90日)生成大写字母:
1 2 3 4 5 6 7 |
为发电机生成的输出(65、90、100));:
1 | TVLPFQJCYFXQDCQSLKUKKILKKHAUFYEXLUQFHDWNMRBIRRRWNXNNZQTINZPCTKLHGHVYWRKEOYNSOFPZBGEECFMCOKWHLHCEWLDZ |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /** Generate a random String with maxlength random characters found in the ASCII table between 33 and 122 (so it contains every lowercase / uppercase letters, numbers and some others characters */ public static String GetRandomString(int maxlength) { String result =""; int i = 0, n = 0, min = 33, max = 122; while(i < maxlength) { n = (int)(Math.random() * (max - min) + min); if(n >= 33 && n < 123) { result += (char)n; ++i; } } return(result); } |
在大小写之间随机10个字母的字符串
1 2 3 4 5 6 7 8 9 10 11 12 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | public class RandomGenerator { private static SecureRandom prng; private static final Logger LOG = LoggerFactory .getLogger(AuthTokenGenerator.class); static { try { // Initialize SecureRandom prng = SecureRandom.getInstance("SHA1PRNG"); } catch (NoSuchAlgorithmException e) { LOG.info("ERROR while intantiating Secure Random: " + prng); } } /** * @return */ public static String getToken() { try { LOG.info("About to Generate Token in getToken()"); String token; // generate a random number String randomNum = Integer.toString(prng.nextInt()); // get its digest MessageDigest sha = MessageDigest.getInstance("SHA-1"); byte[] result = sha.digest(randomNum.getBytes()); token = hexEncode(result); LOG.info("Token in getToken(): " + token); return token; } catch (NoSuchAlgorithmException ex) { return null; } } /** * @param aInput * @return */ private static String hexEncode(byte[] aInput) { StringBuilder result = new StringBuilder(); char[] digits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' }; for (byte b : aInput) { result.append(digits[(b & 0xf0) >> 4]); result.append(digits[b & 0x0f]); } return result.toString(); } } |
可以使用这个简单的Java函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public class GenerateRandomString { private static final String ALPHA_NUM = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; public static void main(String[] args) { GenerateRandomString grs = new GenerateRandomString(); System.out.println(grs.getAlphaNumeric(10)); System.out.println(grs.getAlphaNumeric(20)); } public String getAlphaNumeric(int len) { StringBuffer sb = new StringBuffer(len); for (int i=0; i<len; i++) { int ndx = (int)(Math.random()*ALPHA_NUM.length()); sb.append(ALPHA_NUM.charAt(ndx)); } return sb.toString(); } } |
你可以让它变得困难:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 | package gaming; import java.util.Random; public class game2 { public static char c; public static Random r = new Random(); public static int i = r.nextInt(25); public static int i2 = r.nextInt(25); public static int i3 = r.nextInt(25); public static int i4= r.nextInt(25); public static int i5 = r.nextInt(25); public static int num2 = r.nextInt(9); public static int num3= r.nextInt(9); public static String s1 = String.valueOf(num2); public static String s2 = String.valueOf(num3); public static void main(String[] args){ System.out.print("The pin is:"); changeToString(i); System.out.print(c); changeToString(i2); System.out.print(c); changeToString(i3); System.out.print(c); changeToString(i4); System.out.print(c); changeToString(i5); System.out.print(c); System.out.print(s1); System.out.print(s2); } public static void changeToString(int rand){ switch (rand){ case 0: c = 'A'; break; case 1: c = 'B'; break; case 2: c = 'C'; break; case 3: c = 'D'; break; case 4: c = 'E'; break; case 5: c = 'F'; break; case 6: c = 'G'; break; case 7: c = 'H'; break; case 8: c = 'I'; break; case 9: c = 'J'; break; case 10: c = 'K'; break; case 11: c = 'L'; break; case 12: c = 'M'; break; case 13: c = 'N'; break; case 14: c = 'O'; break; case 15: c = 'P'; break; case 16: c = 'Q'; break; case 17: c = 'R'; break; case 18: c = 'S'; break; case 19: c = 'T'; break; case 20: c = 'U'; break; case 21: c = 'V'; break; case 22: c = 'W'; break; case 23: c = 'X'; break; case 24: c = 'Y'; break; case 25: c = 'Z'; break; } } } |