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

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

有帮助吗?

解决方案

算法

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

执行

这是一些相当简单且非常灵活的代码,用于生成随机标识符。 阅读以下信息 重要的应用笔记。

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 字符标识符创建一个不安全的生成器:

RandomString gen = new RandomString(8, ThreadLocalRandom.current());

为会话标识符创建安全生成器:

RandomString session = new RandomString();

创建一个具有易于阅读的打印代码的生成器。这些字符串比完整的字母数字字符串更长,以补偿使用较少的符号:

String easy = RandomString.digits + "ACEFGHJKLMNPQRUVWXYabcdefhijkprstuvwx";
RandomString tickets = new RandomString(23, new SecureRandom(), easy);

用作会话标识符

生成可能唯一的会话标识符还不够好,或者您可以只使用一个简单的计数器。当使用可预测的标识符时,攻击者会劫持会话。

长度和安全性之间存在紧张关系。较短的标识符更容易猜测,因为可能性较小。但较长的标识符会消耗更多的存储和带宽。较大的符号集会有所帮助,但如果标识符包含在 URL 中或手动重新输入,则可能会导致编码问题。

会话标识符的随机性或熵的基本来源应该来自为密码学设计的随机数生成器。然而,初始化这些生成器有时在计算上可能会很昂贵或很慢,因此应尽可能重用它们。

用作对象标识符

并非每个应用程序都需要安全性。随机分配可以是多个实体在共享空间中生成标识符而无需任何协调或分区的有效方式。协调可能会很慢,尤其是在集群或分布式环境中,并且当实体最终拥有太小或太大的份额时,分割空间会导致问题。

如果攻击者能够查看和操纵未采取措施使其不可预测的标识符,则应通过其他方式对其进行保护(就像大多数 Web 应用程序中发生的情况一样)。应该有一个单独的授权系统来保护其标识符可以在没有访问权限的情况下被攻击者猜测的对象。

还必须注意使用足够长的标识符,以在考虑到标识符的预期总数的情况下不太可能发生冲突。这被称为“生日悖论”。 发生碰撞的概率, p, 大约为 n2/(2qX), 在哪里 n 是实际生成的标识符的数量, q 是字母表中不同符号的数量,并且 X 是标识符的长度。这应该是一个非常小的数字,比如 2‑50 或更少。

计算结果表明,500k 15 个字符的标识符之间发生冲突的几率约为 2‑52, ,这可能比宇宙射线等未检测到的错误的可能性要小。

与 UUID 的比较

根据他们的规范,UUID 的设计不是不可预测的,并且 不应该 用作会话标识符。

标准格式的 UUID 占用大量空间:36 个字符只有 122 位熵。(并非“随机”UUID 的所有位都是随机选择的。)随机选择的字母数字字符串在短短 21 个字符中包含了更多的熵。

UUID 不灵活;它们具有标准化的结构和布局。这是他们的主要优点,也是他们的主要弱点。与外部方合作时,UUID 提供的标准化可能会有所帮助。对于纯粹的内部使用,它们可能效率低下。

其他提示

Java 提供了一种直接执行此操作的方法。如果你不需要破折号,它们很容易去掉。只需使用 uuid.replace("-", "")

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;
    }
}

输出:

uuid = 2d7428a6-b58c-4008-8575-f05549f16316
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 (公共文本)。

例子:

RandomStringGenerator randomStringGenerator =
        new RandomStringGenerator.Builder()
                .withinRange('0', 'z')
                .filteredBy(CharacterPredicates.LETTERS, CharacterPredicates.DIGITS)
                .build();
randomStringGenerator.generate(12); // toUpperCase() if you want

从 commons-lang 3.6 开始, RandomStringUtils 已弃用。

一行:

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

http://mynotes.wordpress.com/2009/07/23/java-generate-random-string/

您可以为此使用 Apache 库: 随机字符串实用程序

RandomStringUtils.randomAlphanumeric(20).toUpperCase();

无需任何外部库即可轻松实现这一点。

1.密码伪随机数据生成

首先您需要一个加密的 PRNG。Java有 SecureRandom 因为通常使用机器上最好的熵源(例如 /dev/random) . 在这里阅读更多内容。

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

笔记: SecureRandom 是 Java 中生成随机字节的最慢但最安全的方法。不过,我建议不要在这里考虑性能,因为它通常对您的应用程序没有真正的影响,除非您必须每秒生成数百万个令牌。

2.可能值所需的空间

接下来,您必须决定您的代币需要“多么独特”。考虑熵的全部也是唯一的一点是确保系统能够抵抗暴力攻击:可能值的空间必须如此之大,以至于任何攻击者只能在非荒唐的时间内尝试可忽略不计的部分值1. 。唯一标识符,例如随机 UUID 有 122 位熵(即2^122 = 5.3x10^36) - 碰撞的几率为“*(...) 为了有十亿分之一的重复几率,必须生成 103 万亿个版本 4 UUID2". 我们将选择 128 位,因为它恰好适合 16 字节 并被视为 高度充足 因为基本上每个(但最极端的)用例都是唯一的,并且您不必考虑重复。这是一个简单的熵比较表,包括对 生日问题.

comparison of token sizes

对于简单的要求,8 或 12 字节长度可能就足够了,但使用 16 字节就比较“安全”了。

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

3.二进制到文本编码

典型的编码包括:

  • Base64 每个字符编码 6 位,产生 33% 的开销。幸运的是,有标准实现 Java 8+安卓. 。对于较旧的 Java,您可以使用任何 许多第三方库. 。如果您希望您的令牌是 url 安全的,请使用 网址安全 RFC4648 的版本(通常大多数实现都支持)。带填充的 16 字节编码示例: XfJhfv3C0P6ag7y9VQxSbw==

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

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

