PHP: Come generare una stringa alfanumerica casuale, unica?


380

Come sarebbe possibile generare una stringa univoca e casuale utilizzando numeri e lettere da utilizzare in un collegamento di verifica? Come quando crei un account su un sito Web, ti invia un'email con un link e devi fare clic su quel link per verificare il tuo account ... sì ... uno di quelli.

Come posso generare uno di quelli che usano PHP?

Aggiornamento: appena ricordato uniqid(). È una funzione PHP che genera un identificatore univoco basato sull'ora corrente in microsecondi. Penso che lo userò.


Tutto ciò che serve sono stringhe e numeri casuali distribuiti uniformemente.
Artelius

10
Ehi Andrew, dovresti scegliere Scottla risposta corretta. Scott sta usando il generatore di numeri psudo-random (CSPRNG) crittograficamente sicuro di OpenSSL che sceglierà la fonte di entropia più sicura in base alla tua piattaforma.
torre

3
Chiunque legga questo dopo il 2015, per favore, guarda qui: paragonie.com/blog/2015/07/… La maggior parte delle risposte migliori sono più o meno imperfette ...
rugk

OpenSSL e non uniqidsono sicuri. Usa qualcosa come Random::alphanumericString($length)o Random::alphanumericHumanString($length).
Caw

Risposte:


305

Avviso di sicurezza : questa soluzione non deve essere utilizzata in situazioni in cui la qualità della casualità può influire sulla sicurezza di un'applicazione. In particolare, rand()e uniqid()non sono generatori di numeri casuali crittograficamente sicuri . Vedi la risposta di Scott per un'alternativa sicura.

Se non ti serve per essere assolutamente unico nel tempo:

md5(uniqid(rand(), true))

Altrimenti (dato che hai già determinato un accesso univoco per il tuo utente):

md5(uniqid($your_user_login, true))

90
Entrambi i metodi non garantiscono l' univocità: la lunghezza dell'input della funzione md5 è maggiore della lunghezza dell'output e secondo il principio en.wikipedia.org/wiki/Pigeonhole_principle la collisione è garantita. D'altra parte, maggiore è la popolazione che si affida agli hash per ottenere un ID "unico", maggiore è la probabilità che si verifichi almeno una collisione (vedi en.wikipedia.org/wiki/Birthday_problem ). La probabilità può essere minima per la maggior parte delle soluzioni, ma esiste ancora.
Dariusz Walczak,

12
Questo non è un metodo sicuro per generare valori casuali. Vedi la risposta di Scott.
torre

4
Per le conferme via e-mail che scadono relativamente presto, penso che la minima possibilità che una persona possa confermare un giorno l'e-mail di qualcun altro è un rischio trascurabile. Ma puoi sempre verificare se il token esiste già nel DB dopo averlo creato e sceglierne uno nuovo in tal caso. Tuttavia, il tempo impiegato a scrivere quel frammento di codice è probabilmente sprecato in quanto molto probabilmente non verrà mai eseguito.
Andrew,

Nota che md5 restituisce valori esadecimali, il che significa che il set di caratteri è limitato a [0-9] e [af].
Thijs Riezebeek,

1
md5 può avere collisioni, hai appena rovinato il vantaggio
uniqid

507

Stavo solo esaminando come risolvere questo stesso problema, ma voglio anche che la mia funzione crei un token che può essere utilizzato anche per il recupero della password. Ciò significa che devo limitare la capacità del token di essere indovinato. Perché uniqidsi basa sul tempo e secondo php.net "il valore di ritorno è leggermente diverso da microtime ()", uniqidnon soddisfa i criteri. PHP consiglia di utilizzare openssl_random_pseudo_bytes()invece per generare token crittograficamente sicuri.

Una risposta rapida, breve e precisa è:

bin2hex(openssl_random_pseudo_bytes($bytes))

che genererà una stringa casuale di caratteri alfanumerici di lunghezza = $ byte * 2. Sfortunatamente questo ha solo un alfabeto di [a-f][0-9], ma funziona.


Di seguito è la funzione più forte che potrei svolgere che soddisfa i criteri (Questa è una versione implementata della risposta di 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)funziona come un calo in sostituzione di rand()o mt_rand. Usa openssl_random_pseudo_bytes per aiutare a creare un numero casuale tra $ min e $ max.

