임의의 5 자 문자열 생성


102

중복 될 가능성이 가장 적은 정확한 5 개의 임의 문자열을 만들고 싶습니다. 이를 수행하는 가장 좋은 방법은 무엇입니까? 감사.


2
특정 캐릭터 세트가 0-9a-zA-Z있습니까?
— Yanick Rochon 2011 년

이 코드 골프 챌린지는 찾을 수 있습니다 : codegolf.stackexchange.com/questions/119226/…
— Titus

를 사용 Random::alphanumericString($length)하면 암호화로 안전한 임의 데이터에서 가져온 0-9a-zA-Z 문자열을 가져올 수 있습니다.
— caw

답변:


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

내 추측은 아마도 특수 문자를 찾는 것이 아니라면 다음과 같다.

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

예

그리고 시계를 기반으로 한 경우 (증분이므로 충돌이 적음) :

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

참고 : 증분은 추측하기 쉽다는 것을 의미합니다. 이것을 솔트 또는 인증 토큰으로 사용하는 경우 사용하지 마십시오. "WCWyb"의 솔트 (현재)는 5 초 후 "WCWyg"임을 의미합니다.)


6
md5()그러나 사용시 문제점 은 16 문자 세트 (10 자리 및 a~ f, 즉 문자열 문자 당 4 비트) 로 구성된 문자열을 얻는다는 것 입니다. 이것은 일부 목적에는 충분할 수 있지만 암호화 목적으로는 너무 적을 수 있습니다 (16 개 기호 중 5 개 문자 = 16 ^ 5 = 20 비트 = 1048576 가능성).
— 아크

3
array_rand($seed, 5)값이 아닌 배열 키를 반환하므로 코드가 작동하지 않습니다
— alumi

1
임의의 문자를 생성하기 위해 암호화 해시 함수 를 사용하는 것은 적어도 부적절하다고 생각합니다.
— gronostaj 2013

또한 가능한 한 포함하는 것입니다 ", '및 백 슬래시 $charset? 이러한 문자를 포함하려면 이스케이프 시퀀스를 사용해야합니까?
— Mai

1
두 번째 스 니펫은 $len입력 매개 변수 도 사용하지 않습니다. 잊으셨습니까?
— TechNyquist 2015

76

for루프가 부족한 경우 사용하고 싶은 것은 다음과 같습니다.

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

흥미로운 솔루션 ... 매우 간결하지만 이것이 for를 사용하는 것보다 빠르거나 느린 지 궁금합니다. 벤치 마크를 방해 할 수 없습니다 :-)하지만
— 아크

@matthew str_shuffle은 지속적으로 중복을 생성합니다
— SCC

@ user2826057 : str_shuffle('ab')줄 것 ab또는 ba하지만 결코 aa. 추가하면 str_repeat허용됩니다. 그러나 내가 준 해결책은 실제로 심각한 것은 아니지만 작동하지만.
— 마태 복음

2
RNG가 균일하게 분포되어 있다고 가정하면 1/60466176이 발생할 가능성이 있습니다.
— Matthew

1
이것은 바우처 코드를 생성하는 사용 사례에 적합합니다. 우리는 같은 문자, 혼란을 제거 l, i, 1, 0, O, 등을 밖으로의 500 개 상품권에는 중복 없어.
— Luke Cousins ​​2014 년

25

빠른 방법은 uniqid 함수 의 가장 변덕스러운 문자를 사용하는 것입니다.

예를 들면 :

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


15

