PHP: Rasgele, benzersiz, alfasayısal bir dize nasıl oluşturulur?


380

Doğrulama bağlantısında kullanılacak sayıları ve harfleri kullanarak rastgele, benzersiz bir dize oluşturmak nasıl mümkün olabilir? Bir web sitesinde bir hesap oluşturduğunuzda ve size bir bağlantı içeren bir e-posta gönderdiğinizde ve hesabınızı doğrulamak için bu bağlantıyı tıklamanız gerekir ... evet ... bunlardan biri.

PHP kullananlardan birini nasıl oluşturabilirim?

Güncelleme: Sadece hatırladım uniqid(). Mikrosaniye cinsinden şimdiki zamana dayalı benzersiz bir tanımlayıcı üreten bir PHP fonksiyonudur. Bunu kullanacağımı düşünüyorum.


İhtiyacınız olan tek şey dizeler ve düzgün dağıtılmış rastgele sayılardır.
Artelius

10
Hey Andrew, Scottdoğru cevap olarak seçmelisin . Scott, platformunuza göre en güvenli entropi kaynağını seçecek olan OpenSSL'nin şifreli olarak güvenli psudo-random sayı üretecini (CSPRNG) kullanıyor.
kale

3
2015'ten sonra bunu okuyan herkes, lütfen buraya bakın: paragonie.com/blog/2015/07/… En iyi cevaplar az ya da çok kusurludur ...
kilim

OpenSSL ve uniqidgüvensizdir. Random::alphanumericString($length)Veya gibi bir şey kullanın Random::alphanumericHumanString($length).
1919'da caw

Yanıtlar:


305

Güvenlik Uyarısı : Bu çözüm, rasgeleliğinizin kalitesinin bir uygulamanın güvenliğini etkileyebileceği durumlarda kullanılmamalıdır. Özellikle rand()ve uniqid()kriptografik olarak güvenli rastgele sayı üreteçleri değildir . Güvenli bir alternatif için Scott'ın cevabına bakınız .

Zaman içinde kesinlikle benzersiz olması gerekmiyorsa:

md5(uniqid(rand(), true))

Aksi takdirde (zaten kullanıcı için benzersiz bir giriş belirlediyseniz):

md5(uniqid($your_user_login, true))

90
Her iki yöntem de tekliği garanti etmez - md5 fonksiyonunun giriş uzunluğu, çıkışının uzunluğundan daha büyüktür ve en.wikipedia.org/wiki/Pigeonhole_principle'a göre çarpışma garanti edilir. Öte yandan, "benzersiz" kimliğe ulaşmak için hashlere güvenen nüfus arttıkça, en az bir çarpışma olma olasılığı da artar (bkz. En.wikipedia.org/wiki/Birthday_problem ). Çoğu çözüm için olasılık küçük olabilir, ancak hala mevcuttur.
Dariusz Walczak

12
Bu rastgele değerler üretmek için güvenli bir yöntem değildir. Scott'ın cevabına bakın.
kale

4
Süresi dolan e-posta onayları için, bir kişinin bir gün başka birinin e-postasını onaylayabilme olasılığının önemsiz olduğunu düşünüyorum. Ancak, jetonu oluşturduktan sonra DB'de zaten var olup olmadığını her zaman kontrol edebilir ve bu durumda yeni bir tane seçebilirsiniz. Ancak, kod snippet'ini yazmak için harcadığınız zaman büyük olasılıkla asla çalıştırılmayacağı için boşa harcanır.
Andrew

Md5'in onaltılık değerler döndürdüğünü, yani karakter kümesinin [0-9] ve [af] ile sınırlı olduğunu unutmayın.
Thijs Riezebeek

1
md5 çarpışma olabilir, sadece
uniqid

507

Sadece aynı sorunun nasıl çözüleceğini araştırıyordum, ama aynı zamanda fonksiyonumun parola almak için de kullanılabilecek bir jeton oluşturmasını istiyorum. Bu, jetonun tahmin edilme yeteneğini sınırlandırmam gerektiği anlamına geliyor. Çünkü uniqidzamana dayalıdır ve php.net'e göre "dönüş değeri mikrotime ()" den biraz farklıdır uniqid, kriterleri karşılamamaktadır. PHP openssl_random_pseudo_bytes()bunun yerine kriptografik olarak güvenli belirteçler oluşturmak için kullanılmasını önerir .

