PHP : 임의의 고유 한 영숫자 문자열을 생성하는 방법?


380

확인 링크에 사용하기 위해 숫자와 문자를 사용하여 임의의 고유 한 문자열을 생성하는 방법은 무엇입니까? 웹 사이트에서 계정을 만들 때 링크가 포함 된 이메일을 보내면 계정을 확인하려면 해당 링크를 클릭해야합니다.

PHP를 사용하여 그중 하나를 어떻게 생성 할 수 있습니까?

업데이트 : 방금 기억했습니다 uniqid(). 현재 시간 (마이크로 초)을 기반으로 고유 식별자를 생성하는 PHP 함수입니다. 나는 그것을 사용할 것이라고 생각합니다.


문자열과 균일하게 분포 된 난수 만 있으면됩니다.
Artelius 2009

10
Andrew, Scott정답으로 선택해야합니다 . Scott은 플랫폼에 따라 가장 안전한 엔트로피 소스를 선택하는 OpenSSL의 암호화 보안 의사 난수 생성기 (CSPRNG)를 사용하고 있습니다.
루크

3
2015 년
이후이 기사를

OpenSSL이며 uniqid안전하지 않습니다. Random::alphanumericString($length)또는 같은 것을 사용하십시오 Random::alphanumericHumanString($length).
caw

답변:


305

보안 공지 :이 솔루션은 임의의 품질이 응용 프로그램의 보안에 영향을 줄 수있는 상황에서는 사용해서는 안됩니다. 특히, rand()uniqid()암호 난수 발생기를 안전하지 않습니다 . 안전한 대안 은 Scott의 답변 을 참조하십시오 .

시간이 지남에 따라 고유해야 할 필요가없는 경우 :

md5(uniqid(rand(), true))

그렇지 않은 경우 (사용자의 고유 한 로그인을 이미 결정한 경우) :

md5(uniqid($your_user_login, true))

90
두 방법 모두 고유성을 보장 하지는 않습니다 . md5 함수의 입력 길이는 출력 길이보다 길며 en.wikipedia.org/wiki/Pigeonhole_principle에 따르면 충돌이 보장됩니다. 반면, "고유 한"id를 달성하기 위해 해시에 의존하는 인구가 많을수록 적어도 하나의 충돌이 발생할 확률이 높아집니다 ( en.wikipedia.org/wiki/Birthday_problem 참조 ). 대부분의 솔루션에 대한 확률은 적을 수 있지만 여전히 존재합니다.
다리우스 발차 크

12
이것은 임의의 값을 생성하는 안전한 방법이 아닙니다. Scott의 답변을 참조하십시오.
rook

4
비교적 빨리 만료되는 전자 메일 확인의 경우 한 사람이 언젠가 다른 사람의 전자 메일을 다른 사람의 전자 메일로 확인했을 가능성은 미미한 위험이라고 생각합니다. 그러나 토큰을 생성 한 후 DB에 토큰이 이미 있는지 항상 확인할 수 있으며, 그렇다면 새로운 토큰을 선택하십시오. 그러나 코드 스 니펫을 작성하는 데 소요되는 시간은 실행되지 않을 가능성이 높으므로 낭비 될 수 있습니다.
Andrew

md5는 16 진수 값을 반환하므로 문자 집합이 [0-9] 및 [af]로 제한됩니다.
Thijs Riezebeek

1
MD5는 그냥 uniqid 이점을 파괴 한 충돌을 할 수 있습니다
user151496

507

나는이 같은 문제를 해결하는 방법을 찾고 있었지만 암호 검색에도 사용할 수있는 토큰을 만드는 기능을 원합니다. 이것은 토큰의 추측 능력을 제한해야 함을 의미합니다. 때문에 uniqid시간에 따라, 그리고 php.net에 따라하고있다 "반환 값은 () microtime에서 약간 다릅니다은" uniqid기준을 충족하지 않습니다. PHP openssl_random_pseudo_bytes()는 암호로 안전한 토큰을 생성하기 위해 대신 사용 하는 것이 좋습니다 .