getToken($length)crea un alfabeto da utilizzare all'interno del token e quindi crea una stringa di lunghezza $length.

EDIT: ho trascurato di citare la fonte - http://us1.php.net/manual/en/function.openssl-random-pseudo-bytes.php#104322

EDIT (PHP7): Con il rilascio di PHP7, la libreria standard ora ha due nuove funzioni che possono sostituire / migliorare / semplificare la funzione crypto_rand_secure sopra. random_bytes($length)erandom_int($min, $max)

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

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

Esempio:

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
Concordato. L'archiviazione della password in chiaro è terribile! (Uso il pesce palla.) Ma dopo che il token è stato generato, consente al titolare del token di reimpostare la password, quindi il token è equivalente alla password mentre è valido (e viene trattato come tale).
Scott,

23
Ehi, ho combinato il tuo eccellente codice con la comoda funzionalità del metodo Kohana Text :: random () e ho
raveren

9
Perfetto! L'ho provato con 10 caratteri come lunghezza. 100000 token e ancora nessun duplicato!
Sharpless512,

5
Ho usato questo processo e l'ho trovato molto lento. Con una lunghezza di 36 è scaduto sul server di sviluppo. Con una lunghezza di 24 sono ancora voluti circa 30 secondi. Non sono sicuro di cosa ho fatto di sbagliato, ma è stato troppo lento per me e ho optato per un'altra soluzione.
Shane,

5
Puoi anche usare base64_encodeinvece di bin2hexottenere una stringa più corta con un alfabeto più grande.
Erjiang,

91

Versione orientata agli oggetti della soluzione più votata

Ho creato una soluzione orientata agli oggetti basata sulla risposta di 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);
    }
}

uso

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

Alfabeto personalizzato

È possibile utilizzare l'alfabeto personalizzato, se necessario. Basta passare una stringa con caratteri supportati al costruttore o al setter:

<?php

$customAlphabet = '0123456789ABCDEF';

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

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

Ecco i campioni di output

SRniGU2sRQb2K1ylXKnWwZr4HrtdRgrM
q1sRUjNq1K9rG905aneFzyD5IcqD4dlC
I0euIWffrURLKCCJZ5PQFcNUCto6cQfD
AKwPJMEM5ytgJyJyGqoD5FQwxv82YvMr
duoRF6gAawNOEQRICnOUNYmStWmOpEgS
sdHUkEn4565AJoTtkc8EqJ6cC4MLEHUx
eVywMdYXczuZmHaJ50nIVQjOidEVkVna
baJGt7cdLDbIxMctLsEBWgAw5BByP5V0
iqT0B2obq3oerbeXkDVLjZrrLheW4d8f
OUQYCny6tj2TYDlTuu1KsnUyaLkeObwa

Spero che possa aiutare qualcuno. Saluti!


Mi dispiace ma come posso eseguire questa cosa? Ho fatto $obj = new RandomStringGenerator;ma quale metodo dovrei chiamare? Grazie.
sg552,

@ sg552, dovresti chiamare il generatemetodo come nell'esempio sopra. Basta passarci un numero intero per specificare la lunghezza della stringa risultante.
Slava Fomin II,

Grazie funziona per me ma Custom Alphabetnon l'ha fatto. Ho un output vuoto quando faccio eco. Ad ogni modo, non sono nemmeno sicuro di quale sia l'uso del secondo esempio, Custom Alphabetquindi penso di rimanere con il primo esempio. Grazie.
sg552,

1
Bello, ma piuttosto eccessivo nella maggior parte degli scenari, a meno che il tuo progetto non si
basi

1
si bello ma eccessivo, soprattutto considerando che ora è praticamente deprecato per php 5.7
Andrew

39

Sono in ritardo ma sono qui con alcuni buoni dati di ricerca basati sulle funzioni fornite dalla risposta di Scott . Quindi ho creato un droplet Digital Ocean solo per questo test automatizzato della durata di 5 giorni e ho archiviato le stringhe uniche generate in un database MySQL.

Durante questo periodo di prova, ho usato 5 diverse lunghezze (5, 10, 15, 20, 50) e sono stati inseriti +/- 0,5 milioni di record per ogni lunghezza. Durante il mio test, solo la lunghezza 5 ha generato duplicati +/- 3K su 0,5 milioni e le lunghezze rimanenti non hanno generato duplicati. Quindi possiamo dire che se usiamo una lunghezza di 15 o superiore con le funzioni di Scott, possiamo generare stringhe uniche altamente affidabili. Ecco la tabella che mostra i miei dati di ricerca:

inserisci qui la descrizione dell'immagine

Aggiornamento: ho creato una semplice app Heroku usando queste funzioni che restituiscono il token come risposta JSON. È possibile accedere all'app a https://uniquestrings.herokuapp.com/api/token?length=15

Spero che questo possa essere d'aiuto.


33

È possibile utilizzare UUID (Universally Unique Identifier), può essere utilizzato per qualsiasi scopo, dalla stringa di autenticazione dell'utente all'ID della transazione di pagamento.

Un UUID è un numero di 16 ottetti (128 bit). Nella sua forma canonica, un UUID è rappresentato da 32 cifre esadecimali, visualizzate in cinque gruppi separati da trattini, nella forma 8-4-4-4-12 per un totale di 36 caratteri (32 caratteri alfanumerici e quattro trattini).

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

}

// chiamando la funzione

$transationID = generate_uuid();

alcuni output di esempio saranno come:

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

spero che aiuti qualcuno in futuro :)


Sembra fantastico, aggiunto alla mia lista!
Mustafa Erdogan,

32

Questa funzione genererà una chiave casuale usando numeri e lettere:

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

Esempio di output:

zsd16xzv3jsytnp87tk7ygv73k8zmr0ekh6ly7mxaeyeh46oe8

6
Dopo un po 'si arriva agli stessi numeri
Sharpless512,

1
Questo non è del tutto casuale perché non avrà mai lo stesso chacater più di una volta.
EricP

16

Uso questo one-liner:

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

dove lunghezza è la lunghezza della stringa desiderata (divisibile per 4, altrimenti viene arrotondata per difetto al numero più vicino divisibile per 4)


6
Non restituisce sempre solo caratteri alfanumerici. Può contenere caratteri come==
user3459110,

1
Se utilizzato in un URL, base64url_encodepuò essere utilizzato invece, vedere qui: php.net/manual/en/function.base64-encode.php
Paul

9

Utilizzare il codice seguente per generare il numero casuale di 11 caratteri o modificare il numero in base alle proprie esigenze.

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

oppure possiamo usare la funzione personalizzata per generare il numero casuale

 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
Questo non può mai generare la stringa "aaaaaaaaaaa" o "aaaaabbbbbb". Seleziona solo una sottostringa di una permutazione casuale dell'alfabeto. La stringa lunga di 11 caratteri ha solo V (11,35) = 288 valori possibili. Non usarlo se ti aspetti che le stringhe siano uniche!
kdojeteri,

@Peping quindisubstr(str_shuffle(str_repeat('0123456789abcdefghijklmnopqrstvwxyz', 36)), 0, 11);
Tim Hallman,

7
  1. Genera un numero casuale usando il tuo generatore di numeri casuali preferito
  2. Moltiplica e dividi per ottenere un numero corrispondente al numero di caratteri dell'alfabeto in codice
  3. Ottieni l'elemento in quell'indice nell'alfabeto del codice.
  4. Ripeti da 1) fino a ottenere la lunghezza desiderata

ad es. (in pseudo codice)

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

Teoricamente parlando, questo non potrebbe potenzialmente generare la stessa stringa più di una volta?
frezq,

4

Ecco il generatore di ID unico per te. fatto da me.

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

puoi fare eco a qualsiasi 'var' per il tuo ID come preferisci. ma $ mdun è migliore, puoi sostituire md5 in sha1 per un codice migliore, ma sarà molto lungo e potrebbe non essere necessario.

Grazie.


7
In questo caso la casualità è garantita da un codice scritto casuale, giusto?
Daniel Kucal,

3
sì, questo è un po '"casuale" perché è un codice oscuro non standard. Ciò rende difficile prevedere ... ma in realtà non utilizza parti non sicure per generare un numero casuale. quindi il risultato non è tecnicamente casuale o sicuro.
Philipp,

4

Per stringhe davvero casuali, puoi usare

<?php

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

uscite:

40a29479ec808ad4bcff288a48a25d5c

quindi anche se provi a generare una stringa più volte nello stesso momento, otterrai un output diverso.


4

Quando si tenta di generare una password casuale, si sta tentando di:

  • Innanzitutto genera un set crittograficamente sicuro di byte casuali

  • Il secondo è trasformare quei byte casuali in una stringa stampabile

