PHP: Bagaimana menghasilkan string acak, unik, alfanumerik?

380

Bagaimana mungkin menghasilkan string acak dan unik menggunakan angka dan huruf untuk digunakan dalam tautan verifikasi? Seperti ketika Anda membuat akun di situs web, dan itu mengirimi Anda email dengan tautan, dan Anda harus mengklik tautan itu untuk memverifikasi akun Anda ... ya ... salah satunya.

Bagaimana saya bisa menghasilkan salah satu dari mereka yang menggunakan PHP?

Pembaruan: Baru diingat tentang uniqid(). Ini adalah fungsi PHP yang menghasilkan pengidentifikasi unik berdasarkan waktu saat ini dalam mikrodetik. Saya pikir saya akan menggunakannya.

Andrew
sumber
Yang Anda butuhkan hanyalah string dan nomor acak yang didistribusikan secara seragam.
Artelius
10
Hei Andrew, Anda harus memilih Scottjawaban yang benar. Scott menggunakan generator nomor psudo-acak (CSPRNG) cryptographically secure openSSL yang akan memilih sumber entropi paling aman berdasarkan pada platform Anda.
benteng
3
Siapa pun yang membaca ini setelah 2015, tolong, silakan lihat di sini: paragonie.com/blog/2015/07/... Sebagian besar jawaban teratas cacat kurang lebih ...
rugk
OpenSSL dan uniqidtidak aman. Gunakan sesuatu seperti Random::alphanumericString($length)atau Random::alphanumericHumanString($length).
gak

Jawaban:

305

Pemberitahuan Keamanan : Solusi ini tidak boleh digunakan dalam situasi di mana kualitas keacakan Anda dapat memengaruhi keamanan aplikasi. Khususnya, rand()dan uniqid()tidak aman generator nomor acak kriptografis . Lihat jawaban Scott untuk alternatif yang aman.

Jika Anda tidak perlu menjadi benar-benar unik dari waktu ke waktu:

md5(uniqid(rand(), true))

Jika tidak (mengingat Anda telah menentukan login unik untuk pengguna Anda):

md5(uniqid($your_user_login, true))
loletech
sumber
90
Kedua metode tidak menjamin keunikan - panjang input dari fungsi md5 lebih besar dari panjang outputnya dan sesuai dengan en.wikipedia.org/wiki/Pigeonhole_principle , tabrakan dijamin. Di sisi lain, semakin besar populasi mengandalkan hash untuk mencapai id "unik", semakin besar kemungkinan terjadi setidaknya satu tabrakan (lihat en.wikipedia.org/wiki/Birthday_problem ). Probabilitasnya mungkin kecil untuk sebagian besar solusi tetapi masih ada.
Dariusz Walczak
12
Ini bukan metode yang aman untuk menghasilkan nilai acak. Lihat jawaban Scott.
benteng
4
Untuk konfirmasi email yang akan segera kedaluwarsa, saya pikir kemungkinan kecil bahwa suatu hari seseorang dapat mengkonfirmasi email orang lain adalah risiko yang dapat diabaikan. Tapi Anda selalu bisa memeriksa apakah token sudah ada di DB setelah membuatnya dan hanya memilih yang baru jika itu masalahnya. Namun, waktu yang Anda habiskan untuk menulis cuplikan kode tersebut kemungkinan besar terbuang karena kemungkinan besar tidak akan pernah berjalan.
Andrew
Perhatikan bahwa md5 mengembalikan nilai heksadesimal, artinya set karakter terbatas pada [0-9] dan [af].
Thijs Riezebeek
1
MD5 dapat memiliki tabrakan, Anda baru saja menghancurkan keuntungan uniqid
user151496
507

Saya hanya mencari cara untuk memecahkan masalah yang sama ini, tetapi saya juga ingin fungsi saya membuat token yang dapat digunakan untuk pengambilan kata sandi juga. Ini berarti bahwa saya perlu membatasi kemampuan token untuk ditebak. Karena uniqiddidasarkan pada waktu, dan menurut php.net "nilai kembali sedikit berbeda dari microtime ()", uniqidtidak memenuhi kriteria. PHP merekomendasikan untuk menggunakan openssl_random_pseudo_bytes()sebagai gantinya untuk menghasilkan token yang aman secara kriptografis.

