PHP: rasgele, benzersiz, alfanümerik dize oluşturmak için nasıl?

6 Cevap php

Nasıl bir doğrulamak bağlantı kullanılmak üzere sayı ve harfleri kullanarak rasgele, benzersiz bir dize oluşturmak mümkün olurdu? Bir web sitesinde bir hesap oluşturun ve size bir link içeren bir e-posta gönderir, ve sen ... evet ... Hesabınızı doğrulamak için bu bağlantıyı tıklayın onlardan biri olduğunda gibi.

Nasıl PHP kullanarak bunlardan birini oluşturabilir?

Update: Sadece uniqid() hakkında hatırladım. Bu mikrosaniye şimdiki zamana dayalı benzersiz bir tanımlayıcı üreten bir PHP fonksiyonu bulunuyor. Ben bunu kullanırız düşünüyorum.

6 Cevap

Eğer zaman içinde kesinlikle benzersiz olması gerekir yoksa:

md5(uniqid(rand(), true))

Aksi halde (zaten kullanıcı için benzersiz bir giriş tespit ettik verilmiştir):

md5(uniqid($your_user_login, true))

Ben sadece bu aynı sorunu çözmek için nasıl içine bakıyordu, ama aynı zamanda benim işlevi de şifre alımı için kullanılabilecek bir belirteç oluşturmak istiyorum. Bu benim tahmin edilmesi belirteci yeteneğini sınırlamak gerektiği anlamına gelir. uniqid is based on the time, and according to php.net "the return value is little different from microtime()", uniqid kriterlere uymayan çünkü. PHP kriptografik olarak güvenli belirteçleri oluşturmak yerine openssl_random_pseudo_bytes() kullanılmasını önerir.

A, hızlı kısa ve noktasına cevabı:

bin2hex(openssl_random_pseudo_bytes($bits))

which will generate a random string of alphanumeric characters of length = $bits * 2. Unfortunately this only has an alphabet of [a-f][0-9], but it works.


Below is the strongest function I could make that satisfies the criteria (This is an implemented version of Erik's answer).

function crypto_rand_secure($min, $max) {
        $range = $max - $min;
        if ($range < 0) return $min; // not so random...
        $log = 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";
    for($i=0;$i<$length;$i++){
        $token .= $codeAlphabet[crypto_rand_secure(0,strlen($codeAlphabet))];
    }
    return $token;
}

crypto_rand_secure($min, $max) rand() ya da mt_rand için yedek bir damla olarak çalışmaktadır. Bu $ dk ve $ max arasında rastgele bir sayı oluşturmak için openssl_random_pseudo_bytes kullanır.

getToken($length) belirteci içinde kullanmak için bir alfabe oluşturur ve ardından uzunlukta bir dize oluşturur $length.

EDIT: Ben kaynağını alıntı ihmal - http://us1.php.net/manual/en/function.openssl-random-pseudo-bytes.php#104322

Bu fonksiyon sayıları ve harfleri kullanarak rasgele 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
  1. Generate a random number using your favourite random-number generator
  2. Multiply and divide it to get a number matching the number of characters in your code alphabet
  3. Get the item at that index in your code alphabet.
  4. Repeat from 1) until you have the length you want

örneğin (sözde kod)

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

İşte sizin için nihai benzersiz kimliği jeneratör olduğunu. bana göre yaptı.

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

istediğiniz gibi sizin id için herhangi bir 'var' echo. ama $ mdun daha iyi, daha iyi kod için sha1 için md5 değiştirebilirsiniz ama size ihtiyacım yok olabilecek çok uzun olacak.

Teşekkür ederim.

Scott, evet çok yazmak ve iyi bir çözüm var! Teşekkürler.

Ben de her kullanıcı için benzersiz API belirteç oluşturmak için gerekli. Benim yaklaşımım şudur, ben kullanıcı bilgilerini (kullanıcı kimliği ve adı) kullanılır:

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

Bir göz ve herhangi bir iyileşme ben yapabilirim varsa bana bildirin lütfen. Teşekkürler