Hızlı, kısa ve önemli bir cevap:

bin2hex(openssl_random_pseudo_bytes($bytes))

uzunluk = $ bayt * 2 rastgele bir alfasayısal karakter dizesi oluşturur. Ne yazık ki bu sadece bir alfabesi vardır [a-f][0-9], ama çalışır.


Aşağıda, kriterleri karşılayan en güçlü fonksiyon var (Bu, Erik'in cevabının uygulamalı bir versiyonudur).

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)rand()veya yerine bir damla olarak çalışır mt_rand. $ Min ve $ max arasında rastgele bir sayı oluşturmaya yardımcı olmak için openssl_random_pseudo_bytes kullanır.

getToken($length)belirteç içinde kullanılacak bir alfabe oluşturur ve ardından bir uzunluk dizesi oluşturur $length.

EDIT: Alıntı yapmayı ihmal ettim - http://us1.php.net/manual/en/function.openssl-random-pseudo-bytes.php#104322

EDIT (PHP7): PHP7'nin piyasaya sürülmesiyle, standart kütüphane artık yukarıdaki crypto_rand_secure işlevini değiştirebilen / geliştirebilen / basitleştirebilen iki yeni işleve sahiptir. random_bytes($length)verandom_int($min, $max)

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

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

Misal:

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
Kabul. Düz metin şifre depolama korkunç! (Ben blowfish kullanıyorum.) Ancak jeton üretildikten sonra jetonun sahibinin parolayı sıfırlamasına izin verir, böylece jeton geçerli olduğu sürece parola eşdeğeridir (ve bu şekilde işlem görür).
Scott

23
Hey, mükemmel kodunuzu uygun Kohana Text :: random () yöntemi işlevselliği ile birleştirdim ve bu özeti oluşturdum: gist.github.com/raveren/5555297
raveren

9
Mükemmel! Uzunluğunu 10 karakter ile test ettim. 100000 jetonları ve yine de kopya yok!
Sharpless512

5
Bu işlemi kullandım ve süper yavaş buldum. 36 uzunluğunda dev sunucusunda zaman aşımına uğradı. 24 uzunluğuyla hala 30 saniye sürdü. Ne yaptığımdan emin değilim ama benim için çok yavaştı ve başka bir çözüm seçtim.
Shane

5
Ayrıca kullanabilirsiniz base64_encodeyerine bin2hexdaha büyük alfabesi ile daha kısa bir dize alır.
erjiang

91

En çok oylanan çözümün nesneye yönelik sürümü

Scott'ın cevabına dayanarak nesne yönelimli bir çözüm yarattım :

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

kullanım

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

Özel alfabe

Gerekirse özel alfabe kullanabilirsiniz. Yapıcıya veya ayarlayıcıya desteklenen karakterleri içeren bir dize iletmeniz yeterlidir:

<?php

$customAlphabet = '0123456789ABCDEF';

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

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

İşte çıktı örnekleri

SRniGU2sRQb2K1ylXKnWwZr4HrtdRgrM
q1sRUjNq1K9rG905aneFzyD5IcqD4dlC
I0euIWffrURLKCCJZ5PQFcNUCto6cQfD
AKwPJMEM5ytgJyJyGqoD5FQwxv82YvMr
duoRF6gAawNOEQRICnOUNYmStWmOpEgS
sdHUkEn4565AJoTtkc8EqJ6cC4MLEHUx
eVywMdYXczuZmHaJ50nIVQjOidEVkVna
baJGt7cdLDbIxMctLsEBWgAw5BByP5V0
iqT0B2obq3oerbeXkDVLjZrrLheW4d8f
OUQYCny6tj2TYDlTuu1KsnUyaLkeObwa

Umarım birine yardım eder. Şerefe!


Üzgünüm ama bu şeyi nasıl yaparım? Yaptım $obj = new RandomStringGenerator;ama hangi yöntemi aramalıyım? Teşekkür ederim.
sg552

