Câu hỏi Làm thế nào để tạo ra một chuỗi alpha-số ngẫu nhiên?


Tôi đã tìm kiếm một đơn giản Thuật toán Java để tạo ra một chuỗi alpha-số giả ngẫu nhiên. Trong tình huống của tôi, nó sẽ được sử dụng như một phiên định danh / khóa duy nhất có khả năng là duy nhất trên thế hệ 500K + (nhu cầu của tôi không thực sự đòi hỏi bất kỳ thứ gì phức tạp hơn). Lý tưởng nhất, tôi sẽ có thể chỉ định một chiều dài tùy thuộc vào nhu cầu duy nhất của tôi. Ví dụ: một chuỗi có chiều dài 12 có thể trông giống như "AEYGF7K0DM1X".


1460


gốc


Cẩn thận nghịch lý sinh nhật. - pablosaraiva
Ngay cả khi xem xét nghịch lý ngày sinh, nếu bạn sử dụng 12 ký tự chữ và số (tổng cộng 62), bạn vẫn cần hơn 34 tỷ chuỗi để đạt được nghịch lý. Và nghịch lý sinh nhật không đảm bảo một vụ va chạm, nó chỉ nói rằng nó có hơn 50% cơ hội. - NullUserException
@NullUserException 50% cơ hội thành công (cho mỗi lần thử) là rất cao: ngay cả với 10 lần thử, tỷ lệ thành công là 0.999. Với điều đó và thực tế là bạn có thể thử A LOT trong một khoảng thời gian 24 giờ trong tâm trí, bạn không cần 34 tỷ dây để được khá chắc chắn để đoán ít nhất một trong số họ. Đó là lý do tại sao một số mã phiên nên được thực sự, thực sự lâu dài. - Pijusn
3 mã dòng đơn này rất hữu ích mà tôi đoán .. Long.toHexString(Double.doubleToLongBits(Math.random()));  UUID.randomUUID().toString();  RandomStringUtils.randomAlphanumeric(12); - Manindar
@Pijusn Tôi biết điều này là cũ, nhưng ... "50% cơ hội" trong nghịch lý sinh nhật là KHÔNG PHẢI "mỗi lần thử", đó là "50% cơ hội, trong số (trong trường hợp này) là 34 tỷ chuỗi, tồn tại ít nhất một cặp trùng lặp". Bạn cần 1.6 septillion - 1.6e21 - các mục trong cơ sở dữ liệu của bạn để có 50% cơ hội cho mỗi lần thử. - Walt


Các câu trả lời:


Thuật toán

Để tạo một chuỗi ngẫu nhiên, ghép các ký tự được rút ngẫu nhiên từ tập hợp các ký hiệu được chấp nhận cho đến khi chuỗi đạt đến độ dài mong muốn.

Thực hiện

Dưới đây là một số mã khá đơn giản và rất linh hoạt để tạo các số nhận dạng ngẫu nhiên. Đọc thông tin sau cho các ghi chú ứng dụng quan trọng.

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

}

Ví dụ sử dụng

Tạo trình tạo không an toàn cho số nhận dạng 8 ký tự:

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

Tạo trình tạo an toàn cho số nhận dạng phiên:

RandomString session = new RandomString();

Tạo máy phát có mã dễ đọc để in. Các chuỗi dài hơn chuỗi chữ số đầy đủ để bù cho việc sử dụng ít ký hiệu hơn:

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

Sử dụng làm số nhận dạng phiên

Việc tạo các số nhận dạng phiên có thể là duy nhất không đủ tốt hoặc bạn chỉ có thể sử dụng bộ đếm đơn giản. Tấn công các phiên tấn công khi các số nhận dạng dự đoán được sử dụng.

Có sự căng thẳng giữa chiều dài và an ninh. Số nhận dạng ngắn hơn dễ đoán hơn vì có ít khả năng hơn. Nhưng số nhận dạng dài hơn tiêu thụ nhiều dung lượng và băng thông hơn. Một bộ ký hiệu lớn hơn sẽ giúp, nhưng có thể gây ra sự cố mã hóa nếu số nhận dạng được bao gồm trong URL hoặc được nhập lại bằng tay.

Nguồn gốc ngẫu nhiên, hoặc entropy, đối với các định danh phiên phải đến từ một trình tạo số ngẫu nhiên được thiết kế cho mật mã. Tuy nhiên, việc khởi tạo các máy phát điện này đôi khi có thể tốn kém về mặt tính toán hoặc chậm, do đó cần phải nỗ lực để tái sử dụng chúng khi có thể.

Sử dụng làm số nhận dạng đối tượng

