Trình tạo chuỗi ngẫu nhiên PHP


814

Tôi đang cố gắng tạo một chuỗi ngẫu nhiên trong PHP và tôi hoàn toàn không nhận được kết quả nào với điều này:

<?php
    function RandomString()
    {
        $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
        $randstring = '';
        for ($i = 0; $i < 10; $i++) {
            $randstring = $characters[rand(0, strlen($characters))];
        }
        return $randstring;
    }

    RandomString();
    echo $randstring;

Tôi đang làm gì sai?


241
Giải pháp một dòng của tôi để tạo chuỗi ngắn là chất nền (md5 (rand ()), 0, 7); chúc may mắn ...
tasmaniski

5
@tasmaniski .. Giải pháp của bạn là ổn .. Nhưng nó ít ngẫu nhiên hơn! Trong ví dụ của bạn, số chuỗi ngẫu nhiên có thể được tạo bị giới hạn bởi kích thước của số nguyên. (2 ^ 32) ở mức tối đa .. Trong trường hợp giải pháp khác, bạn có thể tạo (62 ^ 8) .. Trong trường hợp, tôi muốn các chuỗi lớn hơn, thì số chuỗi khác biệt vẫn ở mức tối đa 2 ^ 32, nhưng trong giải pháp khác nó tăng lên (62 ^ n) ..
Manu

9
Bạn đã quên thêm từng ký tự được tạo mới vào chuỗi. Bạn chỉ cần ghi đè lên như nó là. Phải là $ rand chuỗi. = $ Ký tự ..
Spock

3
@CaptainLightning Bạn có thể vui lòng trao đổi câu trả lời được chấp nhận cho một trong những câu trả lời an toàn hơn không? :)
Scott Arciszewski 8/12/2015

2
strlen($characters)=> strlen($characters) - 1- độ dài chuỗi bắt đầu bằng 1
Zippp

Câu trả lời:


1393

Để trả lời câu hỏi này cụ thể, hai vấn đề:

  1. $randstring không nằm trong phạm vi khi bạn lặp lại nó.
  2. Các nhân vật không được nối với nhau trong vòng lặp.

Đây là một đoạn mã với các sửa chữa:

function generateRandomString($length = 10) {
    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $charactersLength = strlen($characters);
    $randomString = '';
    for ($i = 0; $i < $length; $i++) {
        $randomString .= $characters[rand(0, $charactersLength - 1)];
    }
    return $randomString;
}

Xuất chuỗi ngẫu nhiên với cuộc gọi dưới đây:

// Echo the random string.
// Optionally, you can give it a desired string length.
echo generateRandomString();

Xin lưu ý rằng điều này tạo ra chuỗi ngẫu nhiên dự đoán. Nếu bạn muốn tạo mã thông báo an toàn, hãy xem câu trả lời này .


34
@FranciscoPresencia, tốt hơn là "lãng phí" một biến phụ khi gọi một phương thức trong điều kiện so sánh của một vòng lặp.
Rico Sonntag

200
Tất cả những công việc đó, tại sao không chỉ là một cái gì đó như thế substr(str_shuffle(MD5(microtime())), 0, 10);nào?
SpYk3HH

4
Cảm ơn mã, nhưng xin vui lòng đổi rand()thành mt_rand(). Tôi đã sử dụng phương pháp của bạn và trải qua một tấn va chạm với tên.
Nate

5
@FranciscoPresencia bạn có biết điều đó kém hiệu quả đến mức nào không? Bạn đang kiểm tra độ dài của chuỗi hai lần mỗi lần lặp! Các strlen bên trong vòng lặp nên được lưu trữ trong một biến trước khi vào vòng lặp.
nhà phát triển xe máy

4
Đây không phải là một giải pháp tốt. Các chuỗi này tạo ra sẽ được dự đoán. :(
Scott Arciszewski

370

Lưu ý: str_shuffle()sử dụng nội bộ rand(), không phù hợp cho mục đích mã hóa (ví dụ: tạo mật khẩu ngẫu nhiên). Bạn muốn một trình tạo số ngẫu nhiên an toàn thay thế. Nó cũng không cho phép các nhân vật lặp lại.

Một cách nữa.

CẬP NHẬT (bây giờ điều này tạo ra bất kỳ độ dài của chuỗi):

function generateRandomString($length = 10) {
    return substr(str_shuffle(str_repeat($x='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', ceil($length/strlen($x)) )),1,$length);
}

echo  generateRandomString();  // OR: generateRandomString(24)

Đó là nó. :)


