PHP: Làm thế nào để tạo một chuỗi ngẫu nhiên, duy nhất, chữ và số?


380

Làm thế nào có thể tạo ra một chuỗi ngẫu nhiên, duy nhất bằng cách sử dụng số và chữ cái để sử dụng trong một liên kết xác minh? Giống như khi bạn tạo một tài khoản trên một trang web và nó sẽ gửi cho bạn một email có liên kết và bạn phải nhấp vào liên kết đó để xác minh tài khoản của mình ... vâng ... một trong số đó.

Làm thế nào tôi có thể tạo một trong những người sử dụng PHP?

Cập nhật: Chỉ cần nhớ về uniqid(). Đây là một hàm PHP tạo ra một mã định danh duy nhất dựa trên thời gian hiện tại tính bằng micro giây. Tôi nghĩ rằng tôi sẽ sử dụng nó.


Tất cả bạn cần là chuỗi và số ngẫu nhiên phân phối đồng đều.
Artelius

10
Này Andrew, bạn nên chọn Scottlà câu trả lời đúng. Scott đang sử dụng trình tạo số giả ngẫu nhiên (CSPRNG) bảo mật mã hóa của OpenSSL, sẽ chọn nguồn entropy an toàn nhất dựa trên nền tảng của bạn.
rook

3
Bất cứ ai đọc nó sau năm 2015, xin vui lòng xem tại đây: paragonie.com/blog/2015/07/ Hầu hết các câu trả lời hàng đầu đều thiếu sót ít nhiều ...
rugk

OpenSSL và uniqidkhông an toàn. Sử dụng một cái gì đó như Random::alphanumericString($length)hoặc Random::alphanumericHumanString($length).
caw

Câu trả lời:


305

Thông báo bảo mật : Không nên sử dụng giải pháp này trong các tình huống mà chất lượng ngẫu nhiên của bạn có thể ảnh hưởng đến bảo mật của ứng dụng. Cụ thể, rand()uniqid()không phải là trình tạo số ngẫu nhiên an toàn bằng mật mã . Xem câu trả lời của Scott cho một sự thay thế an toàn.

Nếu bạn không cần nó phải hoàn toàn độc đáo theo thời gian:

md5(uniqid(rand(), true))

Mặt khác (với điều kiện bạn đã xác định thông tin đăng nhập duy nhất cho người dùng của mình):

md5(uniqid($your_user_login, true))

90
Cả hai phương pháp đều không đảm bảo tính duy nhất - độ dài của đầu vào của hàm md5 lớn hơn độ dài đầu ra của nó và theo en.wikipedia.org/wiki/Pigeonhole_principl, sự va chạm được đảm bảo. Mặt khác, dân số dựa vào băm càng lớn để đạt được id "duy nhất", xác suất xảy ra ít nhất một vụ va chạm (xem en.wikipedia.org/wiki/Bapt_probols ). Xác suất có thể rất nhỏ đối với hầu hết các giải pháp nhưng nó vẫn tồn tại.
Dariusz Walczak

12
Đây không phải là một phương pháp an toàn để tạo ra các giá trị ngẫu nhiên. Xem câu trả lời của Scott.
rook

4
Đối với các xác nhận email sẽ hết hạn tương đối sớm, tôi nghĩ khả năng nhỏ là một người có thể một ngày nào đó xác nhận email của người khác là một rủi ro không đáng kể. Nhưng bạn luôn có thể kiểm tra xem mã thông báo đã tồn tại trong DB hay chưa sau khi tạo nó và chỉ cần chọn một mã mới nếu đó là trường hợp. Tuy nhiên, thời gian bạn dành để viết đoạn mã đó có thể bị lãng phí vì rất có thể nó sẽ không bao giờ được chạy.
Andrew

Xin lưu ý rằng md5 trả về giá trị thập lục phân, nghĩa là bộ ký tự được giới hạn ở [0-9] và [af].
Thijs Riezebeek

1
md5 có thể có va chạm, bạn vừa phá hỏng lợi thế của uniqid
user151496

507

Tôi chỉ xem xét cách giải quyết vấn đề tương tự, nhưng tôi cũng muốn chức năng của mình tạo ra một mã thông báo có thể được sử dụng để truy xuất mật khẩu. Điều này có nghĩa là tôi cần hạn chế khả năng đoán mã thông báo. Bởi vì uniqiddựa trên thời gian và theo php.net, "giá trị trả về hơi khác so với microtime ()", uniqidkhông đáp ứng các tiêu chí. PHP khuyên bạn nên sử dụng openssl_random_pseudo_bytes()thay vì tạo mã thông báo bảo mật bằng mật mã.

Câu trả lời nhanh, ngắn gọn và chính xác là:

bin2hex(openssl_random_pseudo_bytes($bytes))