짧고 간결한 대답은 다음과 같습니다.

bin2hex(openssl_random_pseudo_bytes($bytes))

길이 = $ bytes * 2의 임의의 영숫자 문자열을 생성합니다. 불행히도 이것은 알파벳 만 [a-f][0-9]있지만 작동합니다.


아래는 기준을 만족시킬 수있는 가장 강력한 기능입니다 (이것은 Erik의 답변의 구현 버전입니다).

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()또는의 대체품으로 사용됩니다 mt_rand. openssl_random_pseudo_bytes를 사용하여 $ min과 $ max 사이의 난수를 만드는 데 도움이됩니다.

getToken($length)토큰 내에서 사용할 알파벳을 만든 다음 length 문자열을 만듭니다 $length.

편집 : 나는 소스 인용을 소홀히했다-http : //us1.php.net/manual/en/function.openssl-random-pseudo-bytes.php#104322

편집 (PHP7) : PHP7 의 출시와 함께 표준 라이브러리에는 위의 crypto_rand_secure 함수를 대체 / 개선 / 단순화 할 수있는 두 가지 새로운 기능이 있습니다. random_bytes($length)random_int($min, $max)

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

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

예:

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
동의했다. 평문 암호 저장은 끔찍합니다! (나는 복어를 사용합니다.) 그러나 토큰이 생성되면 토큰 보유자가 암호를 재설정 할 수 있으므로 토큰은 유효하면서 암호와 동일하며 유효합니다.
Scott

23
안녕하세요, 저는 우수한 코드를 편리한 Kohana Text :: random () 메소드 기능과 결합하여이 요점을 만들었습니다. gist.github.com/raveren/5555297
raveren

9
완전한! 나는 길이로 10 자로 테스트했습니다. 100000 개의 토큰으로 여전히 중복되지 않습니다!
Sharpless512

5
나는이 과정을 사용하고 매우 느리다는 것을 알았습니다. 36의 길이는 dev 서버에서 시간 초과되었습니다. 24의 길이로 여전히 약 30 초가 걸렸습니다. 내가 뭘 잘못했는지 확실하지 않지만 너무 느려서 다른 해결책을 선택했습니다.
Shane

5
알파벳 base64_encode대신 bin2hex큰 문자열을 얻기 위해 대신에 사용할 수도 있습니다 .
erjiang

91

가장 투표가 많은 솔루션의 객체 지향 버전

Scott 의 답변을 기반으로 객체 지향 솔루션을 만들었습니다 .

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

용법

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

맞춤 알파벳

필요한 경우 사용자 정의 알파벳을 사용할 수 있습니다. 지원되는 문자가있는 문자열을 생성자 또는 설정자에게 전달하십시오.

<?php

$customAlphabet = '0123456789ABCDEF';

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

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

출력 샘플은 다음과 같습니다

SRniGU2sRQb2K1ylXKnWwZr4HrtdRgrM
q1sRUjNq1K9rG905aneFzyD5IcqD4dlC
I0euIWffrURLKCCJZ5PQFcNUCto6cQfD
AKwPJMEM5ytgJyJyGqoD5FQwxv82YvMr
duoRF6gAawNOEQRICnOUNYmStWmOpEgS
sdHUkEn4565AJoTtkc8EqJ6cC4MLEHUx
eVywMdYXczuZmHaJ50nIVQjOidEVkVna
baJGt7cdLDbIxMctLsEBWgAw5BByP5V0
iqT0B2obq3oerbeXkDVLjZrrLheW4d8f
OUQYCny6tj2TYDlTuu1KsnUyaLkeObwa

누군가에게 도움이되기를 바랍니다. 건배!


죄송하지만 이걸 어떻게 실행합니까? 나는 $obj = new RandomStringGenerator;했지만 어떤 방법을 호출해야합니까? 감사합니다.
sg552

@ sg552, generate위의 예제와 같이 메소드를 호출해야합니다 . 결과 문자열의 길이를 지정하려면 정수를 전달하십시오.
Slava Fomin II

