ChatGPT解决这个技术问题 Extra ChatGPT

如何生成随机的、唯一的字母数字字符串?

如何使用数字和字母生成随机的唯一字符串以用于验证链接?就像您在网站上创建帐户时,它会向您发送一封带有链接的电子邮件,您必须单击该链接才能验证您的帐户

如何使用 PHP 生成其中之一?

您所需要的只是字符串和均匀分布的随机数。
嘿 Andrew,您应该选择 Scott 作为正确答案。 Scott 正在使用 OpenSSL 的加密安全伪随机数生成器 (CSPRNG),它将根据您的平台选择最安全的熵源。
请在 2015 年之后阅读此内容的任何人,请看这里:paragonie.com/blog/2015/07/… 大多数热门答案或多或少都有缺陷......
OpenSSL 和 uniqid 不安全。使用 Random::alphanumericString($length)Random::alphanumericHumanString($length) 之类的内容。

g
gagarine

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] 的字母表,但它可以工作。

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


同意。明文密码存储很糟糕! (我使用河豚。)但是在生成令牌后,它允许令牌持有者重置密码,因此令牌在有效时与密码等效(并被视为有效)。
嘿,我将您出色的代码与方便的 Kohana Text::random() 方法功能相结合,并创建了以下要点:gist.github.com/raveren/5555297
完美的!我用 10 个字符作为长度对其进行了测试。 100000 个令牌,仍然没有重复!
我使用了这个过程,发现它超级慢。长度为 36 时,它在开发服务器上超时。长度为 24 仍然需要大约 30 秒。不知道我做错了什么,但对我来说太慢了,我选择了另一种解决方案。
您还可以使用 base64_encode 而不是 bin2hex 来获得具有较大字母的较短字符串。
S
Scott Arciszewski

安全注意事项:此解决方案不应用于随机性质量可能影响应用程序安全性的情况。特别是,rand() 和 uniqid() 不是密码安全的随机数生成器。请参阅 Scott 的答案以获得安全的替代方案。

如果您不需要它随着时间的推移绝对独一无二:

md5(uniqid(rand(), true))

否则(假设您已经为您的用户确定了唯一的登录名):

md5(uniqid($your_user_login, true))

两种方法都不保证唯一性 - md5 函数的输入长度大于其输出长度,并且根据 en.wikipedia.org/wiki/Pigeonhole_principle 保证碰撞。另一方面,依靠散列来获得“唯一”id 的人口越多,发生至少一次冲突的可能性就越大(参见 en.wikipedia.org/wiki/Birthday_problem)。大多数解决方案的概率可能很小,但它仍然存在。
这不是生成随机值的安全方法。见斯科特的回答。
对于相对较快过期的电子邮件确认,我认为一个人有一天可能会确认其他人的电子邮件的可能性很小,这种风险可以忽略不计。但是您总是可以在创建令牌后检查数据库中是否已经存在令牌,如果是这样,只需选择一个新的。但是,您花在编写该代码片段上的时间可能会被浪费,因为它很可能永远不会运行。
请注意 md5 返回十六进制值,这意味着字符集仅限于 [0-9] 和 [af]。
md5 可以有碰撞,你刚刚毁掉了 uniqid 的优势
S
Slava Fomin II

最受欢迎的解决方案的面向对象版本

我根据 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,你应该像上面的例子那样调用 generate 方法。只需将一个整数传递给它以指定结果字符串的长度。
谢谢它对我有用,但 Custom Alphabet 没有。当我回显时,我得到了空输出。无论如何,我什至不确定第二个示例 Custom Alphabet 有什么用,所以我想我只保留第一个示例。谢谢。
不错,但在大多数情况下相当过分,除非您的项目严重依赖随机生成的代码
是的,很好,但有点矫枉过正,特别是考虑到它现在对于 php 5.7 几乎已被弃用
h
halfer

我在这里有一些基于 Scott's answer 提供的功能的良好研究数据。所以我为这个为期 5 天的自动化测试设置了一个 Digital Ocean 液滴,并将生成的唯一字符串存储在 MySQL 数据库中。