sẽ tạo ra một chuỗi ký tự chữ và số ngẫu nhiên có độ dài = $ byte * 2. Thật không may, cái này chỉ có một bảng chữ cái [a-f][0-9], nhưng nó hoạt động.


Dưới đây là chức năng mạnh nhất tôi có thể thực hiện để đáp ứng các tiêu chí (Đây là phiên bản được thực hiện của câu trả lời của Erik).

function crypto_rand_secure($min, $max)
{
    $range = $max - $min;
    if ($range < 1) return $min; // not so random...
    $log = ceil(log($range, 2));
    $bytes = (int) ($log / 8) + 1; // length in bytes
    $bits = (int) $log + 1; // length in bits
    $filter = (int) (1 << $bits) - 1; // set all lower bits to 1
    do {
        $rnd = hexdec(bin2hex(openssl_random_pseudo_bytes($bytes)));
        $rnd = $rnd & $filter; // discard irrelevant bits
    } while ($rnd > $range);
    return $min + $rnd;
}

function getToken($length)
{
    $token = "";
    $codeAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    $codeAlphabet.= "abcdefghijklmnopqrstuvwxyz";
    $codeAlphabet.= "0123456789";
    $max = strlen($codeAlphabet); // edited

    for ($i=0; $i < $length; $i++) {
        $token .= $codeAlphabet[crypto_rand_secure(0, $max-1)];
    }

    return $token;
}

crypto_rand_secure($min, $max)hoạt động như một sự thay thế cho rand()hoặc mt_rand. Nó sử dụng openssl_random_pseudo_bytes để giúp tạo một số ngẫu nhiên trong khoảng từ $ min đến $ max.

getToken($length)tạo một bảng chữ cái để sử dụng trong mã thông báo và sau đó tạo một chuỗi độ dài $length.

EDIT: Tôi đã bỏ qua việc trích dẫn nguồn - http://us1.php.net/manual/en/feft.openssl-random-pseudo-bytes.php#104322

EDIT (PHP7): Với việc phát hành PHP7, thư viện chuẩn hiện có hai chức năng mới có thể thay thế / cải thiện / đơn giản hóa chức năng crypto_rand_secure ở trên. random_bytes($length)random_int($min, $max)

http://php.net/manual/en/feft.random-bytes.php

http://php.net/manual/en/feft.random-int.php

Thí dụ:

function getToken($length){
    $token = "";
    $codeAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    $codeAlphabet.= "abcdefghijklmnopqrstuvwxyz";
    $codeAlphabet.= "0123456789";
    $max = strlen($codeAlphabet);

    for ($i=0; $i < $length; $i++) {
        $token .= $codeAlphabet[random_int(0, $max-1)];
    }

    return $token;
}

2
Đã đồng ý. Lưu trữ mật khẩu Plaintext là khủng khiếp! (Tôi sử dụng blowfish.) Nhưng sau khi mã thông báo được tạo, nó cho phép chủ sở hữu mã thông báo đặt lại mật khẩu, vì vậy mã thông báo tương đương với mật khẩu trong khi nó hợp lệ (và được xử lý như vậy).
Scott

23
Xin chào, tôi đã kết hợp mã tuyệt vời của bạn với chức năng phương thức Kohana Text :: Random () tiện lợi và tạo ra ý chính này: gist.github.com/raveren/5555297
raveren

9
Hoàn hảo! Tôi đã thử nó với 10 ký tự như chiều dài. 100000 mã thông báo và vẫn không có bản sao!
Shar Xếp512

5
Tôi đã sử dụng quá trình này và thấy nó siêu chậm. Với độ dài 36, nó đã hết thời gian trên máy chủ dev. Với độ dài 24, nó vẫn mất khoảng 30 giây. Không chắc chắn những gì tôi đã làm sai nhưng nó quá chậm đối với tôi và tôi đã chọn một giải pháp khác.
Shane

5
Bạn cũng có thể sử dụng base64_encodethay vì bin2hexđể có được một chuỗi ngắn hơn với bảng chữ cái lớn hơn.
erjiang

91

Phiên bản hướng đối tượng của giải pháp được bình chọn nhiều nhất

Tôi đã tạo ra một giải pháp hướng đối tượng dựa trên câu trả lời của Scott :

<?php

namespace Utils;

/**
 * Class RandomStringGenerator
 * @package Utils
 *
 * Solution taken from here:
 * http://stackoverflow.com/a/13733588/1056679
 */
class RandomStringGenerator
{
    /** @var string */
    protected $alphabet;

    /** @var int */
    protected $alphabetLength;


    /**
     * @param string $alphabet
     */
    public function __construct($alphabet = '')
    {
        if ('' !== $alphabet) {
            $this->setAlphabet($alphabet);
        } else {
            $this->setAlphabet(
                  implode(range('a', 'z'))
                . implode(range('A', 'Z'))
                . implode(range(0, 9))
            );
        }
    }

