PHP: jak wygenerować losowy, unikalny, alfanumeryczny ciąg znaków do wykorzystania w tajnym linku?

Jak byłoby możliwe wygenerowanie losowego, unikalnego ciągu znaków za pomocą cyfr i liter do wykorzystania w linku weryfikacyjnym? Na przykład, gdy tworzysz konto na stronie internetowej i wysyła Ci wiadomość e-mail z linkiem, i musisz kliknąć ten link, aby zweryfikować swoje konto

Jak mogę wygenerować jeden z tych przy użyciu PHP?

Author: gagarine, 2009-12-04

27 answers

Security Notice: tego rozwiązania nie należy stosować w sytuacjach, w których jakość losowości może mieć wpływ na bezpieczeństwo aplikacji. W szczególności, rand() i uniqid() nie są kryptograficznie bezpiecznymi generatorami liczb losowych. Zobacz odpowiedź Scotta dla bezpiecznej alternatywy.

Jeśli nie potrzebujesz, aby był absolutnie wyjątkowy w czasie:

md5(uniqid(rand(), true))

Inaczej (biorąc pod uwagę, że już ustaliłeś unikalny login dla twój użytkownik):

md5(uniqid($your_user_login, true))
 323
Author: loletech,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-13 15:50:00

Biblioteka standardowa PHP 7 dostarcza funkcję random_bytes($length) generującą kryptograficznie bezpieczne pseudolosowe bajty.

Przykład:

$bytes = random_bytes(20);
var_dump(bin2hex($bytes));

Powyższy przykład wyświetli coś podobnego do:

string(40) "5fe69c95ed70a9869d9f9af7d8400a6673bb9ce9"

Więcej informacji: http://php.net/manual/en/function.random-bytes.php

PHP 5 (przestarzałe)

Właśnie zastanawiałem się, jak rozwiązać ten sam problem, ale chcę również, aby moja funkcja utworzyła token, który może być używany do odzyskiwania hasła też. Oznacza to, że muszę ograniczyć możliwość odgadnięcia tokena. Ponieważ uniqid opiera się na czasie i zgodnie z php.net "wartość zwracana niewiele różni się od microtime()", uniqid nie spełnia kryteriów. PHP zaleca użycie openssl_random_pseudo_bytes() zamiast generowania kryptograficznie bezpiecznych tokenów.

Szybka, krótka i rzeczowa odpowiedź brzmi:

bin2hex(openssl_random_pseudo_bytes($bytes))

Który wygeneruje losowy ciąg znaków alfanumerycznych o długości = $bajty * 2. Niestety to ma tylko alfabet [a-f][0-9], ale działa.


Poniżej jest najsilniejsza funkcja, jaką mogłem zrobić, która spełnia kryteria(jest to zaimplementowana Wersja odpowiedzi Erika).
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) działa jako zamiennik rand() lub mt_rand. Używa openssl_random_pseudo_bytes, aby pomóc stworzyć losową liczbę między $ min i $ max.

getToken($length) tworzy alfabet do użycia w tokenie, a następnie tworzy ciąg o długości $length.

Źródło: http://us1.php.net/manual/en/function.openssl-random-pseudo-bytes.php#104322

 560
Author: Scott,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-08-11 16:44:36

Obiektowa wersja najczęściej głosowanego rozwiązania

Stworzyłem rozwiązanie zorientowane obiektowo w oparciu o odpowiedź Scotta :

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

Użycie

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

Własny alfabet

W razie potrzeby możesz użyć własnego alfabetu. Wystarczy przekazać ciąg znaków ze wsparciem do konstruktora lub settera:

<?php

$customAlphabet = '0123456789ABCDEF';

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

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

Oto próbki wyjściowe

SRniGU2sRQb2K1ylXKnWwZr4HrtdRgrM
q1sRUjNq1K9rG905aneFzyD5IcqD4dlC
I0euIWffrURLKCCJZ5PQFcNUCto6cQfD
AKwPJMEM5ytgJyJyGqoD5FQwxv82YvMr
duoRF6gAawNOEQRICnOUNYmStWmOpEgS
sdHUkEn4565AJoTtkc8EqJ6cC4MLEHUx
eVywMdYXczuZmHaJ50nIVQjOidEVkVna
baJGt7cdLDbIxMctLsEBWgAw5BByP5V0
iqT0B2obq3oerbeXkDVLjZrrLheW4d8f
OUQYCny6tj2TYDlTuu1KsnUyaLkeObwa

Mam nadzieję, że to komuś pomoże. Zdrowie!
 94
Author: Slava Fomin II,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-03 07:32:22