在此测试期间,我使用了 5 种不同的长度(5、10、15、20、50),并为每个长度插入了 +/-50 万条记录。在我的测试中,只有长度 5 生成了 50 万个中的 +/-3K 重复,其余长度没有生成任何重复。所以我们可以说,如果我们使用长度为 15 或以上的 Scott 函数,那么我们可以生成高度可靠的唯一字符串。这是显示我的研究数据的表格:

https://i.stack.imgur.com/g5MsZ.png

更新

我使用这些函数创建了一个简单的 Heroku 应用程序,该应用程序将令牌作为 JSON 响应返回。该应用程序可在 https://uniquestrings.herokuapp.com/api/token?length=15 访问


为什么不简单地添加一个像 microtime() 这样的时间组件,或者在生成时简单地检查重复项?如果需求是“唯一的”,它就不可能有变化不是唯一的。不过,我很欣赏你的伟大研究,如果它不是绝对关键的话,它非常有用。
@ALZlper microtime() 无法生成加密安全字符串,如果涉及安全性,我们不能依赖它们。
当然,它不是加密安全的。这就是为什么我提到在字符串中添加基于时间的部分。重要的是添加它而不是替代您的答案。你想要更明确地说是对的。我也在不同的答案中写了类似的东西。看看:) stackoverflow.com/a/70365951/7335057
D
Developer

您可以使用 UUID(通用唯一标识符),它可以用于任何目的,从用户身份验证字符串到支付交易 ID。

UUID 是一个 16 字节(128 位)的数字。在其规范形式中,UUID 由 32 个十六进制数字表示,显示在由连字符分隔的五组中,格式为 8-4-4-4-12,总共 36 个字符(32 个字母数字字符和四个连字符)。

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

希望它对将来的人有所帮助:)


看起来棒极了,添加到我的列表中!
I
Ilmari Karonen

此函数将使用数字和字母生成随机密钥:

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

过了一会儿,你得到相同的数字
这不是完全随机的,因为它永远不会有相同的 chacater 超过一次。
D
DudeOnRock

我使用这个单线:

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

其中 length 是所需字符串的长度(可被 4 整除,否则将向下舍入为可被 4 整除的最接近的数字)


它并不总是只返回字母数字字符。它可以包含像 == 这样的字符
如果在 URL 中使用,则可以使用 base64url_encode,请参见此处:php.net/manual/en/function.base64-encode.php
S
Sahil

使用下面的代码生成 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);

这永远不会生成字符串“aaaaaaaaaaa”或“aaaaabbbbbb”。它只是选择字母表随机排列的子串。 11 个字符长的字符串只有 V(11,35) = 288 个可能的值。如果您希望字符串是唯一的,请不要使用它!
@Peping 然后做 substr(str_shuffle(str_repeat('0123456789abcdefghijklmnopqrstvwxyz', 36)), 0, 11);
谢谢你的好功能! '0123456789abcdefghijklmnopqrstvwxyzABCDEFGHIJKLMNOPQRSTVWXYZ~!@#$%^&*()_+-=<>,.?/' - 分机。 str_shuffle 范围。
E
Erik A. Brandstadmoen

使用您最喜欢的随机数生成器生成一个随机数 将其相乘并除以得到一个与您的代码字母表中的字符数匹配的数字 获取代码字母表中该索引处的项目。从 1) 重复,直到你有你想要的长度

例如(在伪代码中)

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

从理论上讲,这不能多次生成相同的字符串吗?
佚名

对于真正随机的字符串,您可以使用

<?php

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

输出:

40a29479ec808ad4bcff288a48a25d5c

因此,即使您尝试在完全相同的时间多次生成字符串,您也会得到不同的输出。


A
Arpit J.

这是一个简单的函数,可让您生成包含字母和数字(字母数字)的随机字符串。您还可以限制字符串长度。这些随机字符串可用于各种目的,包括:推荐代码、促销代码、优惠券代码。函数依赖于以下 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
*/