Không phải mọi ứng dụng đều yêu cầu bảo mật. Phân công ngẫu nhiên có thể là một cách hiệu quả cho nhiều thực thể để tạo các số nhận dạng trong một không gian được chia sẻ mà không cần bất kỳ sự phối hợp hoặc phân vùng nào. Sự phối hợp có thể chậm, đặc biệt là trong một môi trường phân cụm hoặc phân tán, và chia tách một không gian gây ra vấn đề khi các thực thể kết thúc với các cổ phiếu quá nhỏ hoặc quá lớn.

Các định danh được tạo ra mà không thực hiện các biện pháp để làm cho chúng không thể đoán trước nên được bảo vệ bằng các phương tiện khác nếu kẻ tấn công có thể xem và thao tác chúng, như xảy ra trong hầu hết các ứng dụng web. Nên có một hệ thống ủy quyền riêng biệt để bảo vệ các đối tượng mà kẻ tấn công có thể đoán được số nhận dạng mà không có quyền truy cập.

Việc chăm sóc cũng phải được thực hiện để sử dụng các số nhận dạng đủ dài để làm cho các va chạm không thể đưa ra tổng số số nhận dạng dự đoán. Điều này được gọi là "nghịch lý sinh nhật". Xác suất va chạm,  p, xấp xỉ n2/ (2qx), Ở đâu n là số lượng số nhận dạng thực sự được tạo, q là số biểu tượng riêng biệt trong bảng chữ cái và x là độ dài của số nhận dạng. Đây phải là một số rất nhỏ, như 2‑50 hoặc ít hơn.

Làm việc này cho thấy rằng cơ hội va chạm trong số nhận dạng 15 ký tự 15k là khoảng 2‑52, có lẽ ít có khả năng hơn các lỗi không bị phát hiện từ tia vũ trụ, v.v.

So sánh với UUID

Theo đặc điểm kỹ thuật của họ, UUID không được thiết kế để không thể đoán trước, và không nên được sử dụng làm số nhận dạng phiên.

UUID ở định dạng chuẩn của chúng chiếm rất nhiều không gian: 36 ký tự cho chỉ 122 bit entropy. (Không phải tất cả các bit của một UUID "ngẫu nhiên" được chọn ngẫu nhiên.) Một chuỗi ký tự chữ và số được chọn ngẫu nhiên gói entropy nhiều hơn chỉ trong 21 ký tự.

UUID không linh hoạt; chúng có cấu trúc và bố cục chuẩn hóa. Đây là đức hạnh của họ cũng như điểm yếu chính của họ. Khi cộng tác với bên ngoài, tiêu chuẩn hóa được cung cấp bởi UUID có thể hữu ích. Để sử dụng hoàn toàn nội bộ, chúng có thể không hiệu quả.


1398



Nếu bạn cần không gian trong của bạn, bạn có thể tack on .replaceAll("\\d", " "); vào cuối của return new BigInteger(130, random).toString(32); để thực hiện trao đổi regex. Nó thay thế tất cả các chữ số bằng dấu cách. Công trình tuyệt vời cho tôi: Tôi đang sử dụng nó như là một thay thế cho một Lorem Ipsum front-end - weisjohn
@ weisjohn Đó là một ý tưởng hay. Bạn có thể làm điều gì đó tương tự với phương pháp thứ hai, bằng cách xóa các chữ số khỏi symbols và sử dụng một không gian thay thế; bạn có thể kiểm soát độ dài "từ" trung bình bằng cách thay đổi số không gian trong các ký hiệu (nhiều lần xuất hiện cho các từ ngắn hơn). Đối với một giải pháp văn bản giả thực sự vượt trội, bạn có thể sử dụng một chuỗi Markov! - erickson
Tôi đã thử điều đó nhưng đôi khi nó chỉ dài 31. - Daniel Szalay
Tại sao .toString (32) thay vì .toString (36)? - ejain
@ejain vì 32 = 2 ^ 5; mỗi ký tự sẽ đại diện chính xác 5 bit và 130 bit có thể được chia đều thành các ký tự. - erickson


Java cung cấp một cách để làm điều này trực tiếp. Nếu bạn không muốn các dấu gạch ngang, chúng rất dễ tháo ra. Chỉ dùng 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;
    }
}

Đầu ra:

uuid = 2d7428a6-b58c-4008-8575-f05549f16316

733