고마워 그것은 나를 위해 작동하지만 Custom Alphabet하지 않았다. 반향 할 때 빈 출력이 나타납니다. 어쨌든 나는 두 번째 예제의 사용법이 무엇인지조차 확실하지 않으므로 Custom Alphabet첫 번째 예제를 그대로 유지한다고 생각합니다. 감사.
sg552

1
프로젝트가 무작위로 생성 된 코드에 크게 의존하지 않는 한 대부분의 시나리오에서
훌륭

1
네, 근사하지만 과잉, 특히 PHP 5.7에서는 더 이상 사용되지 않습니다.
Andrew

39

나는 늦었지만 Scott의 답변에서 제공하는 기능을 기반으로 한 좋은 연구 데이터가 있습니다. 그래서이 5 일 동안 자동화 된 테스트를 위해 Digital Ocean 드롭 릿을 설정하고 생성 된 고유 한 문자열을 MySQL 데이터베이스에 저장했습니다.

이 테스트 기간 동안 5 개의 다른 길이 (5, 10, 15, 20, 50)를 사용했으며 각 길이마다 +/- 50 만 개의 레코드가 삽입되었습니다. 내 테스트 중에는 5 백만 길이에서 +/- 3K 복제본 만 0.5 백만을 생성했으며 나머지 길이는 복제본을 생성하지 않았습니다. 따라서 Scott의 함수에 길이가 15 이상인 경우 신뢰성이 높은 고유 한 문자열을 생성 할 수 있습니다. 내 연구 데이터를 보여주는 표는 다음과 같습니다.

여기에 이미지 설명을 입력하십시오

업데이트 : 토큰을 JSON 응답으로 반환하는 이러한 함수를 사용하여 간단한 Heroku 앱을 만들었습니다. 앱은 https://uniquestrings.herokuapp.com/api/token?length=15 에서 액세스 할 수 있습니다.

이게 도움이 되길 바란다.


33

UUID (Universally Unique Identifier)를 사용할 수 있으며 사용자 인증 문자열에서 지불 트랜잭션 ID에 이르기까지 모든 용도로 사용할 수 있습니다.

UUID는 16 옥텟 (128 비트) 숫자입니다. 정식 형식으로 UUID는 32 개의 16 진수로 표시되며 하이픈으로 구분 된 5 개의 그룹으로 표시되며 총 8 자 (32 자의 영숫자 및 4 개의 하이픈)로 8-4-4-4-12 형식으로 하이픈으로 구분됩니다.

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

}

// 전화하기

$transationID = generate_uuid();

일부 출력 예는 다음과 같습니다.

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

그것이 미래에 누군가를 돕기를 바랍니다 :)


환상적이고 내 목록에 추가되었습니다!
Mustafa Erdogan

32

이 함수는 숫자와 문자를 사용하여 임의의 키를 생성합니다.

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

출력 예 :

zsd16xzv3jsytnp87tk7ygv73k8zmr0ekh6ly7mxaeyeh46oe8

6
잠시 후 같은 숫자에 도달
Sharpless512

1
이것은 같은 chacater를 두 번 이상 가질 수 없기 때문에 완전히 무작위가 아닙니다.
EricP

16

나는이 하나의 라이너를 사용합니다 :

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

여기서 length는 원하는 문자열의 길이입니다 (4로 나눌 수 있음, 그렇지 않으면 4로 나눌 수있는 가장 가까운 숫자로 내림 됨)


6
항상 영숫자 문자 만 반환하는 것은 아닙니다. 다음과 같은 문자를 포함 할 수 있습니다.==
user3459110

1
URL에서 사용하는 경우 base64url_encode대신 사용할 수 있습니다. php.net/manual/en/function.base64-encode.php
Paul

9

아래 코드를 사용하여 난수 11자를 생성하거나 요구 사항에 따라 숫자를 변경하십시오.

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

또는 사용자 정의 함수를 사용하여 난수를 생성 할 수 있습니다

 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