Jestem spóźniony, ale jestem tutaj z dobrymi danymi badawczymi na podstawie funkcji dostarczonych przez ODPOWIEDŹ Scotta. Więc skonfigurowałem cyfrową kroplę Oceanu tylko dla tego 5-dniowego automatycznego testu i zapisałem wygenerowane unikalne ciągi w bazie danych MySQL.

W tym okresie testowym użyłem 5 różnych długości (5, 10, 15, 20, 50) i + / -0,5 miliona rekordów wstawiono dla każdej długości. Podczas mojego testu tylko długość 5 wygenerowanych +/-3K duplikuje się z 0,5 miliona, a pozostałe długość nie generowała żadnych duplikatów. Możemy więc powiedzieć, że jeśli użyjemy długości 15 lub wyższej z funkcjami Scotta, to możemy wygenerować wysoce niezawodne unikalne ciągi. Oto tabela pokazująca moje dane badawcze:

Tutaj wpisz opis obrazka

Aktualizacja: Stworzyłem prostą aplikację Heroku za pomocą tych funkcji, która zwraca token jako odpowiedź JSON. Dostęp do aplikacji można uzyskać pod adresem https://uniquestrings.herokuapp.com/api/token?length=15

Mam nadzieję, że to pomoże.

 51
Author: Rehmat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-20 09:12:55

Możesz użyć UUID(Universal Unique Identifier), może być używany do dowolnego celu, od łańcucha uwierzytelniania użytkownika po identyfikator transakcji płatniczej.

UUID jest 16-oktetową (128-bitową) liczbą. W swojej kanonicznej formie UUID jest reprezentowany przez 32 cyfry szesnastkowe, wyświetlane w pięciu grupach oddzielonych myślnikami, w formie 8-4-4-4-12 dla łącznie 36 znaków (32 znaki alfanumeryczne i cztery myślniki).
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 )
    );

}

/ / wywołanie funtion

$transationID = generate_uuid();

Niektóre przykładowe wyjścia będą like:

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

Mam nadzieję, że to komuś pomoże w przyszłości:)

 37
Author: Developer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-11 13:38:46

Ta funkcja wygeneruje losowy klucz za pomocą cyfr i liter:

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

Przykładowe wyjście:

zsd16xzv3jsytnp87tk7ygv73k8zmr0ekh6ly7mxaeyeh46oe8
 32
Author: Rathienth Baskaran,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-29 23:09:39

Używam tego jednowarstwowego:

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

Gdzie długość jest długością pożądanego ciągu (podzielna przez 4, w przeciwnym razie jest zaokrąglana w dół do najbliższej liczby podzielnej przez 4)

 17
Author: DudeOnRock,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-12 03:07:38

Użyj poniższego kodu, aby wygenerować losową liczbę 11 znaków lub zmienić liczbę zgodnie z wymaganiami.

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

Lub możemy użyć funkcji niestandardowej do wygenerowania liczby losowej

 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);
 11
Author: Ramesh Kotkar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-01-13 19:18:08
  1. Wygeneruj losową liczbę za pomocą Twój ulubiony losowy numer generator
  2. Mnożenie i dzielenie aby uzyskać liczbę pasującą do liczby znaków w alfabecie kodu
  3. Get the item at that index in Twój alfabet kodu.
  4. Powtórz od 1) aż będziesz miał długość want

E. g (w pseudo kodzie)

int myInt = random(0, numcharacters)
char[] codealphabet = 'ABCDEF12345'
char random = codealphabet[i]
repeat until long enough
 7
Author: Erik A. Brandstadmoen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-04 10:52:52

Dla naprawdę losowych ciągów możesz użyć

<?php

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

Wyjścia:

40a29479ec808ad4bcff288a48a25d5c

Więc nawet jeśli spróbujesz wygenerować łańcuch wiele razy w tym samym czasie, otrzymasz inny wynik.

 6
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-11 13:28:56

Jest to prosta funkcja, która pozwala na generowanie losowych ciągów zawierających litery i cyfry (alfanumerycznych). Można również ograniczyć długość łańcucha. Te losowe ciągi mogą być używane do różnych celów, w tym: kod polecający, kod promocyjny, Kod kuponu. Funkcja opiera się na następujących funkcjach PHP: 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
*/
 5
Author: Arpit J.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-23 11:44:54

Podczas próby wygenerowania losowego hasła próbujesz:

  • Najpierw Wygeneruj kryptograficznie bezpieczny zestaw losowych bajtów

  • Drugi to przekształcenie tych losowych bajtów w drukowalny łańcuch

Teraz istnieje wiele sposobów generowania losowych bajtów w php, takich jak:

$length = 32;

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

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

Następnie chcesz zamienić te losowe bajty w drukowalny ciąg znaków:

Możesz użyć bin2hex :

$string = bin2hex($bytes);

Lub base64_encode :

$string = base64_encode($bytes);

