关于Java:如何生成一个随机的字母数字字符串?

How to generate a random alpha-numeric string?

我一直在寻找一个简单的Java算法来生成伪随机字母数字字符串。在我的情况下,它将被用作唯一的会话/密钥标识符,在500K+代上"可能"是唯一的(我的需求实际上并不需要任何更复杂的东西)。

理想情况下,我可以根据我的独特性需求指定长度。例如,生成的长度为12的字符串可能类似于"AEYGF7K0DM1X"


算法

要生成随机字符串,请连接从可接受符号集随机抽取的字符,直到字符串达到所需的长度。

实施

下面是一些生成随机标识符的非常简单和非常灵活的代码。阅读以下信息了解重要的应用说明。

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
import java.util.UUID;

public class randomStringGenerator {
    public static void main(String[] args) {
        System.out.println(generateString());
    }

    public static String generateString() {
        String uuid = UUID.randomUUID().toString();
        return"uuid =" + uuid;
    }
}

输出:

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类,那么可以使用org.apache.commons.text.RandomStringGenerator(commons文本)。

例子:

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,RandomStringUtils被否决。


在一行中:

1
Long.toHexString(Double.doubleToLongBits(Math.random()));

java generating random string


您可以为此使用Apache库:randomstringutils

1
RandomStringUtils.randomAlphanumeric(20).toUpperCase();


这在没有任何外部库的情况下很容易实现。

1。密码伪随机数据生成

首先,您需要一个加密prng。Java具有EDOCX1×0,因为它通常使用机器上的最佳熵源(例如EDCOX1×1)。在这里阅读更多。

1
2
3
SecureRandom rnd = new SecureRandom();
byte[] token = new byte[byteLength];
rnd.nextBytes(token);

注意:EDCOX1×0是Java中产生随机字节的最慢但最安全的方式。但是,我建议不要在这里考虑性能,因为它通常不会对应用程序产生真正的影响,除非您必须每秒生成数百万个令牌。

2。可能值的所需空间

接下来,您必须决定您的令牌需要"多独特"。考虑熵的唯一目的是确保系统能够抵御蛮力攻击:可能值的空间必须如此之大,以至于任何攻击者只能在非滑稽的时间1中尝试可忽略的一部分值。唯一的标识符,如随机UUID有122位的熵(即2^122=5.3x10^36),碰撞的可能性是"*(……)如果要有十亿分之一的重复机会,必须生成103万亿版本的4 UUID"。我们将选择128位,因为它正好适合16个字节,并且被视为基本上对每个(但最极端的)用例都是唯一的,并且您不必考虑重复。这里是一个简单的熵比较表,包括对生日问题的简单分析。

comparison of token sizes

对于简单的需求,8或12字节的长度可能就足够了,但是对于16字节,您就处于"安全方面"。

基本上就是这样。最后一件事是考虑编码,这样它就可以表示为可打印的文本(读,一个String)。

三。二进制到文本编码

典型编码包括:

  • Base64每个字符编码6bit,产生33%的开销。幸运的是,Java 8 +和Android中有标准的实现。使用较老的Java,您可以使用众多的第三方库中的任何一个。如果希望令牌是URL安全的,请使用URL安全版本的rfc4648(大多数实现通常都支持该版本)。带填充的16字节编码示例:XfJhfv3C0P6ag7y9VQxSbw==

  • Base32每个字符编码5bit,产生40%的开销。这将使用A-Z2-7,使其具有合理的空间效率,同时不区分大小写的字母数字。JDK中没有标准实现。不带填充的16字节编码示例:WUPIL5DQTZGMF4D3NX5L7LNFOY

  • EDOCX1(hex)每个字符编码4位,每个字节需要2个字符(即16字节创建长度为32的字符串)。因此,hex比Base32的空间效率低,但在大多数情况下(url)使用安全,因为它只使用0-9AF。编码16字节的示例:4fa3dd0f57cb3bf331441ed285b27735。请参见此处有关转换为十六进制的SO讨论。

额外的编码,如base85和异国情调的base122存在更好/更差的空间效率。您可以创建自己的编码(这基本上是这个线程中的大多数答案),但是如果您没有非常具体的需求,我建议您不要使用它。请参阅维基百科文章中的更多编码方案。