문자열 "aaaaaaaaaaa"또는 "aaaaabbbbbb"를 생성 할 수 없습니다. 알파벳의 무작위 순열의 하위 문자열을 선택합니다. 11 자 길이의 문자열에는 V (11,35) = 288 개의 가능한 값만 있습니다. 문자열이 고유 할 것으로 예상되면 이것을 사용하지 마십시오!
kdojeteri

@Peping 그렇다면substr(str_shuffle(str_repeat('0123456789abcdefghijklmnopqrstvwxyz', 36)), 0, 11);
팀 홀먼

7
  1. 선호하는 난수 생성기를 사용하여 난수 생성
  2. 곱하고 나누면 코드 알파벳의 문자 수와 일치하는 숫자를 얻습니다.
  3. 해당 색인의 항목을 코드 알파벳으로 가져옵니다.
  4. 원하는 길이가 될 때까지 1)부터 반복하십시오.

예 (의사 코드로)

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

이론적으로 말하자면, 잠재적으로 동일한 문자열을 두 번 이상 생성 할 수 없습니까?
frezq

4

최고의 고유 ID 생성기가 있습니다. 내가 만든

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

원하는대로 ID에 대한 'var'을 에코 할 수 있습니다. 그러나 $ mdun이 더 낫습니다. 더 나은 코드를 위해 md5를 sha1로 바꿀 수는 있지만 너무 길면 필요하지 않을 수 있습니다.

감사합니다.


7
이 경우 임의의 작성된 코드로 임의성이 보장됩니다.
Daniel Kucal

3
예, 이것은 표준이 아닌 모호한 코드이기 때문에 일종의 "무작위"입니다. 이것은 예측하기 어렵지만 실제로는 안전하지 않은 부분을 사용하여 난수를 생성합니다. 따라서 결과는 기술적으로 무작위이거나 안전하지 않습니다.
Philipp

4

정말 임의의 문자열의 경우 사용할 수 있습니다

<?php

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

출력 :

40a29479ec808ad4bcff288a48a25d5c

따라서 정확히 동시에 여러 번 문자열을 생성하려고해도 다른 출력을 얻을 수 있습니다.


4

임의의 비밀번호를 생성하려고 할 때 다음을 수행하려고합니다.

  • 먼저 암호로 안전한 임의 바이트 세트를 생성하십시오.

  • 두 번째는 임의의 바이트를 인쇄 가능한 문자열로 바꾸는 것입니다.

이제 PHP에서 무작위 바이트를 생성하는 여러 가지 방법이 있습니다.

$length = 32;

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

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

그런 다음이 임의의 바이트를 인쇄 가능한 문자열로 바꾸고 싶습니다.

bin2hex 를 사용할 수 있습니다 .

$string = bin2hex($bytes);

또는 base64_encode :

$string = base64_encode($bytes);

그러나 base64를 사용하는 경우 문자열 길이를 제어하지 않습니다. bin2hex를 사용하여 그렇게 할 수 있습니다 .32 바이트 를 사용 하면 64 문자 문자열 로 바뀝니다 . 그러나 EVEN 문자열 에서만 작동 합니다.

그래서 기본적으로 당신은 할 수 있습니다 :

$length = 32;

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

$string = bin2hex($bytes);

3

내가 사용하는 것은 다음과 같습니다.

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

문자와 숫자 (영숫자)가 포함 된 임의의 문자열을 생성 할 수있는 간단한 기능입니다. 문자열 길이를 제한 할 수도 있습니다. 이 임의의 문자열은 추천 코드, 프로모션 코드, 쿠폰 코드를 포함한 다양한 목적으로 사용할 수 있습니다. 함수는 다음 PHP 함수에 의존합니다 : 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

이전 예제를 읽은 후에 나는 이것을 생각해 냈습니다.

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]의 10 배를 복제하고 요소를 섞습니다. substr ()에 대한 임의의 시작점이 더 '크리에이티브'가 된 후 [az]와 다른 요소를 배열에 추가 할 수 있습니다. 다소, 나보다 창의적


1