Należy jednak pamiętać, że nie kontrolujesz długości ciągu znaków, jeśli używasz base64. Możesz użyć bin2hex, używając 32 bajtów zmieni się w 64 łańcuch znaków. Ale będzie działać tak tylko w parzystym łańcuchu.

Więc w zasadzie można po prostu zrobić :

$length = 32;

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

$string = bin2hex($bytes);
 5
Author: Dylan Kas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-10-29 08:36:13

Oto ostateczny unikalny Generator id dla Ciebie. zrobione przeze mnie.

<?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;
?>

Możesz echo dowolnego 'var' dla swojego identyfikatora, jak chcesz. ale $mdun jest lepszy, można zastąpić md5 do sha1 dla lepszego kodu, ale to będzie bardzo długo, co może nie trzeba.

Dziękuję.
 3
Author: Krishna Torque,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-17 23:08:58

Oto czego używam:

md5(time() . rand());    
// Creates something like 0c947c3b1047334f5bb8a3b7adc1d97b
 3
Author: Faraz Kelhini,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-27 16:29:19
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
Author: Nidhin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-03 19:32:38

Jeśli chcesz wygenerować unikalny ciąg znaków w PHP, spróbuj podążać za nim.

md5(uniqid().mt_rand());

W tym,

uniqid() - wygeneruje unikalny ciąg znaków. Ta funkcja zwraca unikalny identyfikator oparty na znaczniku czasu jako ciąg znaków.

mt_rand() - Wygeneruj losową liczbę.

md5() - wygeneruje łańcuch hash.

 2
Author: akshaypjoshi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-12-06 08:24:17

Po przeczytaniu poprzednich przykładów wpadłem na to:

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

Powielam 10 razy tablicę [0-9, A-Z] i przetasowuję elementy, po tym jak uzyskam losowy punkt startowy dla podstr (), aby był bardziej "kreatywny" :) możesz dodawać [a-Z] i inne elementy do tablicy, powielać mniej lub bardziej, być bardziej kreatywnym niż ja

 1
Author: Luiggi ZAMOL,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-25 16:09:48

Lubię używać kluczy hashowych przy kontaktach z linkami weryfikacyjnymi. Polecam korzystanie z microtime i hashowanie za pomocą MD5, ponieważ nie powinno być powodu, dla którego klucze powinny być takie same, ponieważ hashuje na podstawie microtime.

  1. $key = md5(rand());
  2. $key = md5(microtime());
 1
Author: sgtcoder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-07 05:16:17
<?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;

}

?>

Powyższa funkcja wygeneruje losowy ciąg znaków o długości 11 znaków.

 1
Author: Old Ceylon Mudliar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-20 11:21:54

Zawsze używam tej funkcji do generowania niestandardowego losowego ciągu alfanumerycznego... Mam nadzieję, że to pomoże.

<?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
?>

Generuje na przykład: Y1FypdjVbFCFK6Gh9FDJpe6dciwJEfV6mqgpjqafuijaysz86g

Jeśli chcesz porównać z innym ciągiem, aby mieć pewność, że jest to unikalna Sekwencja, możesz użyć tej sztuczki...

$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;

Generuje dwa unikalne ciągi:

QsBDs4JOoVRfFxyLAOGECYIsWvpcpMzAo9pypwxsqpkeamyloi

Ti3kE1WfGgTNxQVXtbNNbhhvvapnaUfGmvjechkujhbucb85pf

Mam nadzieję, że tego właśnie szukasz...
 1
Author: Alessandro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-03-10 08:53:49

Prostym rozwiązaniem jest konwersja bazy 64 na alfanumeryczną poprzez odrzucenie znaków niealfanumerycznych.

Ten używa funkcji random_bytes () dla kryptograficznie bezpiecznego wyniku.

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

Edit: zrewidowałem to, bo potrzebuję czegoś bardziej elastycznego. Oto rozwiązanie, które działa nieco lepiej niż powyższe i daje możliwość określenia dowolnego podzbioru zestawu znaków ASCII:

<?php
class RandomText
{
    protected
        $allowedChars,
        //Maximum index to use
        $allowedCount,
        //Index values will be taken from a pool of this size
        //It is a power of 2 to keep the distribution of values even
        $distributionSize,
        //This many characters will be generated for each output character
        $ratio;
    /**
     * @param string $allowedChars characters to choose from
     */
    public function __construct(string $allowedChars)
    {
        $this->allowedCount = strlen($allowedChars);
        if($this->allowedCount < 1 || $this->allowedCount > 256) throw new \Exception('At least 1 and no more than 256 allowed character(s) must be specified.');
        $this->allowedChars = $allowedChars;
        //Find the power of 2 equal or greater than the number of allowed characters
        $this->distributionSize = pow(2,ceil(log($this->allowedCount, 2)));
        //Generating random bytes is the expensive part of this algorithm
        //In most cases some will be wasted so it is helpful to produce some extras, but not too many
        //On average, this is how many characters needed to produce 1 character in the allowed set
        //50% of the time, more characters will be needed. My tests have shown this to perform well.
        $this->ratio = $this->distributionSize / $this->allowedCount;
    }