Jawaban cepat, singkat dan to the point adalah:

bin2hex(openssl_random_pseudo_bytes($bytes))

yang akan menghasilkan string acak karakter alfanumerik dengan panjang = $ byte * 2. Sayangnya ini hanya memiliki alfabet [a-f][0-9] , tetapi berfungsi.


Di bawah ini adalah fungsi terkuat yang bisa saya buat yang memenuhi kriteria (Ini adalah versi jawaban Erik yang diterapkan).

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)berfungsi sebagai pengganti pengganti untuk rand()atau mt_rand. Ini menggunakan openssl_random_pseudo_bytes untuk membantu membuat angka acak antara $ min dan $ max.

getToken($length)membuat alfabet untuk digunakan dalam token dan kemudian membuat string panjang $length.

EDIT: Saya lalai mengutip sumber - http://us1.php.net/manual/en/function.openssl-random-pseudo-bytes.php#104322

EDIT (PHP7): Dengan dirilisnya PHP7, perpustakaan standar sekarang memiliki dua fungsi baru yang dapat menggantikan / meningkatkan / menyederhanakan fungsi crypto_rand_secure di atas. random_bytes($length)danrandom_int($min, $max)

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

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

Contoh:

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;
}
Scott
sumber
2
Sepakat. Penyimpanan kata sandi plaintext mengerikan! (Saya menggunakan blowfish.) Tetapi setelah token dibuat, pemegang token dapat mereset kata sandi, sehingga token tersebut setara dengan kata sandi saat valid (dan diperlakukan seperti itu).
Scott
23
Hai, saya menggabungkan kode Anda yang sangat baik dengan fungsionalitas metode Kohana Text :: random () yang mudah digunakan dan membuat intisari ini: gist.github.com/raveren/5555297
raveren
9
Sempurna! Saya mengujinya dengan panjang 10 karakter. 100000 token dan masih belum ada duplikat!
Sharpless512
5
Saya menggunakan proses ini dan merasa sangat lambat. Dengan panjang 36 itu habis pada server dev. Dengan panjang 24 masih butuh sekitar 30 detik. Tidak yakin apa yang saya lakukan salah tetapi terlalu lambat bagi saya dan saya memilih solusi lain.
Shane
5
Anda juga dapat menggunakan base64_encodealih-alih bin2hexuntuk mendapatkan string yang lebih pendek dengan alfabet yang lebih besar.
erjiang
91

Versi berorientasi objek dari solusi yang paling banyak dipilih

Saya telah membuat solusi berorientasi objek berdasarkan jawaban 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);
    }
}

Pemakaian

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

Alfabet khusus

Anda dapat menggunakan alfabet khusus jika diperlukan. Cukup berikan string dengan karakter yang didukung ke konstruktor atau setter:

<?php

$customAlphabet = '0123456789ABCDEF';

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

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

Inilah sampel keluarannya

SRniGU2sRQb2K1ylXKnWwZr4HrtdRgrM
q1sRUjNq1K9rG905aneFzyD5IcqD4dlC
I0euIWffrURLKCCJZ5PQFcNUCto6cQfD
AKwPJMEM5ytgJyJyGqoD5FQwxv82YvMr
duoRF6gAawNOEQRICnOUNYmStWmOpEgS
sdHUkEn4565AJoTtkc8EqJ6cC4MLEHUx
eVywMdYXczuZmHaJ50nIVQjOidEVkVna
baJGt7cdLDbIxMctLsEBWgAw5BByP5V0
iqT0B2obq3oerbeXkDVLjZrrLheW4d8f
OUQYCny6tj2TYDlTuu1KsnUyaLkeObwa

Saya harap ini akan membantu seseorang. Bersulang!

Slava Fomin II
sumber
Maaf, bagaimana saya menjalankan hal ini? Saya lakukan $obj = new RandomStringGenerator;tetapi metode apa yang harus saya panggil? Terima kasih.
sg552
@ sg552, Anda harus memanggil generatemetode seperti pada contoh di atas. Cukup berikan bilangan bulat untuk menentukan panjang string yang dihasilkan.
Slava Fomin II
Terima kasih itu bekerja untuk saya tetapi Custom Alphabettidak. Saya mendapat output kosong ketika saya gema. Pokoknya saya bahkan tidak yakin apa gunanya contoh 2 Custom Alphabetjadi saya pikir saya hanya tinggal dengan contoh pertama. Terima kasih.
sg552
1
Bagus, tetapi cukup berlebihan dalam sebagian besar skenario, kecuali proyek Anda sangat bergantung pada kode yang dibuat secara acak
dspacejs
1
ya bagus tapi berlebihan, terutama mengingat itu sudah cukup usang sekarang untuk php 5.7
Andrew
39