Hãy coi chừng rằng giải pháp này chỉ tạo ra một chuỗi ngẫu nhiên với các ký tự thập lục phân. Điều này có thể tốt trong một số trường hợp. - Dave
Lớp UUID rất hữu ích. Tuy nhiên, chúng không nhỏ gọn như các định danh được tạo ra bởi các câu trả lời của tôi. Đây có thể là một vấn đề, ví dụ: trong URL. Phụ thuộc vào nhu cầu của bạn. - erickson
@Ruggs - Mục tiêu là chuỗi alpha-số. Làm thế nào để mở rộng đầu ra cho bất kỳ byte nào có thể phù hợp với điều đó? - erickson
Theo RFC4122 sử dụng UUID làm thẻ là một ý tưởng tồi: Đừng cho rằng UUID khó đoán; chúng không nên được sử dụng như các khả năng bảo mật (ví dụ như các định danh có quyền truy cập tài sản). Một nguồn số ngẫu nhiên có thể dự đoán sẽ làm trầm trọng thêm tình hình. ietf.org/rfc/rfc4122.txt - Somatik
UUID.randomUUID().toString().replaceAll("-", ""); làm cho chuỗi alpha-số, theo yêu cầu. - Numid


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

469



1, giải pháp đơn giản nhất ở đây để tạo chuỗi ngẫu nhiên chiều dài quy định (ngoài việc sử dụng RandomStringUtils từ Commons Lang). - Jonik
Cân nhắc sử dụng SecureRandom thay cho Random lớp học. Nếu mật khẩu được tạo trên một máy chủ, nó có thể dễ bị tấn công theo thời gian. - foens
Tôi cũng sẽ thêm chữ thường: AB = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; và một số ký tự được phép khác. - ACV
Tại sao không đặt static Random rnd = new Random(); bên trong phương pháp? - Micro
@ MicroR Có lý do chính đáng để tạo Random đối tượng trong mỗi lời gọi phương thức? Tôi không nghĩ vậy. - Cassio Mazzochi Molin


Nếu bạn vui khi sử dụng các lớp Apache, bạn có thể sử dụng org.apache.commons.text.RandomStringGenerator (commons-text).

Thí dụ:

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

Từ commons-lang 3.6, RandomStringUtils không được chấp nhận.


453



Vừa xem qua lớp đã đề cập của Apache Commons Lang 3.3.1 thư viện - và nó chỉ sử dụng java.util.Random để cung cấp các chuỗi ngẫu nhiên, vì vậy nó đang sản xuất chuỗi không an toàn. - Yura
Đảm bảo bạn sử dụng SecureRandom khi sử dụng RandomStringUtils: public static java.lang.String random(int count, int start, int end, boolean letters, boolean numbers, @Nullable char[] chars, java.util.Random random) - Ruslans Uralovs


Trong một dòng:

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

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


90