64
+1 cho câu trả lời ngắn nhất :). Nhưng không phải là câu trả lời tốt nhất cho mọi trường hợp sử dụng. Mã này sẽ xuất ra các chuỗi trong đó mỗi ký tự sẽ không xuất hiện nhiều hơn một lần (do đó làm cho nó yếu hơn đối với các cuộc tấn công vũ phu) và sẽ không xuất ra bất cứ thứ gì dài hơn 62 ký tự.
David

17
Đừng làm điều này, nó cực kỳ yếu. Bạn càng tạo chuỗi ngẫu nhiên càng lâu thì nó càng yếu.
Abhi Beckert

23
Có thể yếu, nhưng nó nhanh chóng và dễ dàng. Tùy thuộc vào trường hợp sử dụng, điều này tốt - tôi đã sử dụng nó vì tôi không cần bảo mật hoặc sức mạnh; chỉ là một shuffle lửa nhanh. Tôi đang viết một bài kiểm tra đơn vị, và điều này mang lại cho tôi một đầu vào ngẫu nhiên phù hợp để kiểm tra.
SDC

23
@FranciscoPresencia lý do nó không an toàn là vì nó không bao giờ sử dụng cùng một ký tự hai lần. Điều đó làm cho nó một trình tạo mật khẩu khủng khiếp . Xin mọi người ngừng bỏ phiếu này, nó hoàn toàn không an toàn không bao giờ được sử dụng. Khi mật khẩu dài hơn, số lượng ký tự bạn phải kiểm tra trong một lực lượng vũ phu sẽ ngắn hơn vì bạn không bận tâm kiểm tra bất kỳ ký tự nào được sử dụng trước đó.
Abhi Beckert

8
@FranciscoPresencia: Tôi ủng hộ ý kiến ​​của bạn về việc tránh sử dụng điều này cho mật khẩu ngẫu nhiên. Tuy nhiên, tôi không đồng ý rằng câu trả lời này không nên là một. Tôi có tùy chọn này cộng với một vì đây là một giải pháp một dòng hiệu quả để tạo các chuỗi ngẫu nhiên (chủ đề ban đầu của câu hỏi này).
bwright

331

Có rất nhiều câu trả lời cho câu hỏi này, nhưng không ai trong số họ sử dụng Trình tạo số giả ngẫu nhiên an toàn bằng mật mã (CSPRNG).

Câu trả lời đơn giản, an toàn và chính xác là sử dụng RandomLib và không phát minh lại bánh xe.

Đối với những người khăng khăng phát minh ra giải pháp của riêng bạn, PHP 7.0.0 sẽ cung cấp random_int()cho mục đích này; nếu bạn vẫn còn trên PHP 5.x, chúng tôi đã viết một polyfill PHP 5random_int() để bạn có thể sử dụng API mới ngay cả trước khi bạn nâng cấp lên PHP 7.

Tạo an toàn các số nguyên ngẫu nhiên trong PHP không phải là một nhiệm vụ tầm thường. Bạn phải luôn luôn kiểm tra với các chuyên gia mật mã StackExchange thường trú trước khi bạn triển khai một thuật toán tự trồng trong sản xuất.

Với một trình tạo số nguyên an toàn tại chỗ, việc tạo một chuỗi ngẫu nhiên với CSPRNG là một cuộc dạo chơi trong công viên.

Tạo một chuỗi ngẫu nhiên, an toàn

/**
 * Generate a random string, using a cryptographically secure 
 * pseudorandom number generator (random_int)
 *
 * This function uses type hints now (PHP 7+ only), but it was originally
 * written for PHP 5 as well.
 * 
 * For PHP 7, random_int is a PHP core function
 * For PHP 5.x, depends on https://github.com/paragonie/random_compat
 * 
 * @param int $length      How many characters do we want?
 * @param string $keyspace A string of all possible characters
 *                         to select from
 * @return string
 */
function random_str(
    int $length = 64,
    string $keyspace = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
): string {
    if ($length < 1) {
        throw new \RangeException("Length must be a positive integer");
    }
    $pieces = [];
    $max = mb_strlen($keyspace, '8bit') - 1;
    for ($i = 0; $i < $length; ++$i) {
        $pieces []= $keyspace[random_int(0, $max)];
    }
    return implode('', $pieces);
}

Cách sử dụng :

$a = random_str(32);
$b = random_str(8, 'abcdefghijklmnopqrstuvwxyz');
$c = random_str();

Bản trình diễn : https://3v4l.org/IMJGF (Bỏ qua các lỗi PHP 5; nó cần Random_compat)