4。总结和示例

  • 使用SecureRandom
  • 使用至少16个字节(2^128)的可能值
  • 根据您的要求进行编码(如果您需要字母数字,通常为hexBase32)

不要

  • …使用您自己的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
//"0123456789" +"ABCDE...Z"
String validCharacters = $('0', '9').join() + $('A', 'Z').join();

String randomString(int length) {
    return $(validCharacters).shuffle().slice(length).toString();
}

@Test
public void buildFiveRandomStrings() {
    for (int i : $(5)) {
        System.out.println(randomString(12));
    }
}

它输出类似这样的结果:

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
scala> RandomAlphaNum.gen(42)
res3: java.lang.String = uja6snx21bswf9t89s00bxssu8g6qlu16ffzqaxxoy


一个简单而简短的解决方案,但只使用小写和数字:

1
2
Random r = new java.util.Random ();
String s = Long.toString (r.nextLong () & Long.MAX_VALUE, 36);

它的大小大约是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');
    }
}

为什么选择length*5。让我们假设一个长度为1的随机字符串的简单情况,那么一个随机字符。要得到一个包含所有数字0-9和字符a-z的随机字符,我们需要一个介于0和35之间的随机数字来获得每个字符中的一个。BigInteger提供了一个构造函数来生成一个随机数,在0 to (2^numBits - 1)的范围内均匀分布。不幸的是,35不是2^numbits-1可以接收的数字。所以我们有两种选择:要么选择2^5-1=312^6-1=63。如果我们选择2^6,我们会得到很多"不必要的"/"更长的"数字。因此,即使我们释放了4个字符(w-z),2^5也是更好的选择。现在要生成一个特定长度的字符串,我们可以简单地使用2^(length*numBits)-1号。最后一个问题,如果我们想要一个有一定长度的字符串,随机可以生成一个小数字,所以长度是不满足的,所以我们必须将字符串填充到它所需要的长度,并加上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;
    }
}

  • 根据需要更改字符串。

  • 字符串是不可变的。这里,StringBuilder.append比字符串连接更有效。

  • 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组成的字符串):

    1
    Long.toString(Math.abs( UUID.randomUUID().getLeastSignificantBits(), 36));

    这将生成一个长达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
    String.valueOf(CharStream.random('0', 'z').filter(c -> N.isLetterOrDigit(c)).limit(12).toArray())

    随机并不意味着它必须是唯一的。要获取唯一字符串,请使用:

    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
    public static String randomSeriesForThreeCharacter() {
        Random r = new Random();
        String value="";
        char random_Char ;
        for(int i=0; i<10;i++)
        {
            random_Char = (char) (48 + r.nextInt(74));
            value=value+random_char;
        }
        return value;
    }


    使用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
    public static String getRandomString(int length)
    {
       String randomStr = UUID.randomUUID().toString();
       while(randomStr.length() < length) {
           randomStr += UUID.randomUUID().toString();
       }
       return randomStr.substring(0, length);
    }


    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
    String alphabet ="ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    int length = 12;
    String generated = generateString(alphabet, length);
    System.out.println(generated);

    函数nextInt应接受int bound并返回0bound - 1之间的随机数。


    上面大量使用了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
    public static String randString(int length) {
        return UUID.randomUUID().toString().replace("-","").substring(0, Math.min(length, 32)) + (length > 32 ? randString(length - 32) :"");
    }

    此外,您还可以从ASCII表生成任何小写或大写字母,甚至是特殊字符的思想数据。例如,从A(12月65日)到Z(12月90日)生成大写字母:

    1
    2
    3
    4
    5
    6
    7
    String generateRandomStr(int min, int max, int size) {
        String result ="";
        for (int i = 0; i < size; i++) {
            result += String.valueOf((char)(new Random().nextInt((max - min) + 1) + min));
        }
        return result;
    }

    为发电机生成的输出(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
    StringBuilder randomString = new StringBuilder();  
    Random random = new Random();
    boolean alphaType = true;
    int j;

    for(int i = 0; i <= 9; ++i)
    {
        j = (random.nextInt(25) + (alphaType == true ? 65 : 97));
        randomString.append((char)j);
        alphaType = !alphaType;
    }
    return randomString.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
    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;

        }

    }
    }