如何生成一个随机的字母数字字符串?

问题:

我一直在寻找simple Java算法来生成伪随机字母数字字符串。在我的情况下,它将被用作一个独特的会话/密钥标识符,“500k +”代可能是“可能”的唯一性(我的需求并不需要更多的复杂性)。理想情况下,我可以根据我的唯一性需要指定长度。例如,生成的长度为12的字符串可能看起来像"AEYGF7K0DM1X"

回答:

算法

要产生一个随机字符串,连接从可接受的符号集中随机绘制的字符,直到字符串达到所需的长度。

履行

这里有一些非常简单和非常灵活的代码来生成随机标识符。 Read the information that follows重要的应用笔记。

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&#91;idx&#93; = symbols&#91;random.nextInt(symbols.length)&#93;;
        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&#91;&#93; symbols;

    private final char&#91;&#93; 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&#91;length&#93;;
    }

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

}
&#91;/code&#93;
<h2>用法示例</h2>
为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应用程序中所发生的那样。应该有一个单独的授权系统来保护攻击者无法访问其标识符的对象。
还必须注意使用足够长的标识符,以使预期的标识符总数不会发生碰撞。这被称为“生日悖论”。 The probability of a collision, p大约是n 2 /(2q x),其中n是实际生成的标识符的数量,q是字母表中不同符号的数量,x是标识符的长度。这应该是一个非常小的数字,如2 ‑50或更少。
这样做表明,在500k 15个字符的标识符之间碰撞的机会约为2 ‑52,这可能不如宇宙射线等未检测到的错误。

与UUID的比较

根据它们的规范,UUID不被设计为不可预测的,并且should not被用作会话标识符。
标准格式的UUID占用大量空间:只有122位熵的36个字符。 (不是随机选择“随机”UUID的所有位)。随机选择的字母数字字符串将仅包含21个字符的更多熵。
UUID不灵活;它们具有标准化的结构和布局。这是他们的主要美德,也是他们的主要弱点。当与外界进行合作时,UUID提供的标准化可能会有所帮助。对于纯内部使用,它们效率低下。

 
 
Code问答: http://codewenda.com/topics/python/
Stackoverflow: How to generate a random alpha-numeric string?

*转载请注明本文链接以及stackoverflow的英文链接

发表评论

电子邮件地址不会被公开。 必填项已用*标注

47 − 46 =