임의의 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.