    /**
     * @param string $alphabet
     */
    public function setAlphabet($alphabet)
    {
        $this->alphabet = $alphabet;
        $this->alphabetLength = strlen($alphabet);
    }

    /**
     * @param int $length
     * @return string
     */
    public function generate($length)
    {
        $token = '';

        for ($i = 0; $i < $length; $i++) {
            $randomKey = $this->getRandomInteger(0, $this->alphabetLength);
            $token .= $this->alphabet[$randomKey];
        }

        return $token;
    }

    /**
     * @param int $min
     * @param int $max
     * @return int
     */
    protected function getRandomInteger($min, $max)
    {
        $range = ($max - $min);

        if ($range < 0) {
            // Not so random...
            return $min;
        }

        $log = log($range, 2);

        // Length in bytes.
        $bytes = (int) ($log / 8) + 1;

        // Length in bits.
        $bits = (int) $log + 1;

        // Set all lower bits to 1.
        $filter = (int) (1 << $bits) - 1;

        do {
            $rnd = hexdec(bin2hex(openssl_random_pseudo_bytes($bytes)));

            // Discard irrelevant bits.
            $rnd = $rnd & $filter;

        } while ($rnd >= $range);

        return ($min + $rnd);
    }
}

Sử dụng

<?php

use Utils\RandomStringGenerator;

// Create new instance of generator class.
$generator = new RandomStringGenerator;

// Set token length.
$tokenLength = 32;

// Call method to generate random string.
$token = $generator->generate($tokenLength);

Bảng chữ cái tùy chỉnh

Bạn có thể sử dụng bảng chữ cái tùy chỉnh nếu cần thiết. Chỉ cần truyền một chuỗi có ký tự được hỗ trợ cho hàm tạo hoặc setter:

<?php

$customAlphabet = '0123456789ABCDEF';

// Set initial alphabet.
$generator = new RandomStringGenerator($customAlphabet);

// Change alphabet whenever needed.
$generator->setAlphabet($customAlphabet);

Đây là mẫu đầu ra

SRniGU2sRQb2K1ylXKnWwZr4HrtdRgrM
q1sRUjNq1K9rG905aneFzyD5IcqD4dlC
I0euIWffrURLKCCJZ5PQFcNUCto6cQfD
AKwPJMEM5ytgJyJyGqoD5FQwxv82YvMr
duoRF6gAawNOEQRICnOUNYmStWmOpEgS
sdHUkEn4565AJoTtkc8EqJ6cC4MLEHUx
eVywMdYXczuZmHaJ50nIVQjOidEVkVna
baJGt7cdLDbIxMctLsEBWgAw5BByP5V0
iqT0B2obq3oerbeXkDVLjZrrLheW4d8f
OUQYCny6tj2TYDlTuu1KsnUyaLkeObwa

Tôi hy vọng nó sẽ giúp được ai đó. Chúc mừng!


Tôi xin lỗi nhưng làm thế nào để tôi chạy thứ này? Tôi đã làm $obj = new RandomStringGenerator;nhưng tôi nên gọi phương pháp nào? Cảm ơn bạn.
sg552

@ sg552, bạn nên gọi generatephương thức như trong ví dụ trên. Chỉ cần truyền một số nguyên cho nó để xác định độ dài của chuỗi kết quả.
Slava Fomin II

Cảm ơn nó hoạt động cho tôi nhưng Custom Alphabetkhông. Tôi nhận được đầu ra trống khi tôi lặp lại. Dù sao, tôi thậm chí không chắc việc sử dụng ví dụ thứ 2 là gì Custom Alphabetnên tôi nghĩ tôi chỉ ở lại với ví dụ đầu tiên. Cảm ơn.
sg552

1
Đẹp, nhưng quá mức cần thiết trong hầu hết các kịch bản, trừ khi dự án của bạn phụ thuộc nhiều vào các mã được tạo ngẫu nhiên
dspacejs

1
có tốt nhưng quá mức cần thiết, đặc biệt là xem xét nó hiện đã bị phản đối khá nhiều đối với php 5.7
Andrew

39

Tôi đến trễ nhưng tôi ở đây với một số dữ liệu nghiên cứu tốt dựa trên các chức năng được cung cấp bởi câu trả lời của Scott . Vì vậy, tôi đã thiết lập một giọt Digital Ocean chỉ cho thử nghiệm tự động dài 5 ngày này và lưu trữ các chuỗi duy nhất được tạo trong cơ sở dữ liệu MySQL.