Nhưng chỉ có 6 chữ cái :( - Moshe Revah
Nó đã giúp tôi quá nhưng chỉ có chữ số thập lục phân: ( - noquery
@ Zippoxer, bạn có thể concat nhiều lần =) - daniel.bavrin
Ví dụ của OP cho thấy chuỗi sau đây là một ví dụ AEYGF7K0DM1X không phải hệ thập lục phân. Nó khiến tôi lo lắng về tần suất mọi người nhầm lẫn chữ và số với hệ thập lục phân. Chúng không giống nhau. - hfontanez
Điều này ít ngẫu nhiên hơn so với độ dài chuỗi như Math.random() tạo ra một double giữa 0 và 1, vì vậy phần số mũ hầu như không được sử dụng. Sử dụng random.nextLong cho một ngẫu nhiên long thay vì hack xấu xí này. - maaartinus


Bạn có thể sử dụng thư viện Apache cho việc này: RandomStringUtils

RandomStringUtils.randomAlphanumeric(20).toUpperCase();

87



@ kamil, tôi đã xem mã nguồn cho RandomStringUtils và nó sử dụng một thể hiện của java.util.Random được tạo ra mà không có đối số. Tài liệu cho java.util.Random nói rằng nó sử dụng thời gian hệ thống hiện tại nếu không có hạt giống nào được cung cấp. Điều này có nghĩa là nó không thể được sử dụng cho các mã định danh / khóa phiên vì kẻ tấn công có thể dễ dàng dự đoán được số nhận dạng phiên được tạo ra tại bất kỳ thời điểm nào. - Inshallah
@Inshallah: Bạn đang (không cần thiết) overengineering hệ thống. Trong khi tôi đồng ý rằng nó sử dụng thời gian như hạt giống, kẻ tấn công phải có quyền truy cập vào dữ liệu sau để thực sự có được những gì anh ta muốn 1. Thời gian đến mili giây chính xác, khi mã được hạt giống 2. Số lượng cuộc gọi đã xảy ra cho đến nay 3. Atomicity cho các cuộc gọi của riêng mình (để số lượng các cuộc gọi-cho đến nay ramains cùng) Nếu kẻ tấn công của bạn có tất cả ba trong số những điều này, sau đó bạn có vấn đề lớn hơn nhiều trong tầm tay ... - Ajeet Ganga
phụ thuộc gradle: compile 'commons-lang:commons-lang:2.6' - younes0
@ Ajeet điều này không đúng. Bạn có thể lấy được trạng thái của trình tạo số ngẫu nhiên từ đầu ra của nó. Nếu kẻ tấn công có thể tạo ra vài nghìn cuộc gọi để tạo mã thông báo API ngẫu nhiên, kẻ tấn công sẽ có thể dự đoán tất cả mã thông báo API trong tương lai. - Thomas Grainger
@AjeetGanga Không có gì để làm với hơn kỹ thuật. Nếu bạn muốn tạo id phiên, bạn cần một trình tạo giả ngẫu nhiên mã hóa. Mỗi prng sử dụng thời gian làm hạt giống có thể dự đoán được và rất không an toàn cho dữ liệu không thể đoán trước được. Chỉ dùng SecureRandomvà bạn tốt. - for3st


sử dụng Đô la nên đơn giản như:

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

nó xuất ra một cái gì đó như thế:

DKL1SBH9UJWC
JH7P0IT21EA5
5DTI72EO6SFU
HQUMJTEBNF7Y
1HCR6SKYWGT7

36



sao có thể sử dụng SecureRandom với shuffle? - iwein


Điều này có thể dễ dàng đạt được mà không cần bất kỳ thư viện bên ngoài nào.

1. Tạo mã dữ liệu ngẫu nhiên giả mã hóa

Trước tiên, bạn cần một PRNG mã hóa. Java có SecureRandom cho điều đó thường sử dụng nguồn entropy tốt nhất trên máy (ví dụ: /dev/random). Đọc thêm tại đây.

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

Chú thích:  SecureRandom là cách chậm nhất, nhưng an toàn nhất trong Java khi tạo các byte ngẫu nhiên. Tuy nhiên, tôi khuyên bạn KHÔNG nên xem xét hiệu suất ở đây vì nó thường không có tác động thực sự đến ứng dụng của bạn trừ khi bạn phải tạo ra hàng triệu mã thông báo mỗi giây.

2. Yêu cầu không gian của các giá trị có thể

Tiếp theo, bạn phải quyết định mã thông báo "độc đáo" như thế nào. Toàn bộ và điểm duy nhất để xem xét entropy là đảm bảo rằng hệ thống có thể chống lại các cuộc tấn công bạo lực: không gian của các giá trị có thể phải lớn đến nỗi bất kỳ kẻ tấn công nào cũng chỉ có thể thử một tỷ lệ không đáng kể các giá trị trong thời gian không lố bịch1. Số nhận dạng duy nhất như ngẫu nhiên UUID có 122bit entropy (tức là 2 ^ 122 = 5.3x10 ^ 36) - cơ hội va chạm là "* (...) để có cơ hội nhân bản một tỷ, 103 nghìn tỷ phiên bản 4 UUID phải được tạo ra2". Chúng tôi sẽ chọn 128 bit vì nó phù hợp chính xác thành 16 byte và được xem như đủ cao để trở thành duy nhất cho mọi trường hợp, nhưng các trường hợp sử dụng khắc nghiệt nhất và bạn không phải suy nghĩ về các bản sao. Đây là một bảng so sánh đơn giản của entropy bao gồm phân tích đơn giản của sinh nhật vấn đề.

comparison of token sizes

Đối với yêu cầu đơn giản 8 hoặc 12 byte chiều dài có thể đủ, nhưng với 16 byte bạn đang ở bên "an toàn".

Và đó là cơ bản. Điều cuối cùng là suy nghĩ về mã hóa để nó có thể được biểu diễn dưới dạng văn bản có thể in được (đọc, một String).

3. Mã hóa nhị phân thành văn bản

Mã hóa điển hình bao gồm:

  • Base64 mỗi ký tự mã hóa 6 bit tạo ra một chi phí trên 33%. Đáng tiếc là không có thực hiện tiêu chuẩn trong JDK (7 trở xuống - Có trong Android và Java 8+). Nhưng nhiều thư viện tồn tại thêm cái này. Nhược điểm là, tiêu chuẩn đó Base64 không an toàn cho ví dụ. url và dưới dạng tên tệp trong hầu hết các hệ thống tệp yêu cầu mã hóa bổ sung (ví dụ: mã hóa url) hoặc là Phiên bản an toàn URL của Base64 được sử dụng. Ví dụ mã hóa 16 byte với đệm: XfJhfv3C0P6ag7y9VQxSbw==

  • Base32 mỗi ký tự mã hóa 5 bit tạo ra một chi phí 40%. Điều này sẽ sử dụng A-Z và 2-7 làm cho nó hợp lý không gian hiệu quả trong khi không phân biệt chữ hoa chữ thường. Không có thực hiện tiêu chuẩn trong JDK. Ví dụ mã hóa 16 byte không có đệm: WUPIL5DQTZGMF4D3NX5L7LNFOY

  • Base16 (hex) mỗi ký tự mã hóa 4 bit yêu cầu 2 ký tự trên mỗi byte (ví dụ: 16 byte tạo một chuỗi có độ dài 32). Do đó hex ít hiệu quả hơn Base32 nhưng an toàn để sử dụng trong hầu hết các trường hợp (url) vì nó chỉ sử dụng 0-9 và A đến F. Ví dụ mã hóa 16 byte: 4fa3dd0f57cb3bf331441ed285b27735. Xem một cuộc thảo luận SO về chuyển đổi sang hex ở đây.

Mã hóa bổ sung như Base85 và kỳ lạ Base122 tồn tại với hiệu quả không gian tốt hơn / tồi tệ hơn. Bạn có thể tạo mã hóa của riêng bạn (về cơ bản hầu hết các câu trả lời trong chuỗi này đều làm) nhưng tôi khuyên bạn nên chống lại nó, nếu bạn không có các yêu cầu rất cụ thể. Xem nhiều lược đồ mã hóa hơn trong bài viết trên Wikipedia.

4. Tóm tắt và ví dụ

  • Sử dụng SecureRandom
  • Sử dụng ít nhất 16 byte (2 ^ 128) giá trị có thể
  • Mã hóa theo yêu cầu của bạn (thường là hex hoặc là base32 nếu bạn cần nó là alpha-số)

Đừng

  • ... sử dụng mã hóa brew tại nhà của bạn: tốt hơn có thể duy trì và có thể đọc được đối với những người khác nếu họ thấy mã hóa chuẩn nào bạn sử dụng thay vì kỳ quặc cho các vòng lặp tạo ký tự tại một thời điểm.
  • ... sử dụng UUID: bạn đang lãng phí 6 bits entropy và có biểu diễn chuỗi chi tiết

Ví dụ: Trình tạo mã thông báo Hex

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

Ví dụ: Công cụ

Nếu bạn muốn một công cụ cli sẵn sàng sử dụng, bạn có thể sử dụng xúc xắc: https://github.com/patrickfav/dice


32



Câu trả lời này hoàn thành và hoạt động mà không cần thêm bất kỳ sự phụ thuộc nào. Nếu bạn muốn tránh các dấu hiệu có thể bị trừ trong đầu ra, bạn có thể ngăn tiêu cực BigIntegers sử dụng tham số hàm tạo: BigInteger(1, token) thay vì BigInteger(token). - francoisr
Tanks @francoisr cho gợi ý, tôi đã chỉnh sửa ví dụ về mã - for3st


Đáng ngạc nhiên là không ai ở đây đã gợi ý nhưng:

import java.util.UUID

UUID.randomUUID().toString();

Dễ dàng.

Lợi ích của điều này là UUID là tốt đẹp và lâu dài và đảm bảo được gần như không thể va chạm.

Wikipedia có một lời giải thích tốt về nó:

"... chỉ sau khi tạo ra 1 tỷ UUID mỗi giây trong 100 năm tới, xác suất tạo ra chỉ một bản sao sẽ là khoảng 50%."

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

4 bit đầu tiên là loại phiên bản và 2 cho biến thể để bạn nhận được 122 bit ngẫu nhiên. Vì vậy, nếu bạn muốn để bạn có thể cắt ngắn từ đầu để giảm kích thước của UUID. Nó không được đề nghị nhưng bạn vẫn có tải ngẫu nhiên, đủ cho 500k hồ sơ của bạn dễ dàng.


29



Có người đã đề xuất nó, khoảng một năm trước bạn. - erickson


Đây là trong 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();
  }
}

Đây là một mẫu chạy:

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

28



Điều này sẽ sản xuất chuỗi không an toàn tức là các chuỗi có thể dễ dàng đoán được. - Yura
và leftPad ???? - lahbib
Tất cả thế hệ int ngẫu nhiên đôi bị nhiễm khuẩn này bị phá vỡ bởi thiết kế, chậm và không đọc được. Sử dụng Random#nextInt hoặc là nextLong. Chuyển sang SecureRandom Nếu cần thiết. - maaartinus