附加编码如 Base85 和异国风情 Base122 存在更好/更差的空间效率。您可以创建自己的编码(基本上本线程中的大多数答案都是如此),但如果您没有非常具体的要求,我建议您不要这样做。看 维基百科文章中有更多编码方案。

4.总结和例子

  • 使用 SecureRandom
  • 至少使用 16 个字节 (2^128) 的可能值
  • 根据您的要求进行编码(通常 hex 或者 base32 如果您需要它是字母数字)

  • ...使用您的家庭酿造编码: 如果其他人看到您使用的标准编码而不是一次创建字符的怪异 for 循环,那么对其他人来说可以更好地维护和阅读。
  • ...使用UUID: 它不能保证随机性;你浪费了 6 位熵并且有冗长的字符串表示

例子:十六进制令牌生成器

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 安全)

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

使用 美元 应该很简单:

// "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));
    }
}

它输出类似的内容:

DKL1SBH9UJWC
JH7P0IT21EA5
5DTI72EO6SFU
HQUMJTEBNF7Y
1HCR6SKYWGT7

这是 Java 版本:

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();
  }
}

这是一个示例运行:

scala> RandomAlphaNum.gen(42)
res3: java.lang.String = uja6snx21bswf9t89s00bxssu8g6qlu16ffzqaxxoy

令人惊讶的是这里没有人建议,但是:

import java.util.UUID

UUID.randomUUID().toString();

简单的。

这样做的好处是 UUID 又好又长,并且保证几乎不可能发生冲突。

维基百科对此有很好的解释:

“……只有在接下来的 100 年内每秒生成 10 亿个 UUID 后,仅创建一个重复项的概率才会约为 50%。”

http://en.wikipedia.org/wiki/Universally_unique_identifier#Random_UUID_probability_of_duplicates

前 4 位是版本类型,后 2 位表示变体,因此您将获得 122 位随机数。所以如果你 您可以从末尾截断以减小 UUID 的大小。不建议这样做,但您仍然有大量的随机性,足以轻松处理 500k 条记录。

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

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

其大小约为 12 位以 36 为基数,因此无法进一步改进。当然,您可以附加多个实例。

Java 8 中的替代方案是:

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();
}
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 的过程非常简洁,但不会创建相同长度的字符串。以下代码片段应该足够了:

/*
 * 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=31 或者 2^6-1=63. 。如果我们选择 2^6 我们会得到很多“不必要的”/“更长的”数字。所以 2^5 是更好的选择,即使我们丢失 4 个字符 (w-z)。现在要生成一定长度的字符串,我们可以简单地使用 2^(length*numBits)-1 数字。最后一个问题,如果我们想要一个具有一定长度的字符串,随机可能会生成一个很小的数字,因此长度不满足,因此我们必须将字符串填充到所需的长度并在前面添加零。

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);
    }
}

所以它所做的只是将密码添加到字符串中然后......是的,效果很好,检查一下...很简单。我写的

我发现这个解决方案可以生成随机的十六进制编码字符串。提供的单元测试似乎符合我的主要用例。尽管如此,它比提供的其他一些答案稍微复杂一些。

/**
 * 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);
        }
    }
}
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;
    }
}
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("\n\t Unique codes are \n\n");
        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);
        }
    }
}
  1. 根据您的要求更改字符串字符。

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


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();
    }

不太喜欢任何有关“简单”解决方案的答案:S

我会选择一个简单的;),纯java,一个衬垫(熵基于随机字符串长度和给定的字符集):

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
    }
}

或者(更易读的旧方式)

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):

UUID.randomUUID().toString().replace("-", "")

希望有帮助。

您提到“简单”,但以防万一其他人正在寻找满足更严格安全要求的东西,您可能想看看 杰普沃根. 。jpwgen 是仿照 普世根 在 Unix 中,并且是非常可配置的。

这是一个 Scala 解决方案:

(for (i <- 0 until rnd.nextInt(64)) yield { 
  ('0' + rnd.nextInt(64)).asInstanceOf[Char] 
}) mkString("")

您可以使用 UUID 类及其 getLeastSignificantBits() 消息来获取 64 位随机数据​​,然后将其转换为基数 36 数字(即由 0-9,A-Z 组成的字符串):

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

这会产生一个最多 13 个字符长的字符串。我们使用 Math.abs() 来确保没有负号潜入。

如果您的密码强制包含数字字母特殊字符,您可以使用以下代码:

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();

}

这是一行代码 算盘工具

String.valueOf(CharStream.random('0', 'z').filter(c -> N.isLetterOrDigit(c)).limit(12).toArray())

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

N.uuid() // e.g.: "e812e749-cf4c-4959-8ee1-57829a69a80f". length is 36.
N.guid() // e.g.: "0678ce04e18945559ba82ddeccaabfcd". length is 32 without '-'

使用 apache 库,一行即可完成

import org.apache.commons.lang.RandomStringUtils;
RandomStringUtils.randomAlphanumeric(64);

这是文档 http://commons.apache.org/lang/api-2.3/org/apache/commons/lang/RandomStringUtils.html

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;
}

我认为这是这里最小的解决方案,或者几乎是最小的解决方案之一:

 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 秒。

public static String getRandomString(int length) 
{
   String randomStr = UUID.randomUUID().toString();
   while(randomStr.length() < length) {
       randomStr += UUID.randomUUID().toString();
   }
   return randomStr.substring(0, length);
}

也许这有帮助

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;

    }
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top