3
Khi bắt đầu chức năng, hãy thêm $keyspace = str_shuffle($keyspace );bảo mật
Jevgenij Dmitrijev

13
Bạn có ý nghĩa gì bởi "để bảo mật hơn"? Chúng tôi đã sử dụng một trình tạo số ngẫu nhiên an toàn.
Scott Arciszewski

5
@JGEstiot Tạo chuỗi ngẫu nhiên an toàn đòi hỏi tính ngẫu nhiên an toàn về mặt mật mã. Ai đó đang tìm kiếm "cách tạo chuỗi ngẫu nhiên trong PHP" được phục vụ tốt hơn bởi một câu trả lời an toàn hơn là một câu trả lời không an toàn.
Scott Arciszewski

1
@ Scott Arciszewski Bạn không cần tạo các chuỗi ngẫu nhiên bằng mật mã mỗi khi bạn tạo các chuỗi ngẫu nhiên. Câu hỏi là về việc tạo các chuỗi ngẫu nhiên và điều này không liên quan gì đến bảo mật. Bạn đã giả định rằng chuỗi sẽ được sử dụng trong ngữ cảnh nhạy cảm bảo mật và bạn thêm một lớp phức tạp ngăn chặn cốt lõi của câu hỏi.
JG Estiot

45
Sử dụng random_int()thay vì rand()hoặc mt_rand()thêm không phức tạp cho nhà phát triển. Đồng thời, nó mang lại cho họ sự an toàn cao hơn. Những người đến với StackOverflow đang tìm kiếm giải pháp nhanh chóng có thể không biết liệu thứ mà họ đang xây dựng có cần được bảo mật hay không. Nếu chúng tôi cung cấp cho họ câu trả lời theo mặc định an toàn, họ sẽ tạo ra một Internet an toàn hơn ngay cả khi, từ quan điểm của họ, đó hoàn toàn là tình cờ. Tại sao bạn lại phản đối mục tiêu này là một bí ẩn đối với tôi.
Scott Arciszewski

156

Điều này tạo ra một chuỗi thập lục phân dài 20 ký tự:

$string = bin2hex(openssl_random_pseudo_bytes(10)); // 20 chars

Trong PHP 7 ( Random_bytes () ):

$string = base64_encode(random_bytes(10)); // ~14 characters, includes /=+
// or
$string = substr(str_replace(['+', '/', '='], '', base64_encode(random_bytes(32))), 0, 32); // 32 characters, without /=+
// or
$string = bin2hex(random_bytes(10)); // 20 characters, only 0-9a-f

Xin lưu ý rằng openssl_random_pseudo_bytes()đã không sử dụng thuật toán mã hóa mạnh cho đến khi php 5.6. Lỗi liên quan: bug.php.net/orms.php?id=70014
acidtv

Cũng lưu ý rằng chuỗi nhỏ nhất mà chuỗi này có thể tạo ra có độ dài 2. Nếu bạn truyền một độ dài byte từ 1 trở xuống, openssl_random_pseudo_bytes()bạn sẽ không nhận được gì. Ngoài ra, lưu ý rằng khi sử dụng bin2hex(openssl_random_pseudo_bytes($length / 2))vì bạn đang làm việc với các số nguyên, nó sẽ tự động loại bỏ modulo và sẽ sử dụng bội số thấp nhất tiếp theo của 2. Vì vậy, $length = 19sẽ tạo ra một chuỗi có độ dài 18.
Nathan F.

Đề xuất sử dụng nó làm nội dung tệp có thể được mở thông qua fgets($fp, 1024)và mọi trình chỉnh sửa tệp có vấn đề với các dòng rất dài: function string_rand($len, $split="\n") { return substr(chunk_split(bin2hex(openssl_random_pseudo_bytes(ceil($len / 2))), 1023, $split), 0, $len); }Đặt $splitthành nullnếu nó sẽ trả về một lớp lót. Bằng cách đó bạn có thể sử dụng nó cho cả hai trường hợp.
mgutt

Tôi thực sự thích giải pháp Random_bytes cho PHP 7, nhưng nếu bạn cần chuỗi là một số lượng ký tự nhất định thì cái gì đó sẽ hoạt động như thế này? $string = substr(base64_encode(random_bytes($size)), 0, $size);
Chương trình

Điều này là hoàn toàn không có nghi ngờ là giải pháp tốt nhất. Chiếm rất ít không gian và siêu dễ hiểu.
Matthew Campbell

92