@ sg552, generateyukarıdaki örnekte olduğu gibi yöntemi çağırmalısınız . Elde edilen dizenin uzunluğunu belirtmek için bir tamsayı iletmeniz yeterlidir.
Slava Fomin II

Teşekkürler benim için çalışıyor ama Custom Alphabetolmadı. Yankadığımda boş çıktı aldım. Her neyse, 2. örneğin ne kullanıldığından bile emin değilim, Custom Alphabetbu yüzden sadece ilk örnekte kaldığımı düşünüyorum. Teşekkürler.
sg552

1
Projeniz rasgele oluşturulmuş kodlara
dayanmadığı

1
evet güzel ama overkill, özellikle dikkate php 5.7 için hemen hemen artık göz ardı
Andrew

39

Geç kaldım ama burada Scott'ın cevabının sağladığı fonksiyonlara dayanan bazı iyi araştırma verileri var . Bu yüzden sadece bu 5 günlük otomatik test için bir Digital Ocean damlacık kurdum ve üretilen benzersiz dizeleri bir MySQL veritabanında sakladım.

Bu test döneminde 5 farklı uzunluk kullandım (5, 10, 15, 20, 50) ve her bir uzunluk için +/- 0.5 milyon kayıt eklendi. Testim sırasında, yalnızca uzunluk 5, 0,5 milyondan +/- 3K kopya üretti ve kalan uzunluklar kopya oluşturmadı. Scott'ın işlevleriyle 15 veya daha uzun bir uzunluk kullanırsak, son derece güvenilir benzersiz dizeler üretebileceğimizi söyleyebiliriz. Araştırma verilerimi gösteren tablo:

resim açıklamasını buraya girin

Güncelleme: Jetonu JSON yanıtı olarak döndüren bu işlevleri kullanarak basit bir Heroku uygulaması oluşturdum. Uygulamaya https://uniquestrings.herokuapp.com/api/token?length=15 adresinden erişilebilir.

Umarım bu yardımcı olur.


33

UUID'yi (Evrensel Benzersiz Tanımlayıcı) kullanabilirsiniz, kullanıcı kimlik doğrulama dizesinden ödeme işlem kimliğine kadar herhangi bir amaç için kullanılabilir.

UUID, 16 oktet (128 bit) sayıdır. Kanonik biçiminde, bir UUID, toplam 36 karakter (32 alfasayısal karakter ve dört tire) için 8-4-4-4-12 şeklinde, tire ile ayrılmış beş grupta görüntülenen 32 onaltılık basamakla temsil edilir.

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

}

// çağrı fonksiyonu

$transationID = generate_uuid();

bazı örnek çıktılar şöyle olacaktır:

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

Umarım gelecekte birine yardımcı olur :)


Harika görünüyor, listeme eklendi!
Mustafa Erdoğan

32

Bu işlev rakamlar ve harfler kullanarak rastgele bir anahtar oluşturur:

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

Örnek çıktı:

zsd16xzv3jsytnp87tk7ygv73k8zmr0ekh6ly7mxaeyeh46oe8

6
Bir süre sonra aynı sayılara
ulaşırsınız

1
Bu tamamen rastgele değil, çünkü asla aynı chacater'a bir kereden fazla sahip olmayacak.
EricP

16

Bu tek astarı kullanıyorum:

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

burada uzunluk istenen dizginin uzunluğudur (4'e bölünebilir, aksi takdirde 4'e bölünebilir en yakın sayıya yuvarlanır)


6
Her zaman yalnızca alfasayısal karakterler döndürmez. Bu gibi karakterler içerebilir==
user3459110 26:14

1
Bir URL'de base64url_encodekullanılıyorsa bunun yerine kullanılabilir: php.net/manual/tr/function.base64-encode.php
Paul

9

Rastgele 11 karakterlik sayı oluşturmak için aşağıdaki kodu kullanın veya sayıyı isteğinize göre değiştirin.

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

veya rastgele sayı üretmek için özel işlevi kullanabiliriz

 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
