Rastgele 5 karakter dizisi oluşturun


102

En az kopyalanma olasılığı ile tam 5 rastgele karakter dizisi oluşturmak istiyorum. Bunu yapmanın en iyi yolu ne olabilir? Teşekkürler.


2
belirli bir karakter kümeniz var 0-9a-zA-Zmı yoksa sadece ?
Yanick Rochon

Bu kod golf mücadelesi bir keşif
Titus

Kullanarak Random::alphanumericString($length), 0-9a-zA-Z içeren dizeleri kriptografik olarak güvenli rastgele verilerden elde edebilirsiniz.
2019

Yanıtlar:


162
$rand = substr(md5(microtime()),rand(0,26),5);

En iyi tahminim olur - Siz de özel karakterler aramıyorsanız:

$seed = str_split('abcdefghijklmnopqrstuvwxyz'
                 .'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
                 .'0123456789!@#$%^&*()'); // and any other characters
shuffle($seed); // probably optional since array_is randomized; this may be redundant
$rand = '';
foreach (array_rand($seed, 5) as $k) $rand .= $seed[$k];

Misal

Ve saati temel alan biri için (artımlı olduğundan daha az çarpışma):

function incrementalHash($len = 5){
  $charset = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
  $base = strlen($charset);
  $result = '';

  $now = explode(' ', microtime())[1];
  while ($now >= $base){
    $i = $now % $base;
    $result = $charset[$i] . $result;
    $now /= $base;
  }
  return substr($result, -5);
}

Not: artımlı, tahmin edilmesi daha kolay anlamına gelir; Bunu bir tuz veya doğrulama jetonu olarak kullanıyorsanız, kullanmayın. Bir "WCWyb" tuzu (şimdi) 5 saniye sonra "WCWyg" olduğu anlamına gelir)


6
md5()Bununla birlikte, kullanmanın sorunu, 16 karakterlik bir diziden oluşan bir dizge elde etmenizdir (10 hane ve a- f, yani, karakter dizisi başına 4 bit). Bu, bazı amaçlar için yeterli olabilir, ancak kriptografik amaçlar için çok az olabilir (16 sembolden beş karakter = 16 ^ 5 = 20 bit = 1048576 olasılık).
Ark

3
array_rand($seed, 5)değer değil dizi anahtarı döndürecektir, böylece kodunuz çalışmayacaktır
alumi

1
Rastgele karakterler oluşturmak için kriptografik bir hash işlevi kullanmanın en azından uygunsuz olduğunu düşünüyorum.
gronostaj

O da mümkün dahil etmek mi ", 've ters bölü $charset? Bu karakterleri dahil etmek için kaçış dizilerini kullanmam gerekir mi?
Mai

1
İkinci pasaj $lengiriş parametresini bile kullanmıyor ... unuttunuz mu?
TechNyquist

77

Eğer fordöngüler sıkıntısı vardır, burada kullanımına ne gibi:

$s = substr(str_shuffle(str_repeat("0123456789abcdefghijklmnopqrstuvwxyz", 5)), 0, 5);

İlginç bir çözüm ... çok özlü, bunun için kullanmaktan daha hızlı mı yoksa daha yavaş mı olduğunu merak ediyorum. Yine de kıyaslama yapmaktan rahatsız olamaz :-)
Arc

@matthew str_shuffle sürekli olarak kopyalar üretecek
SCC

@ user2826057: str_shuffle('ab')verir abveya verir baama asla aa. Bunun için izinleri eklemek str_repeat. Ancak bununla birlikte, verdiğim çözüm gerçekten ciddi bir çözüm değil ... işe yarasa da.
Matthew

2
RNG'nin eşit olarak dağıtıldığı varsayılarak bunun gerçekleşme ihtimali 1/60466176'dır.
Matthew

1
Bu, kupon kodları oluşturma durumumuz için mükemmeldir. Biz gibi karakter, kafa karıştırıcı kaldırılan l, i, 1, 0, O, vb ve üzerinden 500 kuponları hiçbir çiftleri var.
Luke Cousins

25

Hızlı bir yol, uniqid işlevinin en uçucu karakterlerini kullanmaktır .

Örneğin:

$rand = substr(uniqid('', true), -5);


15