@tasmaniski: câu trả lời của bạn đã làm việc cho tôi. Tôi đã có cùng một vấn đề, và tôi sẽ đề nghị nó cho những người đang tìm kiếm cùng một câu trả lời. Đây là từ @tasmaniski:

<?php 
    $random = substr(md5(mt_rand()), 0, 7);
    echo $random;
?>

Dưới đây là video youtube chỉ cho chúng tôi cách tạo số ngẫu nhiên


6
nếu chuỗi của bạn chỉ dựa trên một số nguyên ngẫu nhiên, tại sao không sử dụng số nguyên ngẫu nhiên? họ haystack không thể tiến sâu hơn bằng cách băm nó ... và bằng cách cắt băm của bạn thực sự phá hủy entropy nhỏ mà bạn phải bắt đầu.
Surrican

4
Hãy ghi nhớ md5sẽ dẫn đến giới hạn 30 ký tự và luôn luôn ký tự viết thường.
fyrye

3
Ngoài ra, rand () không nên được sử dụng cho mật mã. Nếu bạn đang tìm cách tạo ra một chuỗi âm thanh theo phương pháp áp lạnh, hãy sử dụng openssl_random_pseudo_bytes .
mattkgross

md5(rand())chỉ cung cấp 2 ^ 32 giá trị có thể. Điều này có nghĩa là sau trung bình, 2 ^ 16 chuỗi ngẫu nhiên bạn sẽ mong đợi một chuỗi lặp lại.
Scott Arciszewski

2
Chà..tôi sẽ cá là OP không nói về "chuỗi ngẫu nhiên an toàn". Giải pháp này nhỏ gọn, dễ dàng và dễ nhớ, cho các trường hợp sử dụng đúng . Và, nếu bạn cần quan tâm đến các va chạm có thể xảy ra, tại sao không thêm / nối thêm dấu thời gian vào chuỗi ngẫu nhiên? :)
Erenor Paz

46

Tùy thuộc vào ứng dụng của bạn (tôi muốn tạo mật khẩu), bạn có thể sử dụng

$string = base64_encode(openssl_random_pseudo_bytes(30));

Là cơ sở64, chúng có thể chứa =hoặc -cũng như các ký tự được yêu cầu. Bạn có thể tạo một chuỗi dài hơn, sau đó lọc và cắt nó để loại bỏ những chuỗi đó.

openssl_random_pseudo_bytesdường như là cách được đề xuất để tạo một số ngẫu nhiên thích hợp trong php. Tại sao randkhông sử dụng/dev/random .


2
rand không sử dụng / dev / urandom vì điều đó chỉ khả dụng trong các môi trường như posix và không khả dụng.
Macroman

3
@MacroMan Nhưng openssl_random_pseudo_bytes() là hàng xách tay.
Ja͢ck

Nếu bạn muốn loại bỏ các ký tự base64 bổ sung, hãy thử điều này: gist.github.com/zyphlar/7217f566fc83a9633959
willbradley

3
Điều này không sai, nhưng tôi khuyên bạn nên thận trọng trong cách bạn loại bỏ các ký tự không mong muốn. Xem yêu cầu kéo này trên Máy chủ OAuth2 của giải đấu PHP chẳng hạn.
Scott Arciszewski 6/07/2015

Đây là một trong những câu trả lời tốt nhất. Đáng tiếc là nó không có nhiều hỗ trợ hơn. Tôi sẽ khuyên bạn nên chỉnh sửa câu trả lời của bạn để xử lý tốt hơn các ký tự không mong muốn mặc dù.
jcuenod

28

Dưới đây là một lớp lót đơn giản tạo ra một chuỗi ngẫu nhiên thực sự mà không có bất kỳ vòng lặp cấp độ kịch bản hoặc sử dụng các thư viện OpenSSL.

echo substr(str_shuffle(str_repeat('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', mt_rand(1,10))), 1, 10);

Để phá vỡ nó để các tham số rõ ràng

// Character List to Pick from
$chrList = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';

// Minimum/Maximum times to repeat character List to seed from
$chrRepeatMin = 1; // Minimum times to repeat the seed string
$chrRepeatMax = 10; // Maximum times to repeat the seed string

// Length of Random String returned
$chrRandomLength = 10;

// The ONE LINE random command with the above variables.
echo substr(str_shuffle(str_repeat($chrList, mt_rand($chrRepeatMin,$chrRepeatMax))), 1, $chrRandomLength);