Saya terlambat tetapi saya di sini dengan beberapa data penelitian yang baik berdasarkan fungsi yang disediakan oleh jawaban Scott . Jadi saya membuat tetesan Digital Ocean hanya untuk pengujian otomatis selama 5 hari ini dan menyimpan string unik yang dihasilkan dalam database MySQL.

Selama periode pengujian ini, saya menggunakan 5 panjang yang berbeda (5, 10, 15, 20, 50) dan +/- 0,5 juta catatan dimasukkan untuk setiap panjang. Selama pengujian saya, hanya panjang 5 yang dihasilkan +/- 3K duplikat dari 0,5 juta dan panjang yang tersisa tidak menghasilkan duplikat apa pun. Jadi kita dapat mengatakan bahwa jika kita menggunakan panjang 15 atau lebih dengan fungsi Scott, maka kita dapat menghasilkan string unik yang sangat andal. Berikut adalah tabel yang menunjukkan data penelitian saya:

masukkan deskripsi gambar di sini

Pembaruan: Saya membuat aplikasi Heroku sederhana menggunakan fungsi-fungsi ini yang mengembalikan token sebagai respons JSON. Aplikasi ini dapat diakses di https://uniquestrings.herokuapp.com/api/token?length=15

Saya harap ini membantu.

Rehmat
sumber
33

Anda dapat menggunakan UUID (Pengidentifikasi Unik Semesta), dapat digunakan untuk tujuan apa pun, dari string otentikasi pengguna hingga id transaksi pembayaran.

UUID adalah angka 16-oktet (128-bit). Dalam bentuk kanoniknya, UUID diwakili oleh 32 digit heksadesimal, ditampilkan dalam lima kelompok yang dipisahkan oleh tanda hubung, dalam bentuk 8-4-4-4-12 untuk total 36 karakter (32 karakter alfanumerik dan empat tanda hubung).

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

}

// memanggil funtion

$transationID = generate_uuid();

beberapa contoh output akan seperti:

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

semoga membantu seseorang di masa depan :)

Pengembang
sumber
Terlihat fantastis, ditambahkan ke daftar saya!
Mustafa Erdogan
32

Fungsi ini akan menghasilkan kunci acak menggunakan angka dan huruf:

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

Contoh output:

zsd16xzv3jsytnp87tk7ygv73k8zmr0ekh6ly7mxaeyeh46oe8
Rathienth Baskaran
sumber
6
Setelah beberapa saat Anda mendapatkan nomor yang sama
Sharpless512
1
Ini tidak sepenuhnya acak karena tidak akan pernah memiliki chacater yang sama lebih dari sekali.
EricP
16

Saya menggunakan one-liner ini:

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

di mana panjang adalah panjang dari string yang diinginkan (habis dibagi 4, jika tidak maka akan dibulatkan ke nomor terdekat habis dibagi 4)

DudeOnRock
sumber
6
Itu tidak selalu menghasilkan karakter alfanumerik saja. Ini dapat berisi karakter seperti==
user3459110
1
Jika digunakan dalam URL, base64url_encodedapat digunakan sebagai gantinya, lihat di sini: php.net/manual/en/function.base64-encode.php
Paul
9

Gunakan kode di bawah ini untuk menghasilkan angka acak 11 karakter atau mengubah nomor sesuai kebutuhan Anda.

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

atau kita dapat menggunakan fungsi kustom untuk menghasilkan angka acak

 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);