Trong thời gian thử nghiệm này, tôi đã sử dụng 5 độ dài khác nhau (5, 10, 15, 20, 50) và +/- 0,5 triệu bản ghi được chèn cho mỗi độ dài. Trong quá trình thử nghiệm của tôi, chỉ có độ dài 5 tạo ra +/- 3K trùng lặp trong số 0,5 triệu và các độ dài còn lại không tạo ra bất kỳ bản sao nào. Vì vậy, chúng ta có thể nói rằng nếu chúng ta sử dụng độ dài từ 15 trở lên với các hàm của Scott, thì chúng ta có thể tạo các chuỗi duy nhất có độ tin cậy cao. Đây là bảng hiển thị dữ liệu nghiên cứu của tôi:

nhập mô tả hình ảnh ở đây

Cập nhật: Tôi đã tạo một ứng dụng Heroku đơn giản bằng cách sử dụng các hàm này trả về mã thông báo dưới dạng phản hồi JSON. Ứng dụng có thể được truy cập tại https://uniquestrings.herokuapp.com/api/token?length=15

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


33

Bạn có thể sử dụng UUID (Mã định danh duy nhất toàn cầu), nó có thể được sử dụng cho mọi mục đích, từ chuỗi xác thực người dùng đến id giao dịch thanh toán.

UUID là số 16 octet (128 bit). Ở dạng chính tắc, UUID được biểu thị bằng 32 chữ số thập lục phân, được hiển thị trong năm nhóm được phân tách bằng dấu gạch nối, ở dạng 8-4-4-4-12 cho tổng cộng 36 ký tự (32 ký tự chữ và số và bốn dấu gạch nối).

function generate_uuid() {
    return sprintf( '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
        mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ),
        mt_rand( 0, 0xffff ),
        mt_rand( 0, 0x0C2f ) | 0x4000,
        mt_rand( 0, 0x3fff ) | 0x8000,
        mt_rand( 0, 0x2Aff ), mt_rand( 0, 0xffD3 ), mt_rand( 0, 0xff4B )
    );

}

// gọi chức năng

$transationID = generate_uuid();

một số ví dụ đầu ra sẽ như sau:

E302D66D-87E3-4450-8CB6-17531895BF14
22D288BC-7289-442B-BEEA-286777D559F2
51B4DE29-3B71-4FD2-9E6C-071703E1FF31
3777C8C6-9FF5-4C78-AAA2-08A47F555E81
54B91C72-2CF4-4501-A6E9-02A60DCBAE4C
60F75C7C-1AE3-417B-82C8-14D456542CD7
8DE0168D-01D3-4502-9E59-10D665CEBCB2

hy vọng nó sẽ giúp được ai đó trong tương lai :)


Trông thật tuyệt vời, được thêm vào danh sách của tôi!
Mustafa Erdogan

32

Hàm này sẽ tạo một khóa ngẫu nhiên bằng cách sử dụng số và chữ cái:

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

    for ($i = 0; $i < $length; $i++) {
        $key .= $keys[array_rand($keys)];
    }

    return $key;
}

echo random_string(50);

Ví dụ đầu ra:

zsd16xzv3jsytnp87tk7ygv73k8zmr0ekh6ly7mxaeyeh46oe8

6
Sau một thời gian, bạn có được những con số tương tự
Sharrial512

1
Điều này không hoàn toàn ngẫu nhiên bởi vì nó sẽ không bao giờ có cùng một bộ đếm nhiều hơn một lần.
EricP

16

Tôi sử dụng một lớp lót này:

base64_encode(openssl_random_pseudo_bytes(3 * ($length >> 2)));

trong đó độ dài là chiều dài của chuỗi mong muốn (chia hết cho 4, nếu không, nó được làm tròn xuống đến số gần nhất chia hết cho 4)


6
Nó không luôn luôn trả về các ký tự chữ và số. Nó có thể chứa các ký tự như==
user3459110

1
Nếu được sử dụng trong một URL, base64url_encodecó thể được sử dụng thay thế, hãy xem tại đây: php.net/manual/en/feft.base64-encode.php
Paul

9

Sử dụng mã dưới đây để tạo số lượng ngẫu nhiên 11 ký tự hoặc thay đổi số theo yêu cầu của bạn.

$randomNum=substr(str_shuffle("0123456789abcdefghijklmnopqrstvwxyz"), 0, 11);

hoặc chúng ta có thể sử dụng chức năng tùy chỉnh để tạo số ngẫu nhiên

 function randomNumber($length){
     $numbers = range(0,9);
     shuffle($numbers);
     for($i = 0;$i < $length;$i++)
        $digits .= $numbers[$i];
     return $digits;
 }

 //generate random number
 $randomNum=randomNumber(11);

3
Điều này không bao giờ có thể tạo ra chuỗi "aaaaaaaaaaa" hoặc "aaaaabbbbbb". Nó chỉ chọn một chuỗi con của một hoán vị ngẫu nhiên của bảng chữ cái. Chuỗi dài 11 ký tự chỉ có V (11,35) = 288 giá trị có thể. Không sử dụng điều này nếu bạn mong muốn các chuỗi là duy nhất!
kdojeteri