Phương pháp này hoạt động bằng cách lặp lại ngẫu nhiên danh sách ký tự, sau đó xáo trộn chuỗi kết hợp và trả về số lượng ký tự được chỉ định.

Bạn có thể chọn ngẫu nhiên thêm điều này, bằng cách ngẫu nhiên độ dài của chuỗi được trả về, thay thế $chrRandomLengthbằng mt_rand(8, 15)(đối với một chuỗi ngẫu nhiên từ 8 đến 15 ký tự).


Rất tiếc phải nói nhưng khi một ký tự được chọn, xác suất xuất hiện lại không cao như các ký tự khác vẫn còn trong nhóm. không có sự ngẫu nhiên thực sự ở đây ...
The Surrican

@TheSurrican - Bạn sẽ không chính xác trong tuyên bố đó. Tất cả các ký tự có xác suất bằng nhau khi sử dụng thuật toán này và do đó thực sự ngẫu nhiên. Điều này được đảm bảo bằng cách lặp lại chuỗi chrList $ chrRepeatMax và phép thuật thực sự xảy ra trong str_shuffle xác định tính ngẫu nhiên.
Kraang Prime

Tất cả các ký tự sẽ chỉ xuất hiện một lần và nó rất dễ bị đoán là
tàn bạo

@venimus Đó không chính xác. Chuỗi char được sao chép cho bao nhiêu ký tự bạn muốn (xem $chrRepeatMax$chrRepeatMin) - vì vậy, chuỗi 10 char, có thể (không thể, nhưng có thể), là "aaaaaaaaaa".
Kraang Prime

@SanuelJackson Xin lỗi tôi nhớ bình luận. Tôi đã đưa ra nhận xét về câu trả lời sai. Bạn đúng rồi! Tôi thực sự đã sử dụng "mánh khóe" của bạn, nhưng không sử dụng mt_rand, vì đó là IMHO vô dụng. Nó không thêm vào entropy. Chỉ cần sử dụng const với độ dài tối đa.
venimus

25
function generateRandomString($length = 15)
{
    return substr(sha1(rand()), 0, $length);
}

Tada!


Hãy ghi nhớ sha1sẽ dẫn đến giới hạn 40 ký tự và luôn luôn ký tự viết thường.
fyrye

3
chuỗi sha1 không ngẫu nhiên, một số ký tự nhất định sẽ xảy ra thường xuyên hơn các chuỗi khác. Sẽ là không khôn ngoan khi sử dụng điều này trong trường hợp bạn thực sự muốn ngẫu nhiên như đối với mật khẩu.
Kit Sunde

1
@KitSunde - vâng, sha không phải là ngẫu nhiên, rand () là ngẫu nhiên. Và sha là hoàn toàn tốt cho những gì cần thiết ở đây. OP không cần mức độ ngẫu nhiên của tiền điện tử.
Thưởng thức

@Davor rant()là ngẫu nhiên không thành vấn đề khi sha không được phân phối đều. Nếu bạn chọn ngẫu nhiên từ một phân phối không đồng đều, bạn sẽ có được phân phối không đồng đều chính xác. Đó không phải là sự ngẫu nhiên "cấp độ tiền điện tử" mà tôi nhấn mạnh, nếu đó là trường hợp bạn không nên sử dụng rand(). Phải mất nỗ lực tối thiểu để nhận được từ một phân phối đồng đều như trong câu trả lời được chấp nhận và nó ngẫu nhiên như rand () là điều hợp lý như vậy.
Kit Sunde

@KitSunde - nó thực sự không có sự khác biệt cuối cùng. Đó chính xác là định nghĩa của sự áp đảo và mạ vàng.
Thưởng thức

24

Một cách tốt hơn để thực hiện chức năng này là:

function RandomString($length) {
    $keys = array_merge(range(0,9), range('a', 'z'));

    $key = "";
    for($i=0; $i < $length; $i++) {
        $key .= $keys[mt_rand(0, count($keys) - 1)];
    }
    return $key;
}

echo RandomString(20);

mt_randlà ngẫu nhiên hơn theo điều nàyđiều này trong PHP 7. randHàm này là bí danh của mt_rand.


1
Thận trọng: mt_randkhông tạo ra các giá trị bảo mật bằng mật mã. Vì vậy, bạn nên sử dụng PHP7 random_inthoặc random_bytes.
jchook 20/03/18

18

$randstringtrong phạm vi chức năng không giống như phạm vi mà bạn gọi nó. Bạn phải gán giá trị trả về cho một biến.

$randstring = RandomString();
echo $randstring;