Ramesh Kotkar
sumber
3
Ini tidak pernah dapat menghasilkan string "aaaaaaaaaaa" atau "aaaaabbbbbb". Itu hanya mengambil substring permutasi acak dari alfabet. String sepanjang 11 karakter hanya memiliki V (11,35) = 288 nilai yang mungkin. Jangan gunakan ini jika Anda mengharapkan string menjadi unik!
kdojeteri
@Peping lalu lakukansubstr(str_shuffle(str_repeat('0123456789abcdefghijklmnopqrstvwxyz', 36)), 0, 11);
Tim Hallman
7
  1. Buat nomor acak menggunakan generator nomor acak favorit Anda
  2. Lipat gandakan dan bagi untuk mendapatkan nomor yang cocok dengan jumlah karakter dalam alfabet kode Anda
  3. Dapatkan item di indeks itu dalam alfabet kode Anda.
  4. Ulangi dari 1) sampai Anda memiliki panjang yang Anda inginkan

mis. (dalam kode semu)

int myInt = random(0, numcharacters)
char[] codealphabet = 'ABCDEF12345'
char random = codealphabet[i]
repeat until long enough
Erik A. Brandstadmoen
sumber
Secara teoritis, tidak bisakah ini menghasilkan string yang sama lebih dari satu kali?
frezq
4

Inilah penghasil id unik utama untuk Anda. dibuat oleh saya.

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

Anda dapat menggemakan 'var' apa saja untuk id Anda sesuka Anda. tetapi $ mdun lebih baik, Anda dapat mengganti md5 ke sha1 untuk kode yang lebih baik tetapi itu akan sangat lama yang mungkin tidak Anda butuhkan.

Terima kasih.

Torsi Krishna
sumber
7
Dalam hal ini keacakan dijamin oleh kode tertulis acak, bukan?
Daniel Kucal
3
ya, ini agak "acak" karena ini bukan kode standar yang tidak jelas. Ini membuatnya sulit untuk diprediksi ... tetapi sebenarnya tidak menggunakan bagian yang tidak aman untuk menghasilkan angka acak. jadi hasilnya secara teknis tidak acak atau aman.
Philipp
4

Untuk string yang benar-benar acak, Anda dapat menggunakannya

<?php

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

output:

40a29479ec808ad4bcff288a48a25d5c

jadi bahkan jika Anda mencoba untuk menghasilkan string beberapa kali pada waktu yang sama, Anda akan mendapatkan hasil yang berbeda.


sumber
4

Saat mencoba membuat kata sandi acak, Anda mencoba untuk:

  • Pertama-tama buat satu set byte acak yang aman secara kriptografis

  • Kedua adalah mengubah byte acak tersebut menjadi string yang dapat dicetak

Sekarang, ada beberapa cara untuk menghasilkan byte acak di php seperti:

$length = 32;

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

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

Maka Anda ingin mengubah byte acak ini menjadi string yang dapat dicetak:

Anda dapat menggunakan bin2hex :

$string = bin2hex($bytes);

atau base64_encode :

$string = base64_encode($bytes);

Namun, perhatikan bahwa Anda tidak mengontrol panjang string jika Anda menggunakan base64. Anda dapat menggunakan bin2hex untuk melakukan itu, menggunakan 32 byte akan berubah menjadi string 64 char . Tapi itu hanya akan berfungsi seperti itu dalam string BAHKAN .

Jadi pada dasarnya Anda bisa melakukannya :

$length = 32;

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

$string = bin2hex($bytes);
Dylan Kas
sumber
3

Inilah yang saya gunakan:

md5(time() . rand());    
// Creates something like 0c947c3b1047334f5bb8a3b7adc1d97b
Faraz Kelhini
sumber
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();
    }

 }
Nidhin
sumber
2

Ini adalah fungsi sederhana yang memungkinkan Anda menghasilkan string acak yang mengandung Letters and Numbers (alfanumerik). Anda juga dapat membatasi panjang string. String acak ini dapat digunakan untuk berbagai keperluan, termasuk: Kode Rujukan, Kode Promosi, Kode Kupon. Fungsi bergantung pada fungsi PHP berikut: 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
*/
Arpit J.
sumber
1

setelah membaca contoh sebelumnya saya datang dengan ini:

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

Saya menduplikasi 10 kali array [0-9, AZ] dan mengacak elemen, setelah saya mendapatkan titik awal acak untuk substr () menjadi lebih 'kreatif' :) Anda dapat menambahkan [az] dan elemen lainnya ke array, duplikat lebih atau kurang, lebih kreatif dari saya

Luiggi ZAMOL
sumber
1