@Peping thì làm substr(str_shuffle(str_repeat('0123456789abcdefghijklmnopqrstvwxyz', 36)), 0, 11);
Tim Hallman

7
  1. Tạo số ngẫu nhiên bằng trình tạo số ngẫu nhiên yêu thích của bạn
  2. Nhân và chia nó để có được một số khớp với số lượng ký tự trong bảng chữ cái mã của bạn
  3. Lấy mục tại chỉ mục đó trong bảng chữ cái mã của bạn.
  4. Lặp lại từ 1) cho đến khi bạn có độ dài bạn muốn

ví dụ (bằng mã giả)

int myInt = random(0, numcharacters)
char[] codealphabet = 'ABCDEF12345'
char random = codealphabet[i]
repeat until long enough

Về mặt lý thuyết, điều này có khả năng tạo ra cùng một chuỗi nhiều lần không?
frezq

4

Đây là trình tạo id duy nhất cuối cùng cho bạn. được thực hiện bởi tôi.

<?php
$d=date ("d");
$m=date ("m");
$y=date ("Y");
$t=time();
$dmt=$d+$m+$y+$t;    
$ran= rand(0,10000000);
$dmtran= $dmt+$ran;
$un=  uniqid();
$dmtun = $dmt.$un;
$mdun = md5($dmtran.$un);
$sort=substr($mdun, 16); // if you want sort length code.

echo $mdun;
?>

bạn có thể lặp lại bất kỳ 'var' nào cho id của bạn như bạn muốn. nhưng $ mdun tốt hơn, bạn có thể thay thế md5 thành sha1 để có mã tốt hơn nhưng sẽ rất lâu mà bạn không cần.

Cảm ơn bạn.


7
Trong trường hợp này tính ngẫu nhiên được đảm bảo bằng mã viết ngẫu nhiên, phải không?
Daniel Kucal

3
vâng, đây là loại "ngẫu nhiên" vì nó không phải là mã tiêu chuẩn, tối nghĩa. Điều này gây khó khăn cho việc dự đoán ... nhưng thực tế nó không sử dụng các phần không an toàn để tạo số ngẫu nhiên. do đó, kết quả là về mặt kỹ thuật không ngẫu nhiên hoặc an toàn.
Philipp

4

Đối với các chuỗi thực sự ngẫu nhiên, bạn có thể sử dụng

<?php

echo md5(microtime(true).mt_Rand());

đầu ra:

40a29479ec808ad4bcff288a48a25d5c

vì vậy ngay cả khi bạn cố gắng tạo chuỗi nhiều lần cùng một lúc, bạn sẽ nhận được đầu ra khác nhau.


4

Khi cố gắng tạo mật khẩu ngẫu nhiên, bạn đang cố gắng:

  • Đầu tiên tạo ra một tập hợp các byte ngẫu nhiên được bảo mật bằng mật mã

  • Thứ hai là biến các byte ngẫu nhiên đó thành một chuỗi có thể in được

Bây giờ, có nhiều cách để tạo các byte ngẫu nhiên trong php như:

$length = 32;

//PHP 7+
$bytes= random_bytes($length);

//PHP < 7
$bytes= openssl_random_pseudo_bytes($length);

Sau đó, bạn muốn biến các byte ngẫu nhiên này thành một chuỗi có thể in:

Bạn có thể sử dụng bin2hex :

$string = bin2hex($bytes);

hoặc cơ sở64_encode :

$string = base64_encode($bytes);

Tuy nhiên, lưu ý rằng bạn không kiểm soát độ dài của chuỗi nếu bạn sử dụng base64. Bạn có thể sử dụng bin2hex để làm điều đó, sử dụng 32 byte sẽ biến thành chuỗi 64 char . Nhưng nó sẽ chỉ hoạt động như vậy trong một chuỗi EVEN .

Vì vậy, về cơ bản bạn chỉ có thể làm :

$length = 32;

if(PHP_VERSION>=7){
    $bytes= random_bytes($length);
}else{
    $bytes= openssl_random_pseudo_bytes($length);
} 

$string = bin2hex($bytes);

3

Đây là những gì tôi sử dụng:

md5(time() . rand());    
// Creates something like 0c947c3b1047334f5bb8a3b7adc1d97b

2
function random_string($length = 8) {
    $alphabets = range('A','Z');
    $numbers = range('0','9');
    $additional_characters = array('_','=');
    $final_array = array_merge($alphabets,$numbers,$additional_characters);
       while($length--) {
      $key = array_rand($final_array);

      $password .= $final_array[$key];
                        }
  if (preg_match('/[A-Za-z0-9]/', $password))
    {
     return $password;
    }else{
    return  random_string();
    }

 }

2