Bu asla "aaaaaaaaaaa" veya "aaaaabbbbbb" dizesini üretemez. Sadece alfabenin rastgele bir permütasyonunun bir alt dizesini alır. 11 karakter uzunluğunda dize yalnızca V (11,35) = 288 olası değere sahiptir. Dizelerin benzersiz olmasını bekliyorsanız bunu kullanmayın!
kdojeteri

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

7
  1. En sevdiğiniz rastgele sayı üretecini kullanarak rastgele bir sayı oluşturun
  2. Kod alfabenizdeki karakter sayısıyla eşleşen bir sayı elde etmek için çarpın ve bölün.
  3. Bu dizindeki öğeyi kod alfabenize alın.
  4. İstediğiniz uzunlukta olana kadar 1) 'den tekrarlayın

ör. (sözde kodda)

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

Teorik olarak, bu aynı dizeyi bir defadan fazla üretemez mi?
frezq

4

İşte sizin için eşsiz benzersiz kimlik üreteci. benim tarafımdan yapılmış.

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

kimliğiniz için istediğiniz herhangi bir 'var'ı yankılayabilirsiniz. ama $ mdun daha iyidir, daha iyi kod için md5'i sha1 yerine değiştirebilirsiniz ama bu çok uzun olacak ki ihtiyacınız olmayabilir.

Teşekkür ederim.


7
Bu durumda rasgelelik, rastgele yazılmış kodla garanti edilir, değil mi?
Daniel Kucal

3
Evet, bu bir tür "rastgele" çünkü standart olmayan, belirsiz bir kod. Bu tahmin etmeyi zorlaştırır ... ama aslında rastgele bir sayı üretmek için güvensiz parçalar kullanmaz. sonuç teknik olarak rastgele veya güvenli değildir.
Philipp

4

Gerçekten rastgele dizeler için kullanabilirsiniz

<?php

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

çıktılar :

40a29479ec808ad4bcff288a48a25d5c

bu yüzden aynı anda birden çok kez dize oluşturmaya çalışsanız bile, farklı çıktı elde edersiniz.


4

Rastgele bir şifre oluşturmaya çalıştığınızda:

  • İlk önce kriptografik olarak güvenli bir rastgele bayt kümesi oluşturun

  • İkincisi, bu rastgele baytları yazdırılabilir bir dizeye dönüştürmek

Şimdi, php gibi rastgele bayt oluşturmak için birden çok yolu vardır:

$length = 32;

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

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

Sonra bu rastgele baytları yazdırılabilir bir dizeye dönüştürmek istersiniz:

Bin2hex kullanabilirsiniz :

$string = bin2hex($bytes);

veya base64_encode :

$string = base64_encode($bytes);

Ancak, base64 kullanırsanız dizenin uzunluğunu denetlemediğinizi unutmayın. Bunu yapmak için bin2hex kullanabilirsiniz, 32 bayt kullanmak 64 karakter dizesine dönüşür . Ancak bu sadece bir EVEN dizesinde böyle çalışacaktır .

Temel olarak şunları yapabilirsiniz :

$length = 32;

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

$string = bin2hex($bytes);

3

İşte ne kullanıyorum:

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

Bu, Harfler ve Sayılar (alfasayısal) içeren rastgele dizeler oluşturmanızı sağlayan basit bir işlevdir. Ayrıca dize uzunluğunu sınırlayabilirsiniz. Bu rastgele dizeler aşağıdakiler dahil çeşitli amaçlar için kullanılabilir: Tavsiye Kodu, Promosyon Kodu, Kupon Kodu. İşlev şu PHP işlevlerine dayanır: 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

önceki örnekleri okuduktan sonra ben bu ile geldi:

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

[0-9, AZ] dizisinin 10 katını çoğaltıyorum ve öğeleri karıştırıyorum, substr () için daha 'yaratıcı' olmak üzere rastgele bir başlangıç ​​noktası aldıktan sonra :) diziye [az] ve diğer öğeleri ekleyebilir, çoğaltabilirsiniz az çok benden daha yaratıcı ol


1