확인 링크를 다룰 때 해시 키를 사용하고 싶습니다. Microtime을 기반으로 해시되므로 키가 동일 해야하는 이유가 없기 때문에 MD5를 사용하는 microtime 및 hashing을 사용하는 것이 좋습니다.

  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;

}

?>

위의 함수는 11 자 길이의 임의의 문자열을 생성합니다.


1

PHP에서 고유 한 문자열을 생성하려면 다음을 시도하십시오.

md5(uniqid().mt_rand());

이것에서

uniqid()-고유 한 문자열을 생성합니다. 이 함수는 타임 스탬프 기반 고유 식별자를 문자열로 반환합니다.

mt_rand() -난수를 생성하십시오.

md5() -해시 문자열을 생성합니다.


0

스캇, 예, 당신은 매우 쓰고 좋은 해결책입니다! 감사.

또한 각 사용자에 대해 고유 한 API 토큰을 생성해야합니다. 다음은 내 접근 방식입니다. 사용자 정보 (사용자 ID 및 사용자 이름)를 사용했습니다.

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

개선 사항이 있으면 알려주세요. 감사


0

다음은 내 프로젝트 중 하나에서 사용하고 있으며 훌륭하게 작동하며 고유 한 RANDOM 토큰을 생성합니다 .

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

이 토큰이 어떻게 생성되는지 궁금해하는 사용자를 혼란스럽게 만들기 위해 타임 스탬프에 3을 곱했습니다.)

나는 그것이 도움이되기를 바랍니다 :)


1
사운드가 난처 통해 보안과 같은 "나는 사용자가이 토큰이 생성되는 방법을 궁금해 수 있습니다 누구를위한 혼란을 만드는 세 가지로 타임 스탬프를 곱한 유의하시기 바랍니다" stackoverflow.com/questions/533965/...
해리

타임 스탬프가 생성 된 임의의 문자열에 추가되므로 "난독 화를 통한 보안"이 아니며, 이것이 반환하는 실제 최종 문자열입니다.)
Kaszoni Ferencz


0

이 두 줄의 코드를 사용하여 약 10000000 번 반복 테스트 한 고유 문자열을 생성 할 수 있습니다

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

0

나는 항상 내 함수를 사용하여 사용자 정의 임의의 영숫자 문자열을 생성합니다 ... 도움이되기를 바랍니다.

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

예를 들면 다음과 같습니다. Y1FypdjVbFCFK6Gh9FDJpe6dciwJEfV6MQGpJqAfuijaYSZ86g

다른 문자열과 비교하여 고유 한 시퀀스인지 확인하려면이 트릭을 사용할 수 있습니다 ...

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

두 개의 고유 한 문자열을 생성합니다.

qsBDs4JOoVRfFxyLAOGECYIsWvpcpMzAO9pypwxsqPKeAmYLOi

Ti3kE1WfGgTNxQVXtbNNbhhvvapnaUfGMVJecHkUjHbuCb85pF

희망이 당신이 찾고있는 것입니다 ...


0

간단한 해결책은 영숫자가 아닌 문자를 삭제하여 base 64를 영숫자로 변환하는 것입니다.

이것은 암호로 안전한 결과를 위해 random_bytes ()를 사용합니다.

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

나는 기존의 모든 아이디어의 문제는 아마도 독특하지만 확실히 독특 하지 않다는 것입니다 (Dariusz Walczak의 loletech에 대한 답변에서 지적했듯이). 실제로 독창적 인 솔루션이 있습니다. 스크립트에는 일종의 메모리가 필요합니다. 나에게 이것은 SQL 데이터베이스입니다. 어딘가에 파일에 간단히 쓸 수도 있습니다. 두 가지 구현이 있습니다.

첫 번째 방법 : 고유성을 제공하는 1이 아닌 2 개의 필드를 사용하십시오. 첫 번째 필드는 무작위는 아니지만 고유 한 ID 번호입니다 (첫 번째 ID는 1, 두 번째는 2입니다 ...). SQL을 사용하는 경우 AUTO_INCREMENT 특성으로 ID 필드를 정의하십시오. 두 번째 필드는 고유하지 않지만 무작위입니다. 이것은 사람들이 이미 언급 한 다른 기술로 생성 할 수 있습니다. Scott의 아이디어는 좋지만 md5는 편리하고 대부분의 목적에 충분할 것입니다.

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