Aşağıdakiler, en az çoğaltma şansını sağlamalıdır ( mt_rand()örneğin /dev/*random, GUID'lerden veya GUID'lerden daha iyi bir rasgele sayı kaynağıyla değiştirmek isteyebilirsiniz ):

<?php
    $characters = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
    $result = '';
    for ($i = 0; $i < 5; $i++)
        $result .= $characters[mt_rand(0, 61)];
?>

DÜZENLEME:
Güvenlik konusunda endişeleriniz varsa, gerçekten, do not kullanmak rand()veya mt_rand(), ve rasgele veri cihazı aslında üreten bir cihaz olduğunu doğrulamak rastgele veriler değil, normal bir dosya veya benzeri öngörülebilir bir şey /dev/zero. mt_rand()zararlı kabul edilen:
https://spideroak.com/blog/20121205114003-exploit-information-leaks-in-random-numbers-from-python-ruby-and-php

DÜZENLEME: PHP'de OpenSSL desteğiniz varsa, şunları kullanabilirsiniz openssl_random_pseudo_bytes():

<?php
    $length = 5;
    $randomBytes = openssl_random_pseudo_bytes($length);
    $characters = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
    $charactersLength = strlen($characters);
    $result = '';
    for ($i = 0; $i < $length; $i++)
        $result .= $characters[ord($randomBytes[$i]) % $charactersLength];
?>

İlk örnek $ sonuç ile daha akıllıca. = $ Karakter [mt_rand (0, strlen ($ karakterler) -1)]
hamboy75

Bu durumda uzunluğu önceden belirlemeli ve en azından bir değişkene kaydetmelisiniz. strlen()Bir döngüde kullanmak , özellikle karakter setinin bu arada değişmeyeceğini zaten biliyorsanız, gereksiz bir ek yüktür.
Ark


7

Bunun için her zaman aynı işlevi kullanıyorum, genellikle şifre oluşturmak için. Kullanımı kolay ve kullanışlı.

function randPass($length, $strength=8) {
    $vowels = 'aeuy';
    $consonants = 'bdghjmnpqrstvz';
    if ($strength >= 1) {
        $consonants .= 'BDGHJLMNPQRSTVWXZ';
    }
    if ($strength >= 2) {
        $vowels .= "AEUY";
    }
    if ($strength >= 4) {
        $consonants .= '23456789';
    }
    if ($strength >= 8) {
        $consonants .= '@#$%';
    }

    $password = '';
    $alt = time() % 2;
    for ($i = 0; $i < $length; $i++) {
        if ($alt == 1) {
            $password .= $consonants[(rand() % strlen($consonants))];
            $alt = 0;
        } else {
            $password .= $vowels[(rand() % strlen($vowels))];
            $alt = 1;
        }
    }
    return $password;
}

Güzel kod. Bununla birlikte, $ alt her zaman birden 0'a döner. Bunun yerine $ alt'ı rastgele hale getirmek daha iyi olmaz mıydı?
Nico Andrade


3
$str = '';
$str_len = 8;
for($i = 0, $i < $str_len; $i++){
    //97 is ascii code for 'a' and 122 is ascii code for z
    $str .= chr(rand(97, 122));
}
return $str

2

Yalnızca AF harflerini almanız sorun değilse, işte çözümüm:

str_pad(dechex(mt_rand(0, 0xFFFFF)), 5, '0', STR_PAD_LEFT);

Karma işlevlerin kullanılmasının, rastgele onaltılık rakamlar dizisi oluşturmak gibi basit bir görev için aşırı bir beceri olduğuna inanıyorum. dechex+ mt_randaynı işi yapar, ancak gereksiz kriptografik çalışma yapmaz. str_padçıktı dizesinin 5 karakter uzunluğunu garanti eder (rastgele sayı 0x10000'den küçükse).

Yinelenen olasılık, mt_randgüvenilirliğine bağlıdır . Mersenne Twister , yüksek kaliteli rastgelelikle bilinir, bu nedenle göreve tam olarak uymalıdır.


2

Ayrıca PHP'leri kullanmayı düşünene kadar bunu nasıl yapacağımı bilmiyordum array. Ve bunun, dizilerle rastgele bir dizi veya sayı oluşturmanın en basit yolu olduğundan oldukça eminim. Kod:

function randstr ($len=10, $abc="aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ0123456789") {
    $letters = str_split($abc);
    $str = "";
    for ($i=0; $i<=$len; $i++) {
        $str .= $letters[rand(0, count($letters)-1)];
    };
    return $str;
};

Bu işlevi şu şekilde kullanabilirsiniz

randstr(20)     // returns a random 20 letter string
                // Or like this
randstr(5, abc) // returns a random 5 letter string using the letters "abc"

1

Benzer Brad Christie bireyin cevabı, ancak kullanarak sha1karakterler için alrorithm 0-9a-zA-Zve rastgele değer öneki:

$str = substr(sha1(mt_rand() . microtime()), mt_rand(0,35), 5);

Ancak tanımlı (izin verilen) bir karakter belirlediyseniz:

$validChars = array('0','1','2' /*...*/,'?','-','_','a','b','c' /*...*/);
$validCharsCount = count($validChars);

$str = '';
for ($i=0; $i<5; $i++) {
    $str .= $validChars[rand(0,$validCharsCount - 1)];
}

** GÜNCELLEME **

As Archimedix işaret, bu kombinasyonun sayısı göz önüne alındığında karakter aralığı için düşük olduğundan, bir "çoğaltılamaz alma az ihtimalini" dönmek garantisini vermez. Karakter sayısını artırmanız veya dizede fazladan (özel) karakterlere izin vermeniz gerekir. Sanırım sizin durumunuzda ilk çözüm tercih edilebilir.


Kullanmaktan time()1 milyon kat daha tahmin edilebilir microtime().
Arc