Ora, ci sono diversi modi per generare byte casuali in php come:

$length = 32;

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

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

Quindi vuoi trasformare questi byte casuali in una stringa stampabile:

Puoi usare bin2hex :

$string = bin2hex($bytes);

o base64_encode :

$string = base64_encode($bytes);

Tuttavia, si noti che non si controlla la lunghezza della stringa se si utilizza base64. Puoi usare bin2hex per farlo, usando 32 byte si trasformerà in una stringa di 64 caratteri . Ma funzionerà così solo in una stringa EVEN .

Quindi in pratica puoi semplicemente fare :

$length = 32;

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

$string = bin2hex($bytes);

3

Ecco cosa uso:

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

Questa è una semplice funzione che ti consente di generare stringhe casuali contenenti lettere e numeri (alfanumerici). Puoi anche limitare la lunghezza della stringa. Queste stringhe casuali possono essere utilizzate per vari scopi, tra cui: Codice di riferimento, Codice promozionale, Codice coupon. La funzione si basa sulle seguenti funzioni 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
*/

1

dopo aver letto gli esempi precedenti, ho pensato a questo:

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

Duplico 10 volte l'array [0-9, AZ] e mischio gli elementi, dopo che ho ottenuto un punto di partenza casuale per substr () per essere più "creativo" :) puoi aggiungere [az] e altri elementi all'array, duplicare più o meno, sii più creativo di me


1

Mi piace usare le chiavi hash quando si gestiscono i collegamenti di verifica. Consiglierei di usare il microtime e l'hashing usando MD5 poiché non ci dovrebbero essere ragioni per cui i tasti dovrebbero essere gli stessi poiché ha hash basato sul 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;

}

?>

la funzione sopra genererà una stringa casuale della lunghezza di 11 caratteri.


1

Se vuoi generare una stringa univoca in PHP, prova a seguire.

md5(uniqid().mt_rand());

In questo,

uniqid()- Genererà una stringa univoca. Questa funzione restituisce un identificatore univoco basato su data / ora come stringa.

mt_rand() - Genera numero casuale.

md5() - Genererà la stringa hash.


0

Scott, sì, sei molto bravo a scrivere e un'ottima soluzione! Grazie.

Sono inoltre tenuto a generare un token API univoco per ciascun utente. Di seguito è il mio approccio, ho usato le informazioni dell'utente (Userid e 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;
}

Per favore, dai un'occhiata e fammi sapere se posso fare qualche miglioramento. Grazie


0

Ecco quello che sto usando su uno dei miei progetti, sta funzionando alla grande e genera un TOKEN UNICO CASUALE :

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

Si noti che ho moltiplicato il timestamp per tre per creare confusione per chiunque si stia chiedendo come viene generato questo token;)

Spero possa essere d'aiuto :)


1
"Si noti che ho moltiplicato il timestamp per tre per creare confusione per chiunque si stia chiedendo come viene generato questo token" Sembra una sicurezza attraverso l'offuscamento stackoverflow.com/questions/533965/…
Harry

Questa non è una "sicurezza attraverso l'offuscamento" poiché il timestamp viene quindi aggiunto a una stringa casuale che è stata generata, e questa è la stringa finale effettiva che restituiamo;)
Kaszoni Ferencz,

0

Penso che questo sia il metodo migliore da usare.

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

0

possiamo usare queste due righe di codice per generare stringhe univoche che abbiamo testato circa 10000000 volte di iterazione

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

0

Uso sempre questa mia funzione per generare una stringa alfanumerica casuale personalizzata ... Spero che questo aiuto.

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

Genera ad esempio: Y1FypdjVbFCFK6Gh9FDJpe6dciwJEfV6MQGpJqAfuijaYSZ86g

Se vuoi confrontare con un'altra stringa per essere sicuro che si tratti di una sequenza unica puoi usare questo trucco ...

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

genera due stringhe uniche:

qsBDs4JOoVRfFxyLAOGECYIsWvpcpMzAO9pypwxsqPKeAmYLOi

Ti3kE1WfGgTNxQVXtbNNbhhvvapnaUfGMVJecHkUjHbuCb85pF

Spero che questo sia ciò che stai cercando...


0

Una soluzione semplice è convertire la base 64 in alfanumerica eliminando i caratteri non alfanumerici.

