UFO ET IT

PHP를 사용하여 임의의 문자열을 만드는 방법은 무엇입니까?

ufoet 2020. 12. 13. 10:00
반응형

PHP를 사용하여 임의의 문자열을 만드는 방법은 무엇입니까?


PHP의 rand 함수가 임의의 정수를 생성한다는 것을 알고 있지만 다음과 같은 임의의 문자열을 생성하는 가장 좋은 방법은 무엇입니까?

원래 문자열, 9 자

$string = 'abcdefghi';

6 자로 제한되는 임의 문자열의 예

$string = 'ibfeca';

업데이트 : 나는 이러한 유형의 기능을 많이 발견했으며 기본적으로 각 단계의 논리를 이해하려고 노력하고 있습니다.

업데이트 : 함수는 필요한만큼의 문자를 생성해야합니다.

답장을 보내 주시면 댓글을 남겨주세요.


글쎄, 당신은 내가 내 의견에서 물었던 모든 질문을 명확히하지 않았지만, 나는 당신이 "가능한"문자의 문자열과 반환 할 문자열의 길이를 취할 수있는 함수를 원한다고 가정 할 것이다. 명확성을 위해 평소보다 더 많은 변수를 사용하여 요청에 따라 철저하게 주석을 달았습니다.

function get_random_string($valid_chars, $length)
{
    // start with an empty random string
    $random_string = "";

    // count the number of chars in the valid chars string so we know how many choices we have
    $num_valid_chars = strlen($valid_chars);

    // repeat the steps until we've created a string of the right length
    for ($i = 0; $i < $length; $i++)
    {
        // pick a random number from 1 up to the number of valid chars
        $random_pick = mt_rand(1, $num_valid_chars);

        // take the random character out of the string of valid chars
        // subtract 1 from $random_pick because strings are indexed starting at 0, and we started picking at 1
        $random_char = $valid_chars[$random_pick-1];

        // add the randomly-chosen char onto the end of our string so far
        $random_string .= $random_char;
    }

    // return our finished random string
    return $random_string;
}

예제 데이터로이 함수를 호출하려면 다음과 같이 호출합니다.

$original_string = 'abcdefghi';
$random_string = get_random_string($original_string, 6);

이 함수는 전달 된 유효한 문자의 고유성을 확인하지 않습니다. 예를 들어 유효한 문자 문자열을 사용하여 호출 'AAAB'한 경우 각 문자에 대해 A를 B로 선택할 가능성이 3 배 더 높습니다. 필요에 따라 버그 나 기능으로 간주 될 수 있습니다.


문자의 반복적 인 발생을 허용하려면 다음 기능을 사용할 수 있습니다.

function randString($length, $charset='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789')
{
    $str = '';
    $count = strlen($charset);
    while ($length--) {
        $str .= $charset[mt_rand(0, $count-1)];
    }
    return $str;
}

기본 알고리즘은 0에서 < 문자 수 > − 1 사이의 임의의 숫자를 < length > 곱하여 생성 하는 것입니다. 우리는 집합에서 문자를 선택하고 해당 문자를 연결하는 인덱스로 사용합니다. 0 및 < 문자 수 > − 1 경계는 첫 번째 문자가로 지정 되고 마지막 문자가로 지정 될 때 문자열 의 경계를 나타냅니다 .$charset$charset[0]$charset[count($charset) - 1]


내가 좋아하는 것:

 echo substr(md5(rand()), 0, 7);

그래서 USE A LIBRARY 라고 말하면서 시작하겠습니다 . 많은 것이 존재합니다.

문제의 핵심은이 페이지의 거의 모든 답변이 공격에 취약하다는 것입니다. mt_rand(), rand(), lcg_value()그리고 uniqid()모두 공격에 취약합니다 .

좋은 시스템은 /dev/urandom파일 시스템에서 사용하거나 mcrypt_create_iv()(와 함께 MCRYPT_DEV_URANDOM) 또는 openssl_pseudo_random_bytes(). 위의 모든 것이 수행됩니다. PHP 7은 두 가지 새로운 기능과 함께 올 것이다 random_bytes($len) 그리고 random_int($min, $max)그도 안전합니다.