Đây là một hàm đơn giản cho phép bạn tạo các chuỗi ngẫu nhiên có chứa Chữ và số (chữ và số). Bạn cũng có thể giới hạn độ dài chuỗi. Các chuỗi ngẫu nhiên này có thể được sử dụng cho các mục đích khác nhau, bao gồm: Mã giới thiệu, Mã khuyến mại, Mã phiếu giảm giá. Hàm dựa vào các hàm PHP sau: base_convert, sha1, uniqid, mt_rand

function random_code($length)
{
  return substr(base_convert(sha1(uniqid(mt_rand())), 16, 36), 0, $length);
}

echo random_code(6);

/*sample output
* a7d9e8
* 3klo93
*/

1

sau khi đọc các ví dụ trước tôi đã nghĩ ra điều này:

protected static $nonce_length = 32;

public static function getNonce()
{
    $chars = array();
    for ($i = 0; $i < 10; $i++)
        $chars = array_merge($chars, range(0, 9), range('A', 'Z'));
    shuffle($chars);
    $start = mt_rand(0, count($chars) - self::$nonce_length);
    return substr(join('', $chars), $start, self::$nonce_length);
}

Tôi nhân đôi 10 lần mảng [0-9, AZ] và xáo trộn các yếu tố, sau khi tôi nhận được điểm bắt đầu ngẫu nhiên để chất nền () trở nên 'sáng tạo' hơn :) bạn có thể thêm [az] và các yếu tố khác vào mảng, sao chép nhiều hơn hoặc ít hơn, sáng tạo hơn tôi


1

Tôi thích sử dụng khóa băm khi giao dịch liên kết xác minh. Tôi khuyên bạn nên sử dụng microtime và băm rằng sử dụng MD5 vì không có lý do nào khiến các phím phải giống nhau vì nó băm dựa trên microtime.

  1. $key = md5(rand());
  2. $key = md5(microtime());

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

}

?>

Hàm trên sẽ tạo cho bạn một chuỗi ngẫu nhiên có độ dài 11 ký tự.


1

Nếu bạn muốn tạo một chuỗi duy nhất trong PHP, hãy thử làm theo.

md5(uniqid().mt_rand());

Trong này

uniqid()- Nó sẽ tạo ra chuỗi duy nhất. Hàm này trả về mã định danh duy nhất dựa trên dấu thời gian dưới dạng chuỗi.

mt_rand() - Tạo số ngẫu nhiên.

md5() - Nó sẽ tạo ra chuỗi băm.


0

Scott, vâng, bạn rất viết và giải pháp tốt! Cảm ơn.

Tôi cũng được yêu cầu tạo mã thông báo API duy nhất cho mỗi người dùng của mình. Theo cách tiếp cận của tôi, tôi đã sử dụng thông tin người dùng (Tên người dùng và tên người dùng):

public function generateUniqueToken($userid, $username){

        $rand = mt_rand(100,999);
    $md5 = md5($userid.'!(&^ 532567_465 ///'.$username);

    $md53 = substr($md5,0,3);
    $md5_remaining = substr($md5,3);

    $md5 = $md53. $rand. $userid. $md5_remaining;

    return $md5;
}

Xin vui lòng xem và cho tôi biết nếu tôi có thể cải thiện. Cảm ơn


0

Đây là những gì tôi đang sử dụng cho một trong các dự án của mình, nó hoạt động rất tốt và nó tạo ra một RANDOM ĐỘC ĐÁO ĐỘC ĐÁO :

$timestampz=time();

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


$tokenparta = generateRandomString();


$token = $timestampz*3 . $tokenparta;

echo $token;

Xin lưu ý rằng tôi đã nhân ba dấu thời gian lên ba để tạo sự nhầm lẫn cho bất kỳ ai sử dụng có thể tự hỏi làm thế nào mã thông báo này được tạo ra;)

Tôi hy vọng nó sẽ giúp :)


1
"Xin vui lòng lưu ý rằng tôi nhân với dấu thời gian bằng ba để tạo ra một sự nhầm lẫn cho bất cứ ai sử dụng có thể tự hỏi như thế nào dấu hiệu này được tạo ra" Âm thanh như bảo mật thông qua obfuscation stackoverflow.com/questions/533965/...
Harry

Đây không phải là "bảo mật thông qua obfuscation" vì dấu thời gian sau đó được thêm vào một chuỗi ngẫu nhiên đã được tạo và đó là chuỗi cuối cùng thực sự mà chúng tôi trả về;)
Kaszoni Ferencz 23/10/18

0

Tôi nghĩ rằng đây là phương pháp tốt nhất để sử dụng.

str_shuffle(md5(rand(0,100000)))

0

chúng ta có thể sử dụng hai dòng mã này để tạo chuỗi duy nhất đã thử nghiệm khoảng 10000000 lần lặp

  $sffledStr= str_shuffle('abscdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*()_-+');
    $uniqueString = md5(time().$sffledStr);