D
Dylan Kas

尝试生成随机密码时,您正在尝试:

首先生成一组密码安全的随机字节

其次是将这些随机字节变成可打印的字符串

现在,有多种方法可以在 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);

F
Faraz Kelhini

这是我使用的:

md5(time() . rand());    
// Creates something like 0c947c3b1047334f5bb8a3b7adc1d97b

如果有人正在寻找一个只为 dbs 播种的单班轮,那就最好了。
A
Andres Rave

这人一喝水就噎死了……

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

简单的。这个随机字符串重复的可能性是 0,000000000000000000000000000001^70


这确实可以防止多次获得一个角色。应该可以生成 10 个 a 的字符串。因此,字符串也应该重复 10 的长度。
18 条射线更有可能在 10 秒内击中你
K
Krishna Torque

这是为您提供的终极唯一 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 以获得更好的代码,但这会很长,您可能不需要。

谢谢你。


在这种情况下,随机性是由随机编写的代码保证的,对吧?
是的,这是一种“随机”,因为它是非标准的、晦涩的代码。这使得预测变得困难......但实际上它不是使用不安全的部分来生成随机数。所以结果在技术上不是随机的或安全的。
R
René Vogt

我喜欢在处理验证链接时使用哈希键。我建议使用使用 MD5 的微时间和散列,因为没有理由说明密钥应该相同,因为它基于微时间进行散列。

$key = md5(rand()); $key = md5(microtime());


p
poyynt
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();
    }

 }

a
akshaypjoshi

如果要在 PHP 中生成唯一字符串,请尝试以下操作。

md5(uniqid().mt_rand());

在这,

uniqid() - 它将生成唯一的字符串。此函数将基于时间戳的唯一标识符作为字符串返回。

mt_rand() - 生成随机数。

md5() - 它将生成哈希字符串。


L
Luiggi ZAMOL

在阅读了前面的例子后,我想出了这个:

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] 和其他元素添加到数组中,复制或多或少,比我更有创意


O
Old Ceylon Mudliar
<?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 个字符的随机字符串。


A
Alessandro

我总是使用这个我的函数来生成一个自定义的随机字母数字字符串......希望这有帮助。

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

希望这是您正在寻找的...


J
Jon Hulka

一个简单的解决方案是通过丢弃非字母数字字符将 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);
}

编辑:我刚刚重新审视了这个,因为我需要一些更灵活的东西。这是一个性能比上面更好的解决方案,并提供了指定 ASCII 字符集的任何子集的选项:

<?php
class RandomText
{
    protected
        $allowedChars,
        //Maximum index to use
        $allowedCount,
        //Index values will be taken from a pool of this size
        //It is a power of 2 to keep the distribution of values even
        $distributionSize,
        //This many characters will be generated for each output character
        $ratio;
    /**
     * @param string $allowedChars characters to choose from
     */
    public function __construct(string $allowedChars)
    {
        $this->allowedCount = strlen($allowedChars);
        if($this->allowedCount < 1 || $this->allowedCount > 256) throw new \Exception('At least 1 and no more than 256 allowed character(s) must be specified.');
        $this->allowedChars = $allowedChars;
        //Find the power of 2 equal or greater than the number of allowed characters
        $this->distributionSize = pow(2,ceil(log($this->allowedCount, 2)));
        //Generating random bytes is the expensive part of this algorithm
        //In most cases some will be wasted so it is helpful to produce some extras, but not too many
        //On average, this is how many characters needed to produce 1 character in the allowed set
        //50% of the time, more characters will be needed. My tests have shown this to perform well.
        $this->ratio = $this->distributionSize / $this->allowedCount;
    }