대부분의 이러한 함수 (제외 random_int())는 "원시 문자열"을 반환하므로에서 ASCII 문자를 포함 할 수 있습니다 0 - 255. 인쇄 가능한 문자열을 원한다면 .NET을 통해 결과를 실행하는 것이 좋습니다 base64_encode().


function generate_random_string($name_length = 8) {
    $alpha_numeric = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    return substr(str_shuffle(str_repeat($alpha_numeric, $name_length)), 0, $name_length);
}

아래 댓글에서 mzhang 의 훌륭한 제안에 따라 코드를 업데이트했습니다 .


@taskamiski의 우수한 답변의 더 나은 업데이트 버전 :

mt_rand()대신 사용 하는 더 나은 버전 rand():

echo md5(mt_rand()); // 32 char string = 128bit

더 좋은 것은 긴 문자열의 경우 hash()해싱 알고리즘을 선택할 수 있는 함수를 사용하는 것입니다.

echo hash('sha256', mt_rand()); // 64 char string
echo hash('sha512', mt_rand()); // 128 char string

결과를 50 자로 줄이려면 다음과 같이하십시오.

echo substr(hash('sha256', mt_rand()), 0, 50); // 50 char string

끝에서 문자를 결합하는 것이 반복되는 문자열 연결보다 더 효율적이어야합니다.

편집 # 1 : 문자 반복을 방지하는 옵션이 추가되었습니다.

편집 # 2 : $ norepeat가 선택되고 $ len이 선택할 문자 집합보다 큰 경우 무한 루프에 들어 가지 않도록 예외를 throw합니다.

편집 # 3 : 연관 배열 키 조회가 배열을 선형으로 검색하는 것보다 빠르기 때문에 $ norepeat를 선택하면 선택한 임의의 문자를 저장하기 위해 배열 키를 사용합니다.

function rand_str($len, $norepeat = true)
{
    $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    $max = strlen($chars) - 1;

    if ($norepeat && len > $max + 1) {
        throw new Exception("Non repetitive random string can't be longer than charset");
    }

    $rand_chars = array();

    while ($len) {
        $picked = $chars[mt_rand(0, $max)];

        if ($norepeat) {
            if (!array_key_exists($picked, $rand_chars)) {
                $rand_chars[$picked] = true;
                $len--;
            }
        }
        else {
            $rand_chars[] = $picked;
            $len--;
        }
    }

    return implode('', $norepeat ? array_keys($rand_chars) : $rand_chars);   
}

이것은 임의의 문자열을 생성합니다

function generateRandomString($length=10) {
    $original_string = array_merge(range(0,9), range('a','z'), range('A', 'Z'));
    $original_string = implode("", $original_string);
    return substr(str_shuffle($original_string), 0, $length);
}
echo generateRandomString(6);

여기에 내 공헌도 추가 할 것 같습니다.

function random_string($length) {
    $bytes_1 = openssl_random_pseudo_bytes($length);
    $hex_1 = bin2hex($bytes_1);
    $random_numbers = substr(sha1(rand()), 0, $length);
    $bytes_2 = openssl_random_pseudo_bytes($length);
    $hex_2 = bin2hex($bytes_2);
    $combined_chars = $hex_1 . $random_numbers . $hex_2;
    $chars_crypted = hash('sha512', $combined_chars);

    return $chars_crypted;
}

감사


이에 대한 대부분의 측면은 이미 논의되었지만 약간의 업데이트를 권장합니다. 소매 용으로 사용하는 경우 ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 도메인을 피할 것입니다.

대신 사용 : ABCDEFGHJKMNPQRSTUVWXY3456789

물론, 문자 수가 훨씬 적지 만 고객이 0을 O로, 1을 l로, 2를 Z로 착각 할 수 없기 때문에 많은 번거 로움을 줄일 수 있습니다. 또한 입력에 대해 UPPER를 수행 할 수 있으며 고객은 대문자 나 소문자를 입력하세요. 비슷해 보일 수 있기 때문에 혼동되기도합니다.


무엇을 위해 임의의 문자열이 필요합니까?

암호와 유사한 원격지에이 정보가 사용됩니까?

당신의 임의의 문자열이 필요로하는 경우 어떤 모두의 보안 속성을, 당신은 PHP 7의 사용해야하는 random_int()대신 모든 불안의 기능을 mt_rand()이 스레드에 대한 답변.