0

Tôi luôn sử dụng chức năng này để tạo một chuỗi ký tự chữ và số ngẫu nhiên tùy chỉnh ... Hy vọng sự giúp đỡ này.

<?php
  function random_alphanumeric($length) {
    $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ12345689';
    $my_string = '';
    for ($i = 0; $i < $length; $i++) {
      $pos = mt_rand(0, strlen($chars) -1);
      $my_string .= substr($chars, $pos, 1);
    }
    return $my_string;
  }
  echo random_alphanumeric(50); // 50 characters
?>

Nó tạo ra ví dụ: Y1FypdjVbFCFK6Gh9FDJpe6dciwJEfV6MQGpJqAfuijaYSZ86g

Nếu bạn muốn so sánh với một chuỗi khác để chắc chắn đó là một chuỗi duy nhất, bạn có thể sử dụng thủ thuật này ...

$string_1 = random_alphanumeric(50);
$string_2 = random_alphanumeric(50);
while ($string_1 == $string_2) {
  $string_1 = random_alphanumeric(50);
  $string_2 = random_alphanumeric(50);
  if ($string_1 != $string_2) {
     break;
  }
}
echo $string_1;
echo "<br>\n";
echo $string_2;

nó tạo ra hai chuỗi duy nhất:

qsBDs4JOoVRfFxyLAOGECYIsWvpcpMzAO9pypwxsqPKeAmYLOi

Ti3kE1WfGgTNxQVXtbNNbhhvvapnaUfGMVJecHkUjHbuCb85pF

Hy vọng đây là những gì bạn đang tìm kiếm...


0

Một giải pháp đơn giản là chuyển đổi cơ sở 64 sang chữ số bằng cách loại bỏ các ký tự không chữ và số.

Cái này sử dụng Random_bytes () cho kết quả bảo mật bằng mật mã.

function random_alphanumeric(int $length): string
{
    $result='';
    do
    {
        //Base 64 produces 4 characters for each 3 bytes, so most times this will give enough bytes in a single pass
        $bytes=random_bytes(($length+3-strlen($result))*2);
        //Discard non-alhpanumeric characters
        $result.=str_replace(['/','+','='],['','',''],base64_encode($bytes));
        //Keep adding characters until the string is long enough
        //Add a few extra because the last 2 or 3 characters of a base 64 string tend to be less diverse
    }while(strlen($result)<$length+3);
    return substr($result,0,$length);
}


-1

Tôi tin rằng vấn đề với tất cả các ý tưởng hiện có là chúng có thể là duy nhất, nhưng không chắc chắn là duy nhất (như được chỉ ra trong câu trả lời của Dariusz Walczak cho loletech). Tôi có một giải pháp thực sự là duy nhất. Nó đòi hỏi kịch bản của bạn có một số loại bộ nhớ. Đối với tôi đây là một cơ sở dữ liệu SQL. Bạn cũng có thể chỉ cần viết vào một tập tin ở đâu đó. Có hai cách thực hiện:

Phương pháp đầu tiên: có các trường HAI chứ không phải 1 cung cấp tính duy nhất. Trường đầu tiên là số ID không ngẫu nhiên nhưng là duy nhất (ID đầu tiên là 1, 2 thứ hai ...). Nếu bạn đang sử dụng SQL, chỉ cần xác định trường ID bằng thuộc tính AUTO_INCREMENT. Trường thứ hai không phải là duy nhất nhưng là ngẫu nhiên. Điều này có thể được tạo ra với bất kỳ kỹ thuật nào khác mà mọi người đã đề cập. Ý tưởng của Scott là tốt, nhưng md5 thuận tiện và có thể đủ tốt cho hầu hết các mục đích:

$random_token = md5($_SERVER['HTTP_USER_AGENT'] . time());

Phương pháp thứ hai: Về cơ bản cùng một ý tưởng, nhưng ban đầu chọn một số chuỗi tối đa sẽ được tạo. Đây có thể chỉ là một con số thực sự lớn như một nghìn tỷ. Sau đó, làm điều tương tự, tạo một ID, nhưng không đệm nó để tất cả các ID có cùng số chữ số. Sau đó, chỉ cần nối ID với chuỗi ngẫu nhiên. Nó sẽ đủ ngẫu nhiên cho hầu hết các mục đích, nhưng phần ID sẽ đảm bảo rằng nó cũng là duy nhất.


-1

Bạn có thể sử dụng mã này, tôi hy vọng nó sẽ hữu ích cho bạn.