Ayrıca Brad'in cevabına yaptığım yorumları not edin, daha büyük sorun, oluşturulan hash'in 16 geçerli karakterden oluşan onaltılık bir gösterim olmasıdır, bu nedenle için sadece 1024 varyasyon kalır $str.
Arc

@Archimedix, belki, ancak OP güvenlik istemedi, soru 5x26 farklı karakter kombinasyonundan oluşan dizgi üreten algoritmaya sahip olmak ve kopyalardan kaçınmak olarak tanımlandı. Bu muhtemelen bir kayıt sürecindeki (veya faturalandırma sürecindeki) bir onay referans numarası veya başka bir şey içindir
Yanick Rochon

Onun benim anlayış oldu did istemek çoğaltılamaz alma azından olasılığı ve bu 1 milyar neredeyse 1 olabilirdi olasılığın% 0,1 (1024 yılında 1) sahiptir.
Ark

ancak, 5 karakterlik bir referans anahtarı oluşturmanız ve size bir müşteri " ˫§»⁋⅓" vermeniz gerekiyorsa, onlara " " sadece daha güvenli olduğu için vermek istemezsiniz ... referans anahtarınızı 7 veya daha fazla karaktere yükseltirsiniz . (BTW: önceki yorumumdaki düzeltme, 5x36 karakter)
Yanick Rochon

1

PHP'de iyi çalışıyor (php 5.4.4)

$seed = str_split('abcdefghijklmnopqrstuvwxyz');
$rand = array_rand($seed, 5);
$convert = array_map(function($n){
    global $seed;
    return $seed[$n];
},$rand);

$var = implode('',$convert);
echo $var;

Canlı Demo


1

Kaynak: Rastgele Karakterler Oluşturan PHP İşlevi

Bu basit PHP işlevi benim için çalıştı:

function cvf_ps_generate_random_code($length=10) {

   $string = '';
   // You can define your own characters here.
   $characters = "23456789ABCDEFHJKLMNPRTVWXYZabcdefghijklmnopqrstuvwxyz";

   for ($p = 0; $p < $length; $p++) {
       $string .= $characters[mt_rand(0, strlen($characters)-1)];
   }

   return $string;

}

Kullanım:

echo cvf_ps_generate_random_code(5);

1

İşte benim random 5 cents...

$random=function($a, $b) {
    return(
        substr(str_shuffle(('\\`)/|@'.
        password_hash(mt_rand(0,999999),
        PASSWORD_DEFAULT).'!*^&~(')),
        $a, $b)
    );
};

echo($random(0,5));

PHP'nin yeni password_hash()(*> = PHP 5.5) işlevi, oldukça uzun büyük harf ve küçük harf karakterleri ve sayıları oluşturma işini yapıyor.

İki concat. password_hash$ random işlevi içinde önceki ve sonraki dizeler değişiklik için uygundur.

İçin Paramteres $random()* ($ a $, b) aslında substr()parametreleri. :)

NOT: Bunun bir işlev olması gerekmez, normal değişken de olabilir .. kötü bir tek satırlayıcı gibi, şöyle:

$random=(substr(str_shuffle(('\\`)/|@'.password_hash(mt_rand(0,999999), PASSWORD_DEFAULT).'!*^&~(')), 0, 5));

echo($random);

1
function CaracteresAleatorios( $Tamanno, $Opciones) {
    $Opciones = empty($Opciones) ? array(0, 1, 2) : $Opciones;
    $Tamanno = empty($Tamanno) ? 16 : $Tamanno;
    $Caracteres=array("0123456789","abcdefghijklmnopqrstuvwxyz","ABCDEFGHIJKLMNOPQRSTUVWXYZ");
    $Caracteres= implode("",array_intersect_key($Caracteres, array_flip($Opciones)));
    $CantidadCaracteres=strlen($Caracteres)-1;
    $CaracteresAleatorios='';
    for ($k = 0; $k < $Tamanno; $k++) {
        $CaracteresAleatorios.=$Caracteres[rand(0, $CantidadCaracteres)];
    }
    return $CaracteresAleatorios;
}

Uzman ipucu - Cevabınızın OP'nin problemini nasıl çözdüğüne ve zaten verilen diğer cevaplardan neden farklı olabileceğine dair bazı açıklamalar ekleyin.
Tom

0

Ben uzaktayım bunu kullanıyorum:

<?php function fRand($len) {
    $str = '';
    $a = "abcdefghijklmnopqrstuvwxyz0123456789";
    $b = str_split($a);
    for ($i=1; $i <= $len ; $i++) { 
        $str .= $b[rand(0,strlen($a)-1)];
    }
    return $str;
} ?>

Onu çağırdığınızda, ipin uzunluğunu belirler.

<?php echo fRand([LENGHT]); ?>

Ayrıca dizedeki olası karakterleri de değiştirebilirsiniz $a.


Bu işlevi boşa harcayarak zaman kaybettiğini görüyorum. Google'da biraz araştırdım! @Andrew
LipESprY
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.