다음은 중복 가능성을 최소화해야합니다 ( mt_rand()예 /dev/*random: GUID 에서 또는 GUID 에서 더 나은 난수 소스 로 대체 할 수 있음 ).

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

편집 :
당신이 보안에 대해 우려하는 경우, 정말 할 수 없습니다 사용 rand()하거나 mt_rand(), 당신의 임의의 데이터 장치가 실제로 발생 장치인지 확인 임의 의 데이터가 아닌 일반 파일 또는 같은 예측 뭔가를 /dev/zero. mt_rand()유해한 것으로 간주 :
https://spideroak.com/blog/20121205114003-exploit-information-leaks-in-random-numbers-from-python-ruby-and-php

편집 : PHP에서 OpenSSL을 지원하는 경우 다음을 사용할 수 있습니다 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];
?>

$ 결과 더욱 영리 첫번째 예 [(나 strlen 0 ($ 자) -1)에는, mt_rand = $ 캐릭터.
— hamboy75

이 경우 길이를 미리 결정하고 최소한 변수에 저장해야합니다. strlen()루프에서 사용 하는 것은 불필요한 오버 헤드입니다. 특히 문자 세트가 그 동안 변경되지 않을 것이라는 것을 이미 알고있는 경우 더욱 그렇습니다.
— 아크

나는 어쨌든이 옵션 :), 그것은, PHP는 최적화 된 의심
— hamboy75

7

나는 항상 이것에 대해 동일한 기능을 사용하며 일반적으로 암호를 생성합니다. 사용하기 쉽고 유용합니다.

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

좋은 코드. 그러나 $ alt는 항상 1에서 0으로 뒤집습니다. 대신 $ alt를 무작위로 지정하는 것이 낫지 않습니까?
— 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

문자 AF 만받는 것이 괜찮다면 여기 내 해결책이 있습니다.

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

해시 함수를 사용하는 것은 임의의 16 진수 시퀀스를 생성하는 것과 같은 간단한 작업에 과잉이라고 생각합니다. dechex+ mt_rand는 동일한 작업을 수행하지만 불필요한 암호화 작업없이 수행합니다. str_pad출력 문자열의 5 자 길이를 보장합니다 (난수가 0x10000 미만인 경우).

중복 가능성은 mt_rand의 신뢰성 에 달려 있습니다. Mersenne Twister 는 고품질 임의성으로 유명하므로 작업에 적합해야합니다.


2

PHP 사용을 생각할 때까지이 작업을 수행하는 방법도 몰랐습니다 array. 그리고 이것이 배열로 임의의 문자열이나 숫자를 생성하는 가장 간단한 방법이라고 확신합니다. 코드:

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

이 기능을 다음과 같이 사용할 수 있습니다.

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

유사 브래드 크리스티 의 대답하지만, 사용 sha1문자 alrorithm을 0-9a-zA-Z하고 임의의 값 접두어

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

그러나 정의 된 (허용 된) 문자를 설정 한 경우 :

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

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

** 업데이트 **

으로 Archimedix는 지적이 조합의 수는 지정된 문자 범위에 대한 낮은으로 "복제지고의 이상 가능성"를 반환 보장하지 않습니다. 문자 수를 늘리거나 문자열에 추가 (특수) 문자를 허용해야합니다. 귀하의 경우 첫 번째 해결책이 더 바람직하다고 생각합니다.


사용은 time()1 백만 회 이상의 예측까지입니다 microtime().
— Arc

또한 Brad의 답변에 대한 내 의견에 유의하십시오. 더 큰 문제는 생성 된 해시가 16 개의 유효한 문자로 구성된 16 진수 표현이므로 $str.
— Arc

@Archimedix, 아마도 OP는 보안을 요구하지 않았고, 질문은 5x26 다른 문자의 조합으로 구성된 문자열 생성 알고리즘을 갖고 중복을 피하도록 정의되었습니다. 이것은 등록 과정에서 확인 참조 번호 (또는 청구 과정), 또는 뭔가 아마
— Yanick Rochon

그가 나의 이해이었다 한 부탁 중복지고의 이상 가능성 , 이것은 10 억에 거의 1 수 있었던 0.1 %의 확률 (1024 일)를 갖는다.
— 아크

그러나 5 자의 참조 키를 생성하고 클라이언트 / 고객에게 제공해야하는 경우 ˫§»⁋⅓단순히 더 안전하기 때문에 " " 을 (를) 제공하고 싶지 않습니다. 참조 키를 7 자 이상으로 늘립니다. . (BTW : 내 이전 코멘트 교정, 그것은 5x36 문자입니다)
— Yanick Rochon

1

PHP 에서 잘 작동합니다 (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;

라이브 데모


1

출처 : 임의의 문자를 생성하는 PHP 함수

이 간단한 PHP 함수는 저에게 효과적이었습니다.

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;

}

용법:

echo cvf_ps_generate_random_code(5);

1

여기 내 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의 새로운 password_hash()(*> = PHP 5.5) 함수는 상당히 긴 대문자 및 소문자 및 숫자 세트를 생성하는 작업을 수행합니다.

두 개의 연결. password_hash$ random 함수 앞뒤의 문자열 은 변경에 적합합니다.

대한 Paramteres $random()*는 ($ A, $ b)는 실제로 substr()매개 변수를 설정합니다. :)

참고 : 이것은 함수일 필요는 없습니다. 다음과 같이 하나의 불쾌한 싱글 라이너로 일반 변수 일 수도 있습니다.

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

전문가 팁-답변이 OP의 문제를 어떻게 해결하는지, 그리고 이미 제공된 다른 답변과 다른 이유에 대한 설명을 포함합니다.
— 톰

0

나는 이것을 사용했습니다.

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

호출 할 때 문자열의 길이를 설정합니다.

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

문자열에서 가능한 문자를 변경할 수도 있습니다 $a.


이 기능을 개발하는 동안 잃어버린 시간을 봅니다. 나는 조금 봤어! 앤드류
— LipESprY
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.