function rand_code($len)
{
 $min_lenght= 0;
 $max_lenght = 100;
 $bigL = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 $smallL = "abcdefghijklmnopqrstuvwxyz";
 $number = "0123456789";
 $bigB = str_shuffle($bigL);
 $smallS = str_shuffle($smallL);
 $numberS = str_shuffle($number);
 $subA = substr($bigB,0,5);
 $subB = substr($bigB,6,5);
 $subC = substr($bigB,10,5);
 $subD = substr($smallS,0,5);
 $subE = substr($smallS,6,5);
 $subF = substr($smallS,10,5);
 $subG = substr($numberS,0,5);
 $subH = substr($numberS,6,5);
 $subI = substr($numberS,10,5);
 $RandCode1 = str_shuffle($subA.$subD.$subB.$subF.$subC.$subE);
 $RandCode2 = str_shuffle($RandCode1);
 $RandCode = $RandCode1.$RandCode2;
 if ($len>$min_lenght && $len<$max_lenght)
 {
 $CodeEX = substr($RandCode,0,$len);
 }
 else
 {
 $CodeEX = $RandCode;
 }
 return $CodeEX;
}

Chi tiết về trình tạo mã ngẫu nhiên trong PHP


-2

Đơn giản hóa mã Scotts ở trên bằng cách loại bỏ các vòng lặp không cần thiết đang làm chậm tốc độ và không làm cho nó an toàn hơn so với việc gọi openssl_random_pseudo_bytes chỉ một lần

function crypto_rand_secure($min, $max)
{
 $range = $max - $min;
 if ($range < 1) return $min; // not so random...
 $log = ceil(log($range, 2));
 $bytes = (int) ($log / 8) + 1; // length in bytes
 $rnd = hexdec(bin2hex(openssl_random_pseudo_bytes($bytes)));
 return $min + $rnd%$range;
}

function getToken($length)
{
 return bin2hex(openssl_random_pseudo_bytes($length)
}

Thật không may, tôi không thể đồng ý với bạn rằng đây là một sự đơn giản hóa phù hợp của hàm crypto_rand_secure. Vòng lặp là cần thiết để tránh sai lệch modulo xảy ra khi bạn lấy kết quả của một số được tạo ngẫu nhiên và sau đó sửa đổi nó bằng một số chia phạm vi. vi.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle#Modulo_bias . Bằng cách sử dụng một vòng lặp để loại bỏ bất kỳ số nào ngoài phạm vi và chọn một số mới, nó sẽ tránh được sự thiên vị này. stackoverflow.com/questions/10984974/ trộm
Scott

@Scott, bài đó là về rand (). Tuy nhiên, trong trường hợp này, nó đã được chăm sóc bằng openssl_random_pseudo_bytes để vòng lặp không cần thiết.
mabel

1
gist.github.com/anonymous/87e3ae6fd3320447f46b973e75c2ea85 - Vui lòng chạy tập lệnh này. Bạn sẽ thấy rằng phân phối kết quả không phải là ngẫu nhiên. Các số trong khoảng 0-55 có tỷ lệ xuất hiện cao hơn các số trong khoảng từ 56 đến 100. opensslkhông gây ra điều này, đó là do sai lệch modulo trong câu lệnh return của bạn. 100 (phạm vi) không chia đều 255 (1 byte) và gây ra các kết quả này. Vấn đề lớn nhất của tôi với câu trả lời của bạn là bạn nói rằng chức năng này an toàn như sử dụng một vòng lặp, đó là sai. Việc triển khai crypto_rand_secure của bạn không an toàn về mặt mật mã và gây hiểu lầm.
Scott

@Scott, chúng tôi đang lạc đề ở đây, đây không phải là câu lệnh hoàn trả cuối cùng, nó cũng có thể được tính dần dần từ giá trị trả về của openssl_random_pseudo_bytes mà không cần sử dụng modulo. Điểm tôi đang làm là vòng lặp là không cần thiết một khi openssl_random_pseudo_bytes trả về các byte ngẫu nhiên. Bằng cách tạo vòng lặp, bạn không làm cho nó an toàn hơn, chỉ làm cho nó chậm lại.
mabel

2
Câu trả lời này tuyên truyền thông tin xấu. Bạn đúng là vòng lặp không thực hiệnopenssl an toàn hơn, nhưng quan trọng hơn là nó không làm cho nó kém an toàn hơn, câu trả lời này có. Mã ở trên có một số ngẫu nhiên hoàn toàn tốt và xử lý nó bằng cách thiên vị nó về các số thấp hơn. Nếu bạn từ chối trách nhiệm cho câu trả lời của bạn nói rằng nó nhanh hơn (bằng cách loại bỏ vòng lặp) nhưng đó không phải là CSPRNG, nó sẽ giải quyết vấn đề này. Xin vui lòng, vì tình yêu của tiền điện tử, hãy cho người dùng biết rằng đầu ra của chức năng này có thể bị sai lệch và không phải là một giải pháp tương đương. Vòng lặp không chỉ ở đó để làm phiền bạn.
Scott
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.