450

検証リンクで使用するために、数字と文字を使用してランダムで一意の文字列を生成するにはどうすればよいでしょうか? たとえば、Web サイトでアカウントを作成すると、リンクが記載されたメールが送信され、アカウントを確認するにはそのリンクをクリックする必要があります。

PHPを使用してそれらの1つを生成するにはどうすればよいですか?

4

30 に答える 30

619

PHP 7 標準ライブラリは、random_bytes($length)暗号的に安全な疑似ランダム バイトを生成する関数を提供します。

例:

$bytes = random_bytes(20);
var_dump(bin2hex($bytes));

上記の例では、次のようなものが出力されます。

string(40) "5fe69c95ed70a9869d9f9af7d8400a6673bb9ce9"

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

PHP 5 (古い)

この同じ問題を解決する方法を調べていましたが、パスワードの取得にも使用できるトークンを関数で作成したいと考えています。これは、トークンが推測される能力を制限する必要があることを意味します。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

ソース: http://us1.php.net/manual/en/function.openssl-random-pseudo-bytes.php#104322

于 2012-12-05T22:25:00.530 に答える
338

セキュリティ通知: このソリューションは、ランダム性の品質がアプリケーションのセキュリティに影響を与える可能性がある状況では使用しないでください。特に、rand()uniqid()は、暗号的に安全な乱数ジェネレーターではありません。安全な代替手段については、スコットの回答を参照してください。

時間の経過とともに完全に一意である必要がない場合:

md5(uniqid(rand(), true))

それ以外の場合 (ユーザーの一意のログインを既に決定している場合):

md5(uniqid($your_user_login, true))
于 2009-12-04T10:55:45.187 に答える
100

最も支持されたソリューションのオブジェクト指向バージョン

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

それが誰かを助けることを願っています。乾杯!

于 2014-06-04T09:46:24.427 に答える
45

UUID (Universally Unique Identifier) を使用でき、ユーザー認証文字列から支払いトランザクション ID まで、あらゆる目的に使用できます。

UUID は 16 オクテット (128 ビット) の数値です。標準形式では、UUID は 32 桁の 16 進数で表され、ハイフンで区切られた 5 つのグループに分けられ、8-4-4-4-12 の形式で合計 36 文字 (32 文字の英数字と 4 つのハイフン) で表されます。

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

将来誰かに役立つことを願っています:)

于 2016-08-11T13:38:46.400 に答える
35

この関数は、数字と文字を使用してランダム キーを生成します。

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
于 2012-09-24T18:16:44.273 に答える
18

私はこのワンライナーを使用します:

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

ここで、length は目的の文字列の長さです (4 で割り切れます。それ以外の場合は、4 で割り切れる最も近い数値に切り捨てられます)。

于 2014-10-12T03:07:38.043 に答える
13

以下のコードを使用して、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);
于 2016-12-05T12:54:51.267 に答える
8
  1. お気に入りの乱数ジェネレーターを使用して乱数を生成します
  2. 掛け算と割り算で、コードのアルファベットの文字数と一致する数を取得します
  3. コード アルファベットのそのインデックスにある項目を取得します。
  4. 1)から好みの長さになるまで繰り返す

例 (疑似コード)

int myInt = random(0, numcharacters)
char[] codealphabet = 'ABCDEF12345'
char random = codealphabet[i]
repeat until long enough
于 2009-12-04T10:52:52.643 に答える
7

本当にランダムな文字列の場合、次を使用できます

<?php

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

出力:

40a29479ec808ad4bcff288a48a25d5c

そのため、まったく同時に文字列を複数回生成しようとしても、異なる出力が得られます。

于 2018-05-11T13:28:56.247 に答える
2

検証リンクを扱うときは、ハッシュ キーを使用するのが好きです。マイクロタイムに基づいてハッシュするため、キーが同じである必要がある理由はないため、MD5 を使用するマイクロタイムとハッシュを使用することをお勧めします。

  1. $key = md5(rand());
  2. $key = md5(microtime());
于 2016-03-07T04:58:17.327 に答える
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();
    }

 }
于 2014-01-08T12:20:57.460 に答える
2

これが究極のユニーク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に置き換えてコードを改善できますが、それは非常に長くなり、必要ない場合があります。

ありがとうございました。

于 2013-07-17T23:08:58.917 に答える
2

コップ一杯の水で窒息しているこの人々...

$random= substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*.-_"), 0, 10);

単純。このランダムな文字列の繰り返しの可能性は 0,00000000000000000000000000001^70 です

于 2021-06-27T00:02:59.287 に答える
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]およびその他の要素を配列に追加して、複製することができます多かれ少なかれ、私よりも創造的である

于 2015-02-25T16:09:48.910 に答える
1

私は常にこの関数を使用して、カスタムのランダムな英数字文字列を生成します...これが役立つことを願っています。

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

たとえば、次のように生成されます。

別の文字列と比較して、それが一意のシーケンスであることを確認する場合は、このトリックを使用できます...

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

2 つの一意の文字列を生成します。

qsBDs4JOoVRfFxyLAOGECYIsWvpcpMzAO9pypwxsqPKeAmYLOi

Ti3keE1WfGgTNxQVXtbNNbhhvvapnaUfGMVJecHkUjHbuCb85pF

これがあなたが探しているものであることを願っています...

于 2019-03-09T18:58:25.897 に答える