如何生成随机字母数字字符串

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

理想情况下,我将能够根据我的个性要求指定尺寸。 例如,生成的长度为 12 的字符串可能类似于 "AEYGF7K0DM1X"

1905
2022-06-07 15:16:05
资源 分享
答案: 5

如果您非常乐意使用 Apache 类,您可以使用 org.apache.commons.text.RandomStringGenerator (Apache Commons 文本)。

例子:

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

Apache Commons 朗 3.6 开始,不推荐使用 RandomStringUtils

503
2022-06-08 01:54:18
资源

我发现这个选项可以创建一个随机的十六进制字符串。 提供的设备检查似乎经得起我的主要用例。 虽然,它比给出的其他各种响应稍微复杂一些。

/**
 * 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);
        }
    }
}
9
2022-06-07 17:11:45
资源

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
888
2022-06-07 17:11:40
资源

这是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
43
2022-06-07 15:52:57
资源

算法

要生成随机字符串,请连接从一组可接受的图标中随机抽取的字符,直到字符串达到所需大小。

执行

这是一些用于生成随机标识符的相对基本且真正适用的代码。 阅读符合的信息重要的应用笔记。

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 , 在 n 附近 2 / (2q X ), 在哪里 n 是实际上创建的各种标识符, q 是字母表中独特符号的数量,并且 X 是标识符的长度。 这必须是一个非常小的数字,比如 2 50 或更少。

运行这个程序,500k 15 中的意外机会 - 个性标识符约为 2 52 ,这可能比来自行星射线等的未被注意到的错误要小得多。

与 UUID 对比

根据他们的规范,UUID 并非设计为不可预见的,以及一定不用作会话标识符。

基本格式的 UUID 占用大量空间:36 个字符仅用于 122 个小字符退化。 (并非“随机”UUID 的所有位都是任意选择的。)任意选择的字母数字字符串仅在 21 个字符中加载更多下降。

UUID 不适应; 他们有一个标准化的框架和布局。 这是他们的主要优点,除了他们的主要弱点。 当与外部方合作时,UUID 提供的标准化可能很有价值。 对于完全内部使用,它们可能无效。

1627
2022-06-07 15:46:19
资源