Hoặc chỉ trực tiếp lặp lại giá trị trả về:

echo RandomString();

Ngoài ra, trong chức năng của bạn, bạn có một chút sai lầm. Trong vòng lặp for, bạn cần sử dụng .=để mỗi ký tự được nối vào chuỗi. Bằng cách sử dụng, =bạn đang ghi đè lên nó với mỗi ký tự mới thay vì nối thêm.

$randstring .= $characters[rand(0, strlen($characters))];

14

Đầu tiên, bạn xác định bảng chữ cái bạn muốn sử dụng:

$alphanum = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
$special  = '~!@#$%^&*(){}[],./?';
$alphabet = $alphanum . $special;

Sau đó, sử dụng openssl_random_pseudo_bytes()để tạo dữ liệu ngẫu nhiên thích hợp:

$len = 12; // length of password
$random = openssl_random_pseudo_bytes($len);

Cuối cùng, bạn sử dụng dữ liệu ngẫu nhiên này để tạo mật khẩu. Bởi vì mỗi ký tự $randomcó thể tồn tại chr(0)cho đến khi chr(255), mã sử dụng phần còn lại sau khi chia giá trị thứ tự của nó với $alphabet_lengthđể đảm bảo chỉ các ký tự trong bảng chữ cái được chọn (lưu ý rằng làm như vậy sẽ làm sai lệch tính ngẫu nhiên):

$alphabet_length = strlen($alphabet);
$password = '';
for ($i = 0; $i < $len; ++$i) {
    $password .= $alphabet[ord($random[$i]) % $alphabet_length];
}

Ngoài ra, và nói chung là tốt hơn, là sử dụng RandomLibSecurityLib :

use SecurityLib\Strength;

$factory = new RandomLib\Factory;
$generator = $factory->getGenerator(new Strength(Strength::MEDIUM));

$password = $generator->generateString(12, $alphabet);

Việc sử dụng toán tử modulo %sẽ tạo ra đầu ra sai lệch. Tuy nhiên, +1 mạnh cho RandomLib. Đừng phát minh lại bánh xe.
Scott Arciszewski

1
Vâng, hàm Random_int () mới rất hay: D
Ja͢ck

11

Phương pháp ngắn ..

Dưới đây là một số phương pháp ngắn nhất để tạo chuỗi ngẫu nhiên

<?php
echo $my_rand_strng = substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), -15); 

echo substr(md5(rand()), 0, 7);

echo str_shuffle(MD5(microtime()));
?>

10

Tôi đã kiểm tra hiệu năng của hầu hết các chức năng phổ biến ở đó, thời gian cần thiết để tạo ra 1000'000 chuỗi gồm 32 ký hiệu trên hộp của tôi là:

2.5 $s = substr(str_shuffle(str_repeat($x='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', ceil($length/strlen($x)) )),1,32);
1.9 $s = base64_encode(openssl_random_pseudo_bytes(24));
1.68 $s = bin2hex(openssl_random_pseudo_bytes(16));
0.63 $s = base64_encode(random_bytes(24));
0.62 $s = bin2hex(random_bytes(16));
0.37 $s = substr(md5(rand()), 0, 32);
0.37 $s = substr(md5(mt_rand()), 0, 32);

Xin lưu ý không quan trọng là nó thực sự dài bao nhiêu nhưng chậm hơn và cái nào nhanh hơn để bạn có thể chọn theo yêu cầu của mình, bao gồm cả mật mã, sẵn sàng, v.v.

chất nền () xung quanh MD5 đã được thêm vào vì độ chính xác nếu bạn cần chuỗi ngắn hơn 32 ký hiệu.

Vì lợi ích của câu trả lời: chuỗi không được nối nhưng được ghi đè và kết quả của hàm không được lưu trữ.


Tôi nghĩ rằng, câu trả lời tốt nhất. Cảm ơn!
NSukonny

10

PHP 7+ Tạo các byte ngẫu nhiên được bảo mật bằng mật mã bằng hàm Random_bytes .

$bytes = random_bytes(16);
echo bin2hex($bytes);

Sản lượng có thể

da821217e61e33ed4b2dd96f8439056c


PHP 5.3+ Tạo các byte giả ngẫu nhiên bằng cách sử dụng hàm openssl_random_pseudo_bytes .

$bytes = openssl_random_pseudo_bytes(16);
echo bin2hex($bytes);

Sản lượng có thể

e2d1254506fbb6cd842cd640333214ad


Các trường hợp sử dụng tốt nhất có thể