/**
 * Generate a random string
 * 
 * @link https://paragonie.com/b/JvICXzh_jhLyt4y3
 *
 * @param int $length - How long should our random string be?
 * @param string $charset - A string of all possible characters to choose from
 * @return string
 */
function random_str($length = 32, $charset = 'abcdefghijklmnopqrstuvwxyz')
{
    // Type checks:
    if (!is_numeric($length)) {
        throw new InvalidArgumentException(
            'random_str - Argument 1 - expected an integer'
        );
    }
    if (!is_string($charset)) {
        throw new InvalidArgumentException(
            'random_str - Argument 2 - expected a string'
        );
    }

    if ($length < 1) {
        // Just return an empty string. Any value < 1 is meaningless.
        return '';
    }
    // This is the maximum index for all of the characters in the string $charset
    $charset_max = strlen($charset) - 1;
    if ($charset_max < 1) {
        // Avoid letting users do: random_str($int, 'a'); -> 'aaaaa...'
        throw new LogicException(
            'random_str - Argument 2 - expected a string at least 2 characters long'
        );
    }
    // Now that we have good data, this is the meat of our function:
    $random_str = '';
    for ($i = 0; $i < $length; ++$i) {
        $r = random_int(0, $charset_max);
        $random_str .= $charset[$r];
    }
    return $random_str;
}

당신이 (이이 글을 쓰는로 출시되지 않았기 때문에, 아마 어떤 경우인지) 아직 PHP 7에없는 경우에, 당신은 할 것 paragonie / random_compat 의 유저 랜드 구현되는, random_bytes()그리고 random_int()PHP 5 프로젝트가.

보안 컨텍스트의 경우, 항상 사용 random_int()하지 rand(), mt_rand() 을 참조 ircmaxell의 답변을 뿐만 아니라.


// @author http://codeascraft.etsy.com/2012/07/19/better-random-numbers-in-php-using-devurandom/                                                
function devurandom_rand($min = 0, $max = 0x7FFFFFFF)
{
    $diff = $max - $min;
    if ($diff < 0 || $diff > 0x7FFFFFFF) {
        throw new RuntimeException('Bad range');
    }
    $bytes = mcrypt_create_iv(4, MCRYPT_DEV_URANDOM);
    if ($bytes === false || strlen($bytes) != 4) {
        throw new RuntimeException('Unable to get 4 bytes');
    }
    $ary = unpack('Nint', $bytes);
    $val = $ary['int'] & 0x7FFFFFFF; // 32-bit safe                           
    $fp = (float) $val / 2147483647.0; // convert to [0,1]                          
    return round($fp * $diff) + $min;
}

function build_token($length = 60, $characters_map = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789') {
    $map_length = mb_strlen($characters_map)-1;
    $token = '';
    while ($length--) {
        $token .= mb_substr($characters_map, devurandom_rand(0,$map_length),1);
    }
    return $token;
}

이것은 PHP가 .NET으로 컴파일 된 UNIX 환경에서만 작동합니다 mcrypt.


원래 문자를 임의로 순열하여 비밀번호를 만드시겠습니까? 고유 한 문자 만 포함해야합니까?

rand색인으로 임의의 문자를 선택하는 데 사용 합니다.


이것은 오래된 질문이지만 내 솔루션을 게시하려고합니다 ... 저는 항상이 함수를 사용하여 사용자 정의 임의의 영숫자 문자열을 생성합니다 ...

<?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;
  }
  $test = random_alphanumeric(50); // 50 characters
  echo $test;
?>

테스트 : UFOruSSTCPIqxTRIIMTRkqjOGidcVlhYaS9gtwttxglheVugFM

두 개 이상의 고유 한 문자열이 필요한 경우이 트릭을 사용할 수 있습니다.

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

$ string_1 : tMYicqLCHEvENwYbMUUVGTfkROxKIekEB2YXx5FHyVByp3mlJO

$ string_2 : XdMNJYpMlFRKFDlF6GhVn6jsBVNQ1BCCevj8yK2niFOgpDI2MU

도움이 되었기를 바랍니다.


echo substr(bin2hex(random_bytes(14)), 0, $length);