Questo usa random_bytes () per un risultato crittograficamente sicuro.

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

Credo che il problema con tutte le idee esistenti sia che sono probabilmente uniche, ma non assolutamente uniche (come sottolineato nella risposta di Dariusz Walczak a Loletech). Ho una soluzione che è davvero unica. Richiede che la tua sceneggiatura abbia una sorta di memoria. Per me questo è un database SQL. Potresti anche semplicemente scrivere su un file da qualche parte. Esistono due implementazioni:

Primo metodo: avere DUE campi anziché 1 che forniscono unicità. Il primo campo è un numero ID che non è casuale ma è univoco (Il primo ID è 1, il secondo 2 ...). Se si utilizza SQL, è sufficiente definire il campo ID con la proprietà AUTO_INCREMENT. Il secondo campo non è unico ma è casuale. Questo può essere generato con una qualsiasi delle altre tecniche che le persone hanno già menzionato. L'idea di Scott era buona, ma md5 è conveniente e probabilmente abbastanza buono per la maggior parte degli scopi:

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

Secondo metodo: sostanzialmente la stessa idea, ma inizialmente scegli un numero massimo di stringhe che verranno mai generate. Questo potrebbe essere solo un numero davvero grande come un trilione. Quindi fai la stessa cosa, genera un ID, ma zero lo pad in modo che tutti gli ID abbiano lo stesso numero di cifre. Quindi concatena l'ID con la stringa casuale. Sarà abbastanza casuale per la maggior parte degli scopi, ma la sezione ID assicurerà che sia anche unica.


-1

Puoi usare questo codice, spero che ti sia utile.

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

Dettagli sul generatore di codice casuale in PHP


-2

Semplificare il codice di Scotts sopra rimuovendo i loop non necessari che rallentano gravemente e non lo rendono più sicuro della chiamata openssl_random_pseudo_bytes una sola volta

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

Sfortunatamente, non posso essere d'accordo con te sul fatto che questa sia un'opportuna semplificazione della funzione crypto_rand_secure. Il ciclo è necessario per evitare la distorsione del modulo che si verifica quando si prende il risultato di un numero generato casualmente e quindi lo si modifica con un numero che divide l'intervallo. en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle#Modulo_bias . Utilizzando un loop per eliminare qualsiasi numero al di fuori dell'intervallo e selezionando un nuovo numero, si evita questo pregiudizio. stackoverflow.com/questions/10984974/…
Scott

@Scott, quel post parla di rand (). Tuttavia, in questo caso, è già curato da openssl_random_pseudo_bytes, quindi esegui il loop in modo non necessario.
mabel,

1
gist.github.com/anonymous/87e3ae6fd3320447f46b973e75c2ea85 - Esegui questo script. Vedrai che la distribuzione dei risultati non è casuale. I numeri tra 0-55 hanno una ricorrenza superiore rispetto ai numeri tra 56-100. opensslnon sta causando questo, è a causa della distorsione del modulo nell'istruzione return. 100 (intervallo) non divide uniformemente 255 (1 byte) e causa questi risultati. Il mio problema più grande con la tua risposta è che dichiari che la funzione è sicura come usare un loop, il che è falso. L'implementazione di crypto_rand_secure non è crittograficamente sicura ed è fuorviante.
Scott,

@Scott, stiamo divagando qui, non si tratta dell'ultima dichiarazione di ritorno, può anche essere progressivamente calcolata dal valore di ritorno di openssl_random_pseudo_bytes senza usare il modulo. Il punto che sto sottolineando è che il loop non è necessario una volta che openssl_random_pseudo_bytes restituisce i byte casuali. Creando un ciclo, non lo rendi più sicuro, ma solo rallentandolo.
mabel,

2
Questa risposta diffonde cattive informazioni. Hai ragione sul fatto che il ciclo non lo rende opensslpiù sicuro, ma soprattutto non lo rende meno sicuro, questa risposta lo fa. Il codice sopra prende un numero casuale perfettamente buono e lo manipola orientandolo verso numeri più bassi. Se metti un disclaimer sulla tua risposta affermando che è più veloce (rimuovendo il ciclo) ma non è un CSPRNG, risolverebbe questo problema. Per amore di crypto, fai sapere agli utenti che l'output di questa funzione potrebbe essere distorto e non è una soluzione equivalente. Il loop non è solo lì per infastidirti.
Scott,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.