function getRandomBytes($length = 16)
{
    if (function_exists('random_bytes')) {
        $bytes = random_bytes($length / 2);
    } else {
        $bytes = openssl_random_pseudo_bytes($length / 2);
    }
    return bin2hex($bytes);
}
echo getRandomBytes();

Sản lượng có thể

ba8cc342bdf91143


Điều này sẽ không tạo ra một chuỗi với độ dài nhất định
Timberman

@Timberman nó sẽ tạo ra độ dài chính xác bây giờ.
Madan Sapkota

9

Một cách rất nhanh là làm một cái gì đó như:

substr(md5(rand()),0,10);

Điều này sẽ tạo ra một chuỗi ngẫu nhiên với độ dài 10 ký tự. Tất nhiên, một số người có thể nói rằng nó nặng hơn một chút về mặt tính toán, nhưng ngày nay các bộ xử lý được tối ưu hóa để chạy thuật toán md5 hoặc sha256 rất nhanh. Và tất nhiên, nếu rand()hàm trả về cùng một giá trị, kết quả sẽ giống nhau, có cơ hội là 1/3276767 giống nhau. Nếu vấn đề bảo mật, thì chỉ cần thay đổi rand()thànhmt_rand()


7
function rndStr($len = 64) {
     $randomData = file_get_contents('/dev/urandom', false, null, 0, $len) . uniqid(mt_rand(), true);
     $str = substr(str_replace(array('/','=','+'),'', base64_encode($randomData)),0,$len);
    return $str;
}

4
Đây không phải là di động; nếu bạn cố chạy cái này trong bất kỳ môi trường không tích cực nào, nó sẽ gây ra lỗi nghiêm trọng.
Bryan Agee

7

Cái này được lấy từ các nguồn adminer :

/** Get a random string
* @return string 32 hexadecimal characters
*/
function rand_string() {
    return md5(uniqid(mt_rand(), true));
}

Adminer , công cụ quản lý cơ sở dữ liệu viết bằng PHP.


6

Chức năng trợ giúp từ khung công tác Laravel 5

/**
 * Generate a "random" alpha-numeric string.
 *
 * Should not be considered sufficient for cryptography, etc.
 *
 * @param  int  $length
 * @return string
 */
function str_random($length = 16)
{
    $pool = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';

    return substr(str_shuffle(str_repeat($pool, $length)), 0, $length);
}

4
"Không nên được coi là đủ cho mật mã, v.v." Điều này cần được nhấn mạnh.
Scott Arciszewski


4

Phiên bản chỉnh sửa của hàm hoạt động tốt, nhưng chỉ có một vấn đề tôi tìm thấy: Bạn đã sử dụng sai ký tự để bao quanh các ký tự $, do đó, ký tự 'đôi khi là một phần của chuỗi ngẫu nhiên được tạo.

Để khắc phục điều này, hãy thay đổi:

$characters = 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ’;

đến:

$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';

Cách này chỉ sử dụng các ký tự kèm theo và ký tự 'sẽ không bao giờ là một phần của chuỗi ngẫu nhiên được tạo.


4

Một lớp lót khác, tạo ra một chuỗi ngẫu nhiên gồm 10 ký tự với các chữ cái và số. Nó sẽ tạo một mảng với range(điều chỉnh tham số thứ hai để đặt kích thước), lặp qua mảng này và gán một ký tự ASCII ngẫu nhiên (phạm vi 0-9 hoặc az), sau đó mã hóa mảng để lấy chuỗi.

$str = implode('', array_map(function () { return chr(rand(0, 1) ? rand(48, 57) : rand(97, 122)); }, range(0, 9)));

Lưu ý: điều này chỉ hoạt động trong PHP 5.3 trở lên


cuối cùng là một giải pháp thực sự ngẫu nhiên không phải là một số băm đầy đủ của một số nguyên ngẫu nhiên 32 bit hoặc một chuỗi xáo trộn ...
Surrican

Chỉ có một vấn đề: các con số có khả năng xảy ra như các ký tự, điều này không ngẫu nhiên như tôi muốn có nó. anyaway +1 cho giải pháp tốt nhất trên trang này. điều chỉnh và hoàn hảo của nó.
Surrican

chỉnh ... như thế này? rand(0, 57-48+122-97)<57-48?...:...? :)
vp_arth

4

Lót.

Nó là nhanh chóng cho các chuỗi lớn với một số tính độc đáo.

function random_string($length){
    return substr(str_repeat(md5(rand()), ceil($length/32)), 0, $length);
}