Doğrulama bağlantıları ele alırken karma anahtarları kullanmayı seviyorum. Mikrotime ve MD5 kullanarak hash öneriyoruz çünkü mikrotime dayalı hashes çünkü anahtarları aynı olmalıdır hiçbir neden olmamalıdır.

  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;

}

?>

Yukarıdaki işlev size 11 karakter uzunluğunda rastgele bir dize oluşturur.


1

PHP'de benzersiz bir dize oluşturmak istiyorsanız, aşağıdakileri deneyin.

md5(uniqid().mt_rand());

Bunda,

uniqid()- Benzersiz bir dize oluşturur. Bu işlev, zaman damgası tabanlı benzersiz tanımlayıcıyı dize olarak döndürür.

mt_rand() - Rastgele sayı üret.

md5() - Karma dizesini oluşturur.


0

Scott, evet çok yazma ve iyi bir çözümsünüz! Teşekkürler.

Ayrıca her kullanıcı için benzersiz API jetonu oluşturmam gerekiyor. Aşağıda benim yaklaşımım, kullanıcı bilgilerini (Userid ve Username) kullandım:

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

Lütfen bir göz atın ve yapabileceğim herhangi bir gelişme varsa bana bildirin. Teşekkürler


0

İşte projelerimden birinde kullandığım şey, harika çalışıyor ve BENZERSİZ BİR RASTGELE TOKEN yaratıyor :

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

Kullanıcı bu belirtecin nasıl oluşturulduğunu merak ediyor olabilen kişi için bir karışıklık yaratmak için zaman damgasını üçle çarptığımı lütfen unutmayın;)

Umut ediyorum bu yardım eder :)


1
"Kullanıcı bu belirtecin nasıl üretildiğini merak ediyor olabileceği için bir karışıklık yaratmak için zaman damgasını üçle çarptığımı lütfen unutmayın" Gizleme gibi bir şey gibi görünüyor stackoverflow.com/questions/533965/…
Harry

Zaman damgası oluşturulan rastgele bir dizeye eklendiğinden bu bir "gizleme yoluyla güvenlik" değildir ve bu döndüğümüz gerçek son dizedir;)
Kaszoni Ferencz

0

Bunun en iyi yöntem olduğunu düşünüyorum.

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

0

benzersiz dize oluşturmak için bu iki kod satırını kullanabiliriz, yaklaşık 10000000 kez yineleme test ettik

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

0

Ben her zaman bu özel bir rastgele alfasayısal dize oluşturmak için işlevimi kullanın ... Umarım bu yardım.

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

Örneğin şunu üretir: Y1FypdjVbFCFK6Gh9FDJpe6dciwJEfV6MQGpJqAfuijaYSZ86g

Benzersiz bir sıra olduğundan emin olmak için başka bir dize ile karşılaştırmak istiyorsanız bu hileyi kullanabilirsiniz ...

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

iki benzersiz dize oluşturur:

qsBDs4JOoVRfFxyLAOGECYIsWvpcpMzAO9pypwxsqPKeAmYLOi

Ti3kE1WfGgTNxQVXtbNNbhhvvapnaUfGMVJecHkUjHbuCb85pF

Umarım aradığın şey budur ...


0

Basit bir çözüm, alfasayısal olmayan karakterleri atarak temel 64'ü alfasayısal olarak dönüştürmektir.

Bu, kriptografik olarak güvenli bir sonuç için random_bytes () kullanır.

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üm mevcut fikirlerle ilgili sorunun muhtemelen benzersiz, ancak kesinlikle benzersiz olmaması olduğuna inanıyorum (Dariusz Walczak'ın loletech'e cevabında belirtildiği gibi). Aslında benzersiz bir çözümüm var. Betiğinizin bir tür belleğe sahip olması gerekir. Benim için bu bir SQL veritabanı. Ayrıca bir yere bir dosyaya da yazabilirsiniz. İki uygulama vardır:

İlk yöntem: benzersizlik sağlayan 1 yerine İKİ alana sahip olmak. İlk alan rastgele olmayan ancak benzersiz bir kimlik numarasıdır (İlk Kimlik 1, ikinci 2 ...). SQL kullanıyorsanız, kimlik alanını AUTO_INCREMENT özelliğiyle tanımlamanız yeterlidir. İkinci alan benzersiz değil, rastgele. Bu, insanların daha önce bahsettiği diğer tekniklerden herhangi biriyle üretilebilir. Scott'ın fikri iyiydi, ama md5 uygun ve muhtemelen çoğu amaç için yeterince iyi:

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