    /**
     * @param int $length string length of required result
     * @return string random text
     */
    public function get(int $length) : string
    {
        if($length < 1) throw new \Exception('$length must be >= 1.');
        $result = '';
        //Keep track of result length to prevent having to compute strlen()
        $l = 0;
        $indices = null;
        $i = null;
        do
        {
            //Bytes will be used to index the character set. Convert to integers.
            $indices = unpack('C*', random_bytes(ceil(($length - $l) * $this->ratio)));
            foreach($indices as $i)
            {
                //Reduce to the smallest range that gives an even distribution
                $i %= $this->distributionSize;
                //If the index is within the range of characters, add one char to the string
                if($i < $this->allowedCount)
                {
                    $l++;
                    $result .= $this->allowedChars[$i];
                }
                if($l >= $length) break;
            }
        }while($l < $length);
        return $result;
    }
}

M
Mateusz Będziński

简单的“单行”字符串哈希生成器,例如 77zd43-7bc495-64cg9a-535548(1byte = 2chars)

  $hash = implode('-', [
       bin2hex(random_bytes(3)),
       bin2hex(random_bytes(3)),
       bin2hex(random_bytes(3)),
       bin2hex(random_bytes(3)),
    ]);

S
Somen Das

可以使用此代码。我用 35,000,00 个 ID 进行了测试,没有重复。

<?php
$characters = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_';
$result = '';
for ($i = 0; $i < 11; $i++)
    $result .= $characters[mt_rand(0, 63)];?>

您可以根据需要自由修改它。如果您有任何建议,请随时发表评论。建议您在使用此 ID 之前检查数据库中的每个 ID,因为您的数据库中有 100% 的唯一 ID。


这绝对需要像 microtime() 这样的时间分量
H
Himanshu Sharma

斯科特,是的,你写得很好,解决方案很好!谢谢。

我还需要为我的每个用户生成唯一的 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;
}

请看一下,如果我能做任何改进,请告诉我。谢谢


F
Fery Kaszoni

这是我在我的一个项目中使用的,它工作得很好,它会生成一个唯一的随机令牌:

$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,以使任何用户可能想知道这个令牌是如何生成的;)

我希望它有帮助:)


“请注意,我将时间戳乘以 3,以使任何可能想知道此令牌是如何生成的用户都感到困惑”听起来像是通过混淆获得的安全性 stackoverflow.com/questions/533965/…
这不是“通过混淆的安全性”,因为时间戳随后被添加到生成的随机字符串中,这就是我们返回的实际最终字符串;)
D
Davinder Kumar

我认为这是最好的使用方法。

str_shuffle(md5(rand(0,100000)))

R
Rajesh Prasad Yadav

我们可以使用这两行代码生成唯一的字符串已经测试了大约 10000000 次迭代

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

N
Nixon Kosgei

这是一个有趣的

public function randomStr($length = 16) {
    $string = '';
        
    while (($len = strlen($string)) < $length) {
        $size = $length - $len;
            
        $bytes = random_bytes($size);
            
        $string .= substr(str_replace(['/', '+', '='], '', base64_encode($bytes)), 0, $size);
    }
        
        return $string;
}

从 laravel here 窃取


b
bytesized

我相信所有现有想法的问题在于它们可能是独一无二的,但并非绝对是独一无二的(正如 Dariusz Walczak 对 loletech 的回复中指出的那样)。我有一个实际上是独一无二的解决方案。它要求您的脚本具有某种内存。对我来说,这是一个 SQL 数据库。您也可以简单地在某处写入文件。有两种实现:

第一种方法:有两个字段而不是一个提供唯一性。第一个字段是一个 ID 号,它不是随机的而是唯一的(第一个 ID 是 1,第二个是 2...)。如果您使用 SQL,只需使用 AUTO_INCREMENT 属性定义 ID 字段。第二个字段不是唯一的,而是随机的。这可以使用人们已经提到的任何其他技术来生成。 Scott 的想法很好,但是 md5 很方便,并且对于大多数用途来说可能已经足够了:

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

第二种方法:基本相同的想法,但最初选择将生成的最大字符串数。这可能只是一个非常大的数字,比如一万亿。然后做同样的事情,生成一个 ID,但是用零填充它,这样所有的 ID 都是相同的位数。然后只需将 ID 与随机字符串连接起来。对于大多数用途来说,它是足够随机的,但 ID 部分将确保它也是唯一的。