md5(rand())là một cách không an toàn khủng khiếp để tạo ra một số ngẫu nhiên.
Scott Arciszewski

1
một chuỗi có độ dài X và một số tính duy nhất là ý định. sự ngẫu nhiên thực sự không phải là ý định.
Jacob Smith


3

Tôi thích bình luận cuối cùng sử dụng openssl_random_pseudo_bytes, nhưng đó không phải là giải pháp cho tôi vì tôi vẫn phải xóa các ký tự mà tôi không muốn và tôi không thể có được một chuỗi độ dài đã đặt. Đây là giải pháp của tôi ...

function rndStr($len = 20) {
    $rnd='';
    for($i=0;$i<$len;$i++) {
        do {
            $byte = openssl_random_pseudo_bytes(1);
            $asc = chr(base_convert(substr(bin2hex($byte),0,2),16,10));
        } while(!ctype_alnum($asc));
        $rnd .= $asc;
    }
    return $rnd;
}

3
function randomString($length = 5) {
    return substr(str_shuffle(implode(array_merge(range('A','Z'), range('a','z'), range(0,9)))), 0, $length);
}

3

Đây là giải pháp một dòng đơn giản của tôi để tạo mật khẩu ngẫu nhiên thân thiện sử dụng, ngoại trừ các ký tự trông giống như "1" và "l", "O" và "0", v.v ... ở đây có 5 ký tự nhưng bạn có thể dễ dàng thay đổi nó tất nhiên:

$user_password = substr(str_shuffle('abcdefghjkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ23456789'),0,5);

Điều này là hoàn hảo để tạo các chuỗi ID ngẫu nhiên để gọi sau này trên jquery. IDK nếu nó thực hành tốt nhưng điều này đã giúp tôi rất nhiều, mà không sử dụng câu trả lời như được chấp nhận ...
Rodrigo Zuluaga

3

Đây là một giải pháp khác.

function genRandomString($length = 10)
{
    if($length < 1)
        $length = 1;
    return substr(preg_replace("/[^A-Za-z0-9]/", '', base64_encode(openssl_random_pseudo_bytes($length * 2))), 0, $length);
}

Tái bút Tôi đang sử dụng PHP 7.2 trên Ubuntu.


2

Một cách khác để tạo một chuỗi ngẫu nhiên trong PHP là:

function RandomString($length) {
    $original_string = array_merge(range(0,9), range('a','z'), range('A', 'Z'));
    $original_string = implode("", $original_string);
    return substr(str_shuffle($original_string), 0, $length);
}
echo RandomString(6);

2

Đây là cách tôi đang thực hiện để có được một khóa ngẫu nhiên duy nhất thực sự:

$Length = 10;
$RandomString = substr(str_shuffle(md5(time())), 0, $Length);
echo $RandomString;

Bạn có thể sử dụng time () vì đây là dấu thời gian Unix và luôn duy nhất so với các ngẫu nhiên khác được đề cập ở trên. Sau đó, bạn có thể tạo md5sum của điều đó và lấy độ dài mong muốn bạn cần từ MD5 được tạo chuỗi . Trong trường hợp này, tôi đang sử dụng 10 ký tự và tôi có thể sử dụng chuỗi dài hơn nếu tôi muốn làm cho nó độc đáo hơn.

Tôi hi vọng cái này giúp được.


2
Tất nhiên, khác time()xa với duy nhất: nó sẽ trả lại cùng một giá trị cho đến khi kết thúc thứ hai hiện tại. Điều thực sự cung cấp một số tính ngẫu nhiên ở đây là str_shuffle()phần còn lại của mã chỉ làm giảm mẫu để chọn ký tự.
Álvaro González

1
Vì vậy, những gì bạn đang làm về cơ bản là xáo trộn xung quanh một số nguyên 32 bit. không có nhiều entropy ở đây ...
The Surrican

2
Kẻ tấn công có thể đoán giá trị được trả về time()(chỉ là dấu thời gian), đó là nguồn ngẫu nhiên yếu.
AL

2

Tham số một lớp chỉ sử dụng các hàm riêng của PHP , hoạt động kể từ PHP 5.1.0

str_shuffle(implode('', (array_intersect_key(($map =  array_map('chr', array_merge(array_map('mt_rand', array_fill(0, $length = 25, 48), array_fill(0,$length,57)),array_map('mt_rand', array_fill(0, $length, 65), array_fill(0,$length,90)),array_map('mt_rand', array_fill(0, $length, 97), array_fill(0,$length,122))))), array_flip($keys = array_rand($map, $length))))))
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.