이 코드는 바이너리에서 16 진수로 변환 된 임의의 바이트를 가져 와서 $ length 변수에 넣으면이 16 진수 문자열의 하위 문자열을받습니다.


이 시도

충분히 간단합니다!

function RandomFromCharset($charset,$length) 
{

$characters = $charset; // your existing charset / defined string
    $charactersLength = strlen($characters);
    $random_from_charset = '';
    for ($i = 0; $i < $length; $i++) 
    {
        $random_from_charset.= $characters[rand(0, $charactersLength - 1)];
    }

return random_from_charset;
}

다음과 같이 함수를 호출하십시오.

RandomFromCharset($charset,$length);

where $length will be length of random string you want (this can be predefined also in the function as RandomFromCharset(charset,$length=10) ) to generate and $charset will be your existing string to which you want to restrict the characters.


you could make an array of characters then use rand() to pick a letter from the array and added it to a string.

$letters = array( [0] => 'a' [1] => 'b' [2] => 'c' [3] => 'd' ... [25] = 'z');

$lengthOfString = 10;
$str = '';

while( $lengthOfString-- )
{
   $str .= $letters[rand(0,25)];
}
echo $str;

*note that this does allow repeat characters


This builds on Gumbo's solution by adding functionality to list a set of characters to be skipped in the base character set. The random string selects characters from $base_charset which do not also appear in $skip_charset.

/* Make a random string of length using characters from $charset, excluding $skip_chars.
 * @param length (integer) length of return value
 * @param skip_chars (string) characters to be excluded from $charset
 * @param charset (string) characters of posibilities for characters in return val
 * @return (string) random string of length $length    */
function rand_string(
        $length, 
        $skip_charset = '', 
        $base_charset='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'){
  $skip_len = strlen($skip_charset);
  for ($i = 0; $i<$skip_len; $i++){
    $base_charset = str_replace($skip_charset[$i], '', $base_charset);
  }
  cvar_dump($base_charset, '$base_charset after replace');
  $str = '';
  $count = strlen($base_charset);
  while ($length--) {
    $str .= $base_charset[mt_rand(0, $count - 1)];
  }
  return $str;
}

Here are some usage examples. The first two examples use the default value for $base_charset. The last example explicitly defines $base_charset.

echo rand_string(15, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz');
//  470620078953298
echo rand_string(8, 'abcdefghijklmnopqrstuvwxyz0123456789');
//  UKLIHOTFSUZMFPU
echo rand_string(15, 'def', 'abcdef');
//  cbcbbccbabccaba

well, I was looking for a solution, and I kindda used @Chad Birch's solution merged with @Gumbo's one. This is what I came up with:

function get_random_string($length, $valid_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz123456790!·$%&/()=?¿¡',.-;:+*`+´ç")
{
    $random_string = "";
    $num_valid_chars = strlen($valid_chars);
    for ($i = 0; $i < $length; $i++, $random_string .= $valid_chars[mt_rand(1, $num_valid_chars)-1]);
    return $random_string;
}

I think comments are pretty much unnecesary since the answers I used to build up this one are already thoroughly commented. Cheers!


If you're not concerned about time, memory, or cpu efficiency, and if your system can handle it, why not give this algorithm a try?!

function randStr($len, $charset = 'abcdABCD0123') {
    $out = '';
    $str = array();

    for ($i = 0; $i < PHP_INT_MAX; $i++) {
        $str[$i] = $charset;

        shuffle($str);
        $charset .= implode($charset, $str);
        $charset = str_shuffle($charset);
    }

    $str = array_flip($str);
    $str = array_keys($str);

    for ($i = 0; $i < PHP_INT_MAX; $i++) {
        shuffle($str);
    }

    $str = implode('', $str);

    for ($i = 0; $i < strlen($str); $i++) {
        $index = mt_rand(1, strlen($str));
        $out .= $str[$index - 1];
    }

    for ($i = 0; $i < PHP_INT_MAX; $i++) {
        $out = str_shuffle($out);
    }

    return substr($out, 0, $len);
}

Maybe this will read better if it uses recursion, but I'm not sure if PHP uses tail recursion or not...

참고URL : https://stackoverflow.com/questions/853813/how-to-create-a-random-string-using-php

반응형