如何在PHP中生成唯一的安全随机字符串?

4zcjmb1e  于 2023-02-11  发布在  PHP
关注(0)|答案(6)|浏览(149)

我想添加随机字符串作为令牌的形式提交,这是唯一的生成永远。我花了很多时间与谷歌,但我很困惑,其中组合使用?
我在谷歌上找到了很多方法:

1) Combination of character and number.

2) Combination of character, number and special character.

3) Combination of character, number, special character and date time.

我可以使用哪种组合?
我可以生成多少个字符的随机字符串?
任何其他方法是安全的,然后请让我知道。

4dc9hkyq

4dc9hkyq1#

以下是一些考虑因素:

    • 字母**

字符数可以被认为是编码的alphabet,它本身并不影响字符串的强度,但较大的字母表(数字、非字母数字字符等)确实允许类似强度的较短字符串(aka keyspace),因此如果您要查找较短的字符串,它很有用。

    • 输入值**

为了保证字符串是唯一的,需要添加一些保证是唯一的东西。

  • 如果您有一个好的随机数生成器,则随机值是一个好的种子值
  • 时间是一个很好的添加种子值,但在高流量环境中可能不是唯一的
  • 如果假设用户不会在完全相同的时间创建会话,则用户ID是一个很好的种子值
  • 唯一ID是系统保证唯一的东西。在单服务器部署或分布式部署中,这通常是服务器保证/验证唯一的东西。一种简单的方法是添加计算机ID和计算机唯一ID。一种更复杂的方法是为计算机分配键范围,并让每台计算机管理其键范围。

我曾经使用过的要求绝对唯一性的系统都添加了一个服务器唯一ID来保证一个条目是唯一的,这意味着相同的条目在不同的服务器上会被视为不同的,这正是我们想要的。

    • 方法**

再选择一个符合您的唯一性要求的输入值。如果您需要永远绝对唯一,则需要您控制并确信唯一的某个值,例如计算机关联编号(不会与分布式系统中的其他编号冲突)。如果您不需要绝对唯一,则可以使用具有其他值(如时间)的随机数。如果您需要随机性,则添加随机数。
使用与您的用例相匹配的字母表/编码。对于机器ID,十六进制和base64等编码比较流行。对于机器可读的ID,对于大小写不敏感的编码,我更喜欢base32(Crockford)或base36,对于区分大小写的编码,我更喜欢base58或base62。这是因为这些base32、3658和62生成的字符串更短,并且(与base64相比)在多种用途(例如URL、XML、文件名等)中是安全的,并且不需要在不同用例之间进行转换。

nukf8bse

nukf8bse2#

根据你的需要,你肯定可以得到很多更花哨的,但我只是把它扔在那里,因为它是我经常使用的东西,如你所描述的:

md5(rand());

它快速,简单,容易记忆。而且因为它是十六进制的,所以和其他的很好用。

zazmityj

zazmityj3#

请参考此SO Protected Question。这可能就是您要查找的内容。
我认为最好是把你重新引导到一个以前问过的问题上,这个问题有更实质性的答案。你会发现很多选择。

8ljdwjyq

8ljdwjyq4#

尝试函数getUniqueToken()的代码,它返回长度为10(默认值)的唯一字符串。

/*
    This function will return unique token string...
*/
function getUniqueToken($tokenLength = 10){
    $token = "";
    //Combination of character, number and special character...
    $combinationString = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789*#&$^";
    for($i=0;$i<$tokenLength;$i++){
        $token .= $combinationString[uniqueSecureHelper(0,strlen($combinationString))];
    }
    return $token;
}

/*
    This helper function will return unique and secure string...
*/
function uniqueSecureHelper($minVal, $maxVal) {
        $range = $maxVal - $minVal;
        if ($range < 0) return $minVal; // not so random...

        $log = 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 $minVal + $rnd;
}

使用此代码(两个函数),您可以通过传递int参数(如getUniqueToken(15))来增加字符串长度。
我使用你的第二个想法(字符,数字和特殊字符的组合),你在谷歌搜索后改进。我希望我的例子会帮助你。

yfjy0ee7

yfjy0ee75#

你应该选择3个选项。因为它有日期和时间,所以每次都是唯一的。方法你试过了吗
字符串随机播放($string)
每次从$string生成随机字符串时。结束然后使用substr
($字符串,开始,结束)
如果你想要日期和时间,那么把结果字符串和它连接起来。

xtupzzrd

xtupzzrd6#

对于唯一字符串,请使用uniqid()
为了保证安全,使用哈希算法
例如:
echo md5(uniqid())

相关问题