두 번째 방법 : 기본적으로 동일한 아이디어이지만 처음에는 생성 될 최대 문자열 수를 선택합니다. 이것은 1 조와 같이 정말 큰 숫자 일 수 있습니다. 그런 다음 동일한 작업을 수행하고 ID를 생성하지만 모든 ID가 동일한 자릿수를 갖도록 0을 채 웁니다. 그런 다음 ID를 임의의 문자열로 연결하십시오. 그것은 대부분의 목적을 위해 무작위로 이루어 지지만, ID 섹션은 또한 그것이 고유하다는 것을 보장 할 것입니다.


-1

이 코드를 사용할 수 있습니다. 도움이 되길 바랍니다.

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에서 임의 코드 생성기에 대한 세부 사항


-2

불필요하게 속도가 느려지고 openssl_random_pseudo_bytes를 한 번만 호출하는 것보다 더 안전하지 않은 불필요한 루프를 제거하여 위의 Scotts 코드 단순화

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

불행히도 이것이 crypto_rand_secure 함수의 적절한 단순화라는 것에 동의하지 않습니다. 임의로 생성 된 숫자의 결과를 가져온 다음 범위를 나누는 숫자로 변조 할 때 발생하는 모듈러스 바이어스를 피하려면 루프가 필요합니다. en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle#Modulo_bias . 루프를 사용하여 범위를 벗어난 숫자를 버리고 새 숫자를 선택하면 이러한 편견을 피할 수 있습니다. stackoverflow.com/questions/10984974/…
Scott

@ Scott, 그 게시물은 rand ()에 관한 것입니다. 그러나이 경우 openssl_random_pseudo_bytes에 의해 이미 처리되었으므로 불필요한 루프를 반복하십시오.
mabel

1
gist.github.com/anonymous/87e3ae6fd3320447f46b973e75c2ea85- 이 스크립트를 실행하십시오. 결과 분포가 무작위가 아님을 알 수 있습니다. 0-55 사이의 숫자는 56-100 사이의 숫자보다 더 높습니다. openssl이 문제를 일으키는 것은 아닙니다. 리턴 명령문의 모듈러스 바이어스 때문입니다. 100 (범위)은 255 (1 바이트)를 균등하게 나누지 않으며 이러한 결과를 발생시킵니다. 귀하의 답변에 대한 가장 큰 문제는 루프를 사용하는 것만 큼 기능이 안전하다는 것입니다. crypto_rand_secure의 구현은 암호화 적으로 안전하지 않으며 오해의 소지가 있습니다.
Scott

@Scott, 우리는 여기서 돌아갑니다. 마지막 return statement에 관한 것이 아니며 modulo를 사용하지 않고 openssl_random_pseudo_bytes의 return value에서 점진적으로 계산할 수 있습니다. 내가 만들고있는 요점은 openssl_random_pseudo_bytes가 임의의 바이트를 반환하면 루프가 필요 없다는 것입니다. 루프를 만들면 더 안전하게 만들지 않고 느리게 만듭니다.
mabel

2
이 답변은 잘못된 정보를 전파합니다. 루프가 openssl더 안전 하지 않다는 것이 맞지만, 더 중요한 것은 루프가 덜 안전하지 않다는 것입니다. 위의 코드는 완벽하게 좋은 임의의 숫자를 취하고 더 낮은 숫자로 바이어스하여 엉망으로 만듭니다. 루프를 제거하여 더 빠르지 만 CSPRNG가 아니라고 답변에 고지 사항을 표시하면이 문제가 해결됩니다. 암호화를 좋아한다면 사용자 에게이 기능의 출력이 바이어스 될 수 있으며 동등한 솔루션 이 아니라는 것을 알려주십시오 . 루프는 단지 당신을 귀찮게하는 것이 아닙니다.
Scott
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.