Saya suka menggunakan kunci hash saat menangani tautan verifikasi. Saya akan merekomendasikan menggunakan microtime dan hashing yang menggunakan MD5 karena seharusnya tidak ada alasan mengapa kunci harus sama karena hash didasarkan dari microtime.

  1. $key = md5(rand());
  2. $key = md5(microtime());
theveterancoder
sumber
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;

}

?>

fungsi di atas akan menghasilkan Anda string acak yang panjangnya 11 karakter.

Mudeyar Ceylon Tua
sumber
1

Jika Anda ingin membuat string unik di PHP, coba ikuti.

md5(uniqid().mt_rand());

Di dalam,

uniqid()- Ini akan menghasilkan string unik. Fungsi ini mengembalikan pengidentifikasi unik berbasis cap waktu sebagai string.

mt_rand() - Menghasilkan nomor acak.

md5() - Ini akan menghasilkan string hash.

akshaypjoshi
sumber
0

Scott, ya, Anda sangat menulis dan solusi yang bagus! Terima kasih.

Saya juga harus membuat token API unik untuk setiap pengguna saya. Berikut ini adalah pendekatan saya, saya menggunakan informasi pengguna (Userid dan 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;
}

Silakan lihat dan beri tahu saya jika ada perbaikan yang dapat saya lakukan. Terima kasih

Himanshu Sharma
sumber
0

Inilah yang saya gunakan pada salah satu proyek saya, ini bekerja dengan baik dan menghasilkan TOKEN ACAK UNIK :

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

Harap perhatikan bahwa saya mengalikan cap waktu dengan tiga untuk membuat kebingungan bagi siapa pun pengguna yang mungkin bertanya-tanya bagaimana token ini dihasilkan;)

Saya harap ini membantu :)

Kaszoni Ferencz
sumber
1
"Harap dicatat bahwa saya mengalikan cap waktu dengan tiga untuk membuat kebingungan bagi siapa pun pengguna yang mungkin bertanya-tanya bagaimana token ini dihasilkan" Kedengarannya seperti keamanan melalui kebingungan stackoverflow.com/questions/533965/…
Harry
Ini bukan "keamanan melalui kebingungan" karena stempel waktu kemudian ditambahkan ke string acak yang dihasilkan, dan itulah string terakhir yang sebenarnya kita kembalikan;)
Kaszoni Ferencz
0

Saya pikir ini adalah metode terbaik untuk digunakan.

str_shuffle(md5(rand(0,100000)))
Davinder Kumar
sumber
0

kita dapat menggunakan dua baris kode ini untuk menghasilkan string unik yang telah diuji sekitar 10.000.000 kali iterasi

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

Saya selalu menggunakan fungsi ini untuk menghasilkan string alfanumerik acak khusus ... Semoga bantuan ini.

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

Ini menghasilkan misalnya: Y1FypdjVbFCFK6Gh9FDJpe6dciwJEfV6MQGpJqAfuijaYSZ86g

Jika Anda ingin membandingkan dengan string lain untuk memastikan itu adalah urutan unik, Anda dapat menggunakan trik ini ...

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

itu menghasilkan dua string unik:

qsBDs4JOoVRfFxyLAOGECYIsWvpcpMzAO9pypwxsqPKeAmYLOi

Ti3kE1WfGgTNxQVXtbNNbhhvvapnaUfGMVJecHkUjHbuCb85pF

Semoga ini yang Anda cari ...

Alessandro
sumber
0

Solusi sederhana adalah mengubah basis 64 menjadi alfanumerik dengan membuang karakter non-alfanumerik.

Yang ini menggunakan random_bytes () untuk hasil yang aman secara kriptografis.

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);
}
Jon Hulka
sumber
0

Saya pikir ini solusi yang lebih baik

Str::uuid()->toString()
Oğuz Can Sertel
sumber
-1

Saya percaya masalah dengan semua ide yang ada adalah bahwa mereka mungkin unik, tetapi tidak pasti unik (seperti yang ditunjukkan dalam balasan Dariusz Walczak kepada loletech). Saya punya solusi yang sebenarnya unik. Ini mengharuskan skrip Anda memiliki semacam memori. Bagi saya ini adalah database SQL. Anda juga bisa menulis ke file di suatu tempat. Ada dua implementasi:

Metode pertama: memiliki DUA bidang daripada 1 yang memberikan keunikan. Bidang pertama adalah nomor ID yang tidak acak tetapi unik (ID pertama adalah 1, 2 kedua ...). Jika Anda menggunakan SQL, cukup tentukan bidang ID dengan properti AUTO_INCREMENT. Kolom kedua tidak unik tetapi acak. Ini dapat dihasilkan dengan salah satu teknik lain yang telah disebutkan orang. Ide Scott bagus, tetapi md5 nyaman dan mungkin cukup baik untuk sebagian besar tujuan:

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

Metode kedua: Pada dasarnya ide yang sama, tetapi pada awalnya memilih jumlah maksimum string yang pernah dihasilkan. Ini bisa menjadi jumlah yang sangat besar seperti satu triliun. Kemudian lakukan hal yang sama, buat ID, tapi nol padatkan sehingga semua ID memiliki jumlah digit yang sama. Kemudian gabungkan ID dengan string acak. Ini akan cukup acak untuk sebagian besar tujuan, tetapi bagian ID akan memastikan bahwa itu juga unik.

bytesized
sumber
-1

Anda dapat menggunakan kode ini, semoga bermanfaat bagi Anda.

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

Rincian tentang pembuat kode acak dalam PHP

Sajjad Hossain
sumber
-2

Menyederhanakan kode Scotts di atas dengan menghapus loop yang tidak perlu yang memperlambat dengan buruk dan tidak membuatnya lebih aman daripada memanggil openssl_random_pseudo_bytes sekali saja

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)
}
mabel
sumber
Sayangnya, saya tidak dapat setuju dengan Anda bahwa ini adalah penyederhanaan yang sesuai dari fungsi crypto_rand_secure. Pengulangan diperlukan untuk menghindari bias modulo yang terjadi ketika Anda mengambil hasil dari angka yang dihasilkan secara acak dan kemudian memodifikasinya dengan angka yang membagi rentang. en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle#Modulo_bias . Dengan menggunakan loop untuk membuang nomor apa pun di luar rentang dan memilih nomor baru, itu menghindari bias ini. stackoverflow.com/questions/10984974/...
Scott
@Scott, posting itu tentang rand (). Namun dalam kasus ini, ini sudah ditangani oleh openssl_random_pseudo_bytes sehingga tidak perlu diulang.
mabel
1
gist.github.com/anonymous/87e3ae6fd3320447f46b973e75c2ea85 - Silakan jalankan skrip ini. Anda akan melihat bahwa distribusi hasilnya tidak acak. Angka antara 0-55 memiliki kejadian lebih tinggi daripada angka antara 56-100. openssltidak menyebabkan ini, itu karena bias modulo dalam pernyataan pengembalian Anda. 100 (rentang) tidak membagi 255 (1 byte) secara merata dan menyebabkan hasil ini. Masalah terbesar saya dengan jawaban Anda adalah bahwa Anda menyatakan bahwa fungsinya seaman menggunakan loop, yang salah. Implementasi crypto_rand_secure Anda tidak aman secara kriptografis dan menyesatkan.
Scott
@Scott, kami sedang ngelantur di sini, ini bukan tentang pernyataan pengembalian terakhir, itu juga dapat secara progresif dihitung dari nilai pengembalian openssl_random_pseudo_bytes tanpa menggunakan modulo. Poin yang saya buat adalah bahwa loop tidak perlu setelah openssl_random_pseudo_bytes mengembalikan byte acak. Dengan membuat lingkaran, Anda tidak membuatnya lebih aman, hanya membuatnya lambat.
mabel
2
Jawaban ini menyebarkan informasi yang buruk. Anda benar bahwa loop tidak membuatopenssl lebih aman, tetapi yang lebih penting itu tidak membuatnya kurang aman, jawaban ini tidak. Kode di atas mengambil angka acak yang sangat bagus dan mengubahnya dengan membiaskannya ke angka yang lebih rendah. Jika Anda meletakkan penafian jawaban Anda yang menyatakan bahwa itu lebih cepat (dengan menghapus loop) tetapi itu bukan CSPRNG itu akan menyelesaikan masalah ini. Tolong, untuk cinta crypto, beri tahu pengguna bahwa output dari fungsi ini bisa menjadi bias dan bukan solusi yang setara. Pengulangan itu tidak hanya mengganggu Anda.
Scott