İkinci yöntem: Temel olarak aynı fikir, ancak başlangıçta üretilecek maksimum sayıda dizeyi seçin. Bu sadece bir trilyon gibi çok büyük bir sayı olabilir. Sonra aynı şeyi yapın, bir kimlik oluşturun, ancak sıfırlayın, böylece tüm kimlikler aynı sayıda basamak olmalıdır. Sonra kimliği rastgele dizeyle birleştirin. Çoğu amaç için yeterince rastgele olacaktır, ancak kimlik bölümü benzersiz olmasını da sağlayacaktır.


-1

Bu kodu kullanabilirsiniz, umarım sizin için yararlı olacaktır.

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

PHP rastgele kod üreteci hakkında detaylar


-2

Kötü bir şekilde yavaşlayan ve sadece bir kez openssl_random_pseudo_bytes çağırmaktan daha güvenli hale getirmeyen gereksiz döngüleri kaldırarak yukarıdaki Scotts kodunu basitleştirmek

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

Ne yazık ki, bunun crypto_rand_secure işlevinin uygun bir sadeleştirmesi olduğunu kabul edemiyorum. Döngü, rasgele oluşturulmuş bir sayının sonucunu aldığınızda ortaya çıkan modulo yanlılığını önlemek ve daha sonra aralığı bölen bir sayı ile modifiye etmek için gereklidir. en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle#Modulo_bias . Aralık dışındaki herhangi bir sayıyı dışarı atmak ve yeni bir sayı seçmek için bir döngü kullanarak, bu önyargıdan kaçınır. stackoverflow.com/questions/10984974/…
Scott

@Scott, bu yazı rand () hakkında. Ancak bu durumda, zaten openssl_random_pseudo_bytes tarafından halledilir.
mabel

1
gist.github.com/anonymous/87e3ae6fd3320447f46b973e75c2ea85 - Lütfen bu komut dosyasını çalıştırın. Sonuçların dağılımının rasgele olmadığını göreceksiniz. 0-55 arasındaki sayılar, 56-100 arasındaki sayılardan daha yüksektir. opensslbuna neden olmuyorsa, bunun nedeni dönüş ifadenizdeki modulo önyargısıdır. 100 (aralık) 255 (1 bayt) eşit olarak bölmez ve bu sonuçlara neden olur. Cevabınızla ilgili en büyük sorunum, işlevin yanlış bir döngü kullanmak kadar güvenli olduğunu belirtmenizdir. Crypto_rand_secure uygulamanız kriptografik olarak güvenli değil ve yanıltıcı.
Scott

@Scott, burada kazıyoruz, son dönüş ifadesiyle ilgili değil, ayrıca modulo kullanmadan openssl_random_pseudo_bytes dönüş değerinden aşamalı olarak hesaplanabilir. Yaptığım nokta, openssl_random_pseudo_bytes rastgele baytları döndürdüğünde döngü gereksiz olmasıdır. Döngü yaparak, onu daha güvenli hale getirmiyorsunuz, sadece yavaşlatıyorsunuz.
mabel

2
Bu cevap kötü bilgi yayar. Döngünün openssldaha güvenli hale gelmediğinden eminsiniz, ama daha da önemlisi, daha az güvenli hale getirmiyor, bu cevap yapıyor. Yukarıdaki kod, mükemmel bir rasgele sayı alır ve daha düşük sayılara doğru yöneltir. Cevabınıza daha hızlı olduğunu (döngüyü kaldırarak) ancak CSPRNG olmadığını belirten bir sorumluluk reddi beyanı verirseniz, bu sorun çözülür. Lütfen, kripto sevgisi için, kullanıcılara bu işlevin çıktısının taraflı olabileceğini ve eşdeğer bir çözüm olmadığını bildirin . Döngü sadece sizi rahatsız etmek için orada değil.
Scott
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.