    /**
     * @param int $length string length of required result
     * @return string random text
     */
    public function get(int $length) : string
    {
        if($length < 1) throw new \Exception('$length must be >= 1.');
        $result = '';
        //Keep track of result length to prevent having to compute strlen()
        $l = 0;
        $indices = null;
        $i = null;
        do
        {
            //Bytes will be used to index the character set. Convert to integers.
            $indices = unpack('C*', random_bytes(ceil(($length - $l) * $this->ratio)));
            foreach($indices as $i)
            {
                //Reduce to the smallest range that gives an even distribution
                $i %= $this->distributionSize;
                //If the index is within the range of characters, add one char to the string
                if($i < $this->allowedCount)
                {
                    $l++;
                    $result .= $this->allowedChars[$i];
                }
                if($l >= $length) break;
            }
        }while($l < $length);
        return $result;
    }
}
 1
Author: Jon Hulka,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2021-02-06 19:18:04

Scott, tak, jesteś bardzo pisać i dobre rozwiązanie! Dzięki.

Jestem również zobowiązany do wygenerowania unikalnego tokena API dla każdego mojego użytkownika. Poniżej znajduje się moje podejście, użyłem informacji o użytkowniku (Userid i Username):

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

Proszę spojrzeć i dać mi znać, jeśli jakaś poprawa mogę zrobić. Dzięki

 0
Author: Himanshu Sharma,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-25 15:59:46

Oto, czego używam w jednym z moich projektów, działa świetnie i generuje unikalny losowy TOKEN :

$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;

Proszę zauważyć, że pomnożyłem znacznik czasu przez trzy, aby stworzyć zamieszanie dla każdego, kto może zastanawiać się, jak ten token jest generowany;)

Mam nadzieję, że to pomoże:)

 0
Author: Fery Kaszoni,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-01 09:41:17

Myślę, że to najlepsza metoda.

str_shuffle(md5(rand(0,100000)))
 0
Author: Davinder Kumar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-18 06:14:00

Możemy użyć tych dwóch linii kodu do wygenerowania unikalnego ciągu przetestowaliśmy około 10000000 razy iteracji

  $sffledStr= str_shuffle('abscdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*()_-+');
    $uniqueString = md5(time().$sffledStr);
 0
Author: Rajesh Prasad Yadav,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-03 09:07:23

Uważam, że problem ze wszystkimi istniejącymi pomysłami polega na tym, że są one prawdopodobnie unikalne, ale niezdecydowanie unikalne (jak zaznaczono w odpowiedzi Dariusza Walczaka do loletecha). Mam rozwiązanie, które jest unikalne. Wymaga to, aby twój skrypt miał jakąś pamięć. Dla mnie jest to baza danych SQL. Możesz też po prostu zapisać gdzieś plik. Istnieją dwie implementacje:

Pierwsza metoda: posiada dwa pola zamiast 1, które zapewniają unikalność. Pierwsze pole jest numerem identyfikacyjnym, który nie jest losowy, ale jest unikalny (pierwszy IDENTYFIKATOR to 1, drugi 2...). Jeśli używasz SQL, po prostu zdefiniuj pole ID za pomocą właściwości AUTO_INCREMENT. Drugie pole nie jest unikalne, ale jest losowe. Można to wygenerować za pomocą dowolnej z innych technik, o których już wspomniano. Pomysł Scotta był dobry, ale md5 jest wygodny i prawdopodobnie wystarczająco dobry dla większości celów: {]}

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

Druga metoda: zasadniczo ten sam pomysł, ale początkowo wybierz maksymalną liczbę ciągów, które nigdy nie zostanie wygenerowany. To może być naprawdę duża liczba, jak bilion. Następnie zrób to samo, Wygeneruj identyfikator, ale Zeruj go tak, aby wszystkie identyfikatory były taką samą liczbą cyfr. Następnie po prostu połącz identyfikator z losowym ciągiem znaków. Będzie to wystarczająco losowe dla większości celów, ale sekcja ID zapewni, że jest również unikalna.

 -1
Author: bytesized,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-28 07:13:17

Uproszczenie powyższego kodu przez usunięcie niepotrzebnych pętli, co bardzo spowalnia i nie czyni go bezpieczniejszym niż wywołanie openssl_random_pseudo_bytes tylko raz

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)
}
 -2
Author: Mark,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-01 04:11:36