如何在 PHP 中制作简短的随机唯一密钥,例如 YouTube 视频 ID?

发布于 2024-09-28 09:12:45 字数 1778 浏览 0 评论 0原文

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

情场扛把子 2024-10-05 09:12:45

这个想法是将唯一整数(例如当前时间)转换为其他数学基础。

PHP 中的一个非常简单的方法:

// With this precision (microsecond) ID will looks like '2di2adajgq6h'

// From PHP 7.4.0 this is needed, otherwise a warning is displayed
$cleanNumber = preg_replace( '/[^0-9]/', '', microtime(false) );
$id = base_convert($cleanNumber, 10, 36);


// With less precision (second) ID will looks like 'niu7pj'

$id = base_convert(time(), 10, 36);

The idea is to convert a unique integer (such as current time) in an other mathematical base.

A very simple way in PHP :

// With this precision (microsecond) ID will looks like '2di2adajgq6h'

// From PHP 7.4.0 this is needed, otherwise a warning is displayed
$cleanNumber = preg_replace( '/[^0-9]/', '', microtime(false) );
$id = base_convert($cleanNumber, 10, 36);


// With less precision (second) ID will looks like 'niu7pj'

$id = base_convert(time(), 10, 36);
浅暮の光 2024-10-05 09:12:45

一个小型 PHP 类,用于从一个或多个数字生成类似 YouTube 的哈希值。当您不想向用户公开数据库 ID 时,请使用 hashids。

来源:https://github.com/ivanakimov/hashids.php

A small PHP class to generate YouTube-like hashes from one or many numbers. Use hashids when you do not want to expose your database ids to the user.

Source: https://github.com/ivanakimov/hashids.php

魂牵梦绕锁你心扉 2024-10-05 09:12:45

这是一个每次随机生成唯一密钥的小函数。重复相同唯一 ID 的机会非常少。

function uniqueKey($limit = 10) {

    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';

    $randstring = '';

    for ($i = 0; $i < $limit; $i++) {

        $randstring .= $characters[rand(0, strlen($characters))];
    }

    return $randstring;
}

Here is a small function that generates unique key randomly each time. It has very fewer chances to repeat same unique ID.

function uniqueKey($limit = 10) {

    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';

    $randstring = '';

    for ($i = 0; $i < $limit; $i++) {

        $randstring .= $characters[rand(0, strlen($characters))];
    }

    return $randstring;
}
把回忆走一遍 2024-10-05 09:12:45

使用您喜欢的任何一个:-)

// 生成字母数字输出

function generateRandomID() {
    // http://mohnish.in
    $required_length = 11;
    $limit_one = rand();
    $limit_two = rand();
    $randomID = substr(uniqid(sha1(crypt(md5(rand(min($limit_one, $limit_two), max($limit_one, $limit_two)))))), 0, $required_length);
    return $randomID;
}

// 只生成字母输出

function anotherRandomIDGenerator() {
    // Copyright: http://snippets.dzone.com/posts/show/3123
    $len = 8;
    $base='ABCDEFGHKLMNOPQRSTWXYZabcdefghjkmnpqrstwxyz';
    $max=strlen($base)-1;
    $activatecode='';
    mt_srand((double)microtime()*1000000);
    while (strlen($activatecode)<$len+1)
    $activatecode.=$base{mt_rand(0,$max)};
    return $activatecode;
}

Use whichever you like :-)

// Generates Alphanumeric Output

function generateRandomID() {
    // http://mohnish.in
    $required_length = 11;
    $limit_one = rand();
    $limit_two = rand();
    $randomID = substr(uniqid(sha1(crypt(md5(rand(min($limit_one, $limit_two), max($limit_one, $limit_two)))))), 0, $required_length);
    return $randomID;
}

// Generates only alphabetic output

function anotherRandomIDGenerator() {
    // Copyright: http://snippets.dzone.com/posts/show/3123
    $len = 8;
    $base='ABCDEFGHKLMNOPQRSTWXYZabcdefghjkmnpqrstwxyz';
    $max=strlen($base)-1;
    $activatecode='';
    mt_srand((double)microtime()*1000000);
    while (strlen($activatecode)<$len+1)
    $activatecode.=$base{mt_rand(0,$max)};
    return $activatecode;
}
ゞ花落谁相伴 2024-10-05 09:12:45

对我来说最好的算法是这样的: 使用 PHP/Python/Javascript/Java/SQL 创建类似 Youtube 的 ID

<?php
/**
 * Translates a number to a short alhanumeric version
 *
 * Translated any number up to 9007199254740992
 * to a shorter version in letters e.g.:
 * 9007199254740989 --> PpQXn7COf
 *
 * specifiying the second argument true, it will
 * translate back e.g.:
 * PpQXn7COf --> 9007199254740989
 *
 * this function is based on any2dec && dec2any by
 * fragmer[at]mail[dot]ru
 * see: http://nl3.php.net/manual/en/function.base-convert.php#52450
 *
 * If you want the alphaID to be at least 3 letter long, use the
 * $pad_up = 3 argument
 *
 * In most cases this is better than totally random ID generators
 * because this can easily avoid duplicate ID's.
 * For example if you correlate the alpha ID to an auto incrementing ID
 * in your database, you're done.
 *
 * The reverse is done because it makes it slightly more cryptic,
 * but it also makes it easier to spread lots of IDs in different
 * directories on your filesystem. Example:
 * $part1 = substr($alpha_id,0,1);
 * $part2 = substr($alpha_id,1,1);
 * $part3 = substr($alpha_id,2,strlen($alpha_id));
 * $destindir = "/".$part1."/".$part2."/".$part3;
 * // by reversing, directories are more evenly spread out. The
 * // first 26 directories already occupy 26 main levels
 *
 * more info on limitation:
 * - http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/165372
 *
 * if you really need this for bigger numbers you probably have to look
 * at things like: http://theserverpages.com/php/manual/en/ref.bc.php
 * or: http://theserverpages.com/php/manual/en/ref.gmp.php
 * but I haven't really dugg into this. If you have more info on those
 * matters feel free to leave a comment.
 *
 * The following code block can be utilized by PEAR's Testing_DocTest
 * <code>
 * // Input //
 * $number_in = 2188847690240;
 * $alpha_in  = "SpQXn7Cb";
 *
 * // Execute //
 * $alpha_out  = alphaID($number_in, false, 8);
 * $number_out = alphaID($alpha_in, true, 8);
 *
 * if ($number_in != $number_out) {
 *   echo "Conversion failure, ".$alpha_in." returns ".$number_out." instead of the ";
 *   echo "desired: ".$number_in."\n";
 * }
 * if ($alpha_in != $alpha_out) {
 *   echo "Conversion failure, ".$number_in." returns ".$alpha_out." instead of the ";
 *   echo "desired: ".$alpha_in."\n";
 * }
 *
 * // Show //
 * echo $number_out." => ".$alpha_out."\n";
 * echo $alpha_in." => ".$number_out."\n";
 * echo alphaID(238328, false)." => ".alphaID(alphaID(238328, false), true)."\n";
 *
 * // expects:
 * // 2188847690240 => SpQXn7Cb
 * // SpQXn7Cb => 2188847690240
 * // aaab => 238328
 *
 * </code>
 *
 * @author  Kevin van Zonneveld <[email protected]>
 * @author  Simon Franz
 * @author  Deadfish
 * @author  SK83RJOSH
 * @copyright 2008 Kevin van Zonneveld (http://kevin.vanzonneveld.net)
 * @license   http://www.opensource.org/licenses/bsd-license.php New BSD Licence
 * @version   SVN: Release: $Id: alphaID.inc.php 344 2009-06-10 17:43:59Z kevin $
 * @link    http://kevin.vanzonneveld.net/
 *
 * @param mixed   $in   String or long input to translate
 * @param boolean $to_num  Reverses translation when true
 * @param mixed   $pad_up  Number or boolean padds the result up to a specified length
 * @param string  $pass_key Supplying a password makes it harder to calculate the original ID
 *
 * @return mixed string or long
 */
function alphaID($in, $to_num = false, $pad_up = false, $pass_key = null)
{
  $out   =   '';
  $index = 'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
  $base  = strlen($index);

  if ($pass_key !== null) {
    // Although this function's purpose is to just make the
    // ID short - and not so much secure,
    // with this patch by Simon Franz (http://blog.snaky.org/)
    // you can optionally supply a password to make it harder
    // to calculate the corresponding numeric ID

    for ($n = 0; $n < strlen($index); $n++) {
      $i[] = substr($index, $n, 1);
    }

    $pass_hash = hash('sha256',$pass_key);
    $pass_hash = (strlen($pass_hash) < strlen($index) ? hash('sha512', $pass_key) : $pass_hash);

    for ($n = 0; $n < strlen($index); $n++) {
      $p[] =  substr($pass_hash, $n, 1);
    }

    array_multisort($p, SORT_DESC, $i);
    $index = implode($i);
  }

  if ($to_num) {
    // Digital number  <<--  alphabet letter code
    $len = strlen($in) - 1;

    for ($t = $len; $t >= 0; $t--) {
      $bcp = bcpow($base, $len - $t);
      $out = $out + strpos($index, substr($in, $t, 1)) * $bcp;
    }

    if (is_numeric($pad_up)) {
      $pad_up--;

      if ($pad_up > 0) {
        $out -= pow($base, $pad_up);
      }
    }
  } else {
    // Digital number  -->>  alphabet letter code
    if (is_numeric($pad_up)) {
      $pad_up--;

      if ($pad_up > 0) {
        $in += pow($base, $pad_up);
      }
    }

    for ($t = ($in != 0 ? floor(log($in, $base)) : 0); $t >= 0; $t--) {
      $bcp = bcpow($base, $t);
      $a   = floor($in / $bcp) % $base;
      $out = $out . substr($index, $a, 1);
      $in  = $in - ($a * $bcp);
    }
  }

  return $out;
}

For me best algorithm is this: Create Youtube-Like IDs With PHP/Python/Javascript/Java/SQL

<?php
/**
 * Translates a number to a short alhanumeric version
 *
 * Translated any number up to 9007199254740992
 * to a shorter version in letters e.g.:
 * 9007199254740989 --> PpQXn7COf
 *
 * specifiying the second argument true, it will
 * translate back e.g.:
 * PpQXn7COf --> 9007199254740989
 *
 * this function is based on any2dec && dec2any by
 * fragmer[at]mail[dot]ru
 * see: http://nl3.php.net/manual/en/function.base-convert.php#52450
 *
 * If you want the alphaID to be at least 3 letter long, use the
 * $pad_up = 3 argument
 *
 * In most cases this is better than totally random ID generators
 * because this can easily avoid duplicate ID's.
 * For example if you correlate the alpha ID to an auto incrementing ID
 * in your database, you're done.
 *
 * The reverse is done because it makes it slightly more cryptic,
 * but it also makes it easier to spread lots of IDs in different
 * directories on your filesystem. Example:
 * $part1 = substr($alpha_id,0,1);
 * $part2 = substr($alpha_id,1,1);
 * $part3 = substr($alpha_id,2,strlen($alpha_id));
 * $destindir = "/".$part1."/".$part2."/".$part3;
 * // by reversing, directories are more evenly spread out. The
 * // first 26 directories already occupy 26 main levels
 *
 * more info on limitation:
 * - http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/165372
 *
 * if you really need this for bigger numbers you probably have to look
 * at things like: http://theserverpages.com/php/manual/en/ref.bc.php
 * or: http://theserverpages.com/php/manual/en/ref.gmp.php
 * but I haven't really dugg into this. If you have more info on those
 * matters feel free to leave a comment.
 *
 * The following code block can be utilized by PEAR's Testing_DocTest
 * <code>
 * // Input //
 * $number_in = 2188847690240;
 * $alpha_in  = "SpQXn7Cb";
 *
 * // Execute //
 * $alpha_out  = alphaID($number_in, false, 8);
 * $number_out = alphaID($alpha_in, true, 8);
 *
 * if ($number_in != $number_out) {
 *   echo "Conversion failure, ".$alpha_in." returns ".$number_out." instead of the ";
 *   echo "desired: ".$number_in."\n";
 * }
 * if ($alpha_in != $alpha_out) {
 *   echo "Conversion failure, ".$number_in." returns ".$alpha_out." instead of the ";
 *   echo "desired: ".$alpha_in."\n";
 * }
 *
 * // Show //
 * echo $number_out." => ".$alpha_out."\n";
 * echo $alpha_in." => ".$number_out."\n";
 * echo alphaID(238328, false)." => ".alphaID(alphaID(238328, false), true)."\n";
 *
 * // expects:
 * // 2188847690240 => SpQXn7Cb
 * // SpQXn7Cb => 2188847690240
 * // aaab => 238328
 *
 * </code>
 *
 * @author  Kevin van Zonneveld <[email protected]>
 * @author  Simon Franz
 * @author  Deadfish
 * @author  SK83RJOSH
 * @copyright 2008 Kevin van Zonneveld (http://kevin.vanzonneveld.net)
 * @license   http://www.opensource.org/licenses/bsd-license.php New BSD Licence
 * @version   SVN: Release: $Id: alphaID.inc.php 344 2009-06-10 17:43:59Z kevin $
 * @link    http://kevin.vanzonneveld.net/
 *
 * @param mixed   $in   String or long input to translate
 * @param boolean $to_num  Reverses translation when true
 * @param mixed   $pad_up  Number or boolean padds the result up to a specified length
 * @param string  $pass_key Supplying a password makes it harder to calculate the original ID
 *
 * @return mixed string or long
 */
function alphaID($in, $to_num = false, $pad_up = false, $pass_key = null)
{
  $out   =   '';
  $index = 'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
  $base  = strlen($index);

  if ($pass_key !== null) {
    // Although this function's purpose is to just make the
    // ID short - and not so much secure,
    // with this patch by Simon Franz (http://blog.snaky.org/)
    // you can optionally supply a password to make it harder
    // to calculate the corresponding numeric ID

    for ($n = 0; $n < strlen($index); $n++) {
      $i[] = substr($index, $n, 1);
    }

    $pass_hash = hash('sha256',$pass_key);
    $pass_hash = (strlen($pass_hash) < strlen($index) ? hash('sha512', $pass_key) : $pass_hash);

    for ($n = 0; $n < strlen($index); $n++) {
      $p[] =  substr($pass_hash, $n, 1);
    }

    array_multisort($p, SORT_DESC, $i);
    $index = implode($i);
  }

  if ($to_num) {
    // Digital number  <<--  alphabet letter code
    $len = strlen($in) - 1;

    for ($t = $len; $t >= 0; $t--) {
      $bcp = bcpow($base, $len - $t);
      $out = $out + strpos($index, substr($in, $t, 1)) * $bcp;
    }

    if (is_numeric($pad_up)) {
      $pad_up--;

      if ($pad_up > 0) {
        $out -= pow($base, $pad_up);
      }
    }
  } else {
    // Digital number  -->>  alphabet letter code
    if (is_numeric($pad_up)) {
      $pad_up--;

      if ($pad_up > 0) {
        $in += pow($base, $pad_up);
      }
    }

    for ($t = ($in != 0 ? floor(log($in, $base)) : 0); $t >= 0; $t--) {
      $bcp = bcpow($base, $t);
      $a   = floor($in / $bcp) % $base;
      $out = $out . substr($index, $a, 1);
      $in  = $in - ($a * $bcp);
    }
  }

  return $out;
}
爱人如己 2024-10-05 09:12:45

上面的所有方法都很好,但请确保您知道并且不要假设生成的字符串是唯一的。我过去所做的是创建一个递归函数,根据我的数据库检查字符串,如果它是唯一的,则返回该值,否则它会再次运行。不过,这几乎不会发生,具体取决于您的唯一字符串的长度。 知道它的独特性真是太好了。

all the methods above are good but make sure you know and not assume the generated string is unique. What I have done in the past is made a recursive function that checks the string against my database and if it is unique it returns the value, otherwise it just runs again. This will hardly happen though depending how long your unique string is. Its just good to know its unique.

中性美 2024-10-05 09:12:45

我一直在寻找一种非常快速且简单的解决方案(这并不是为了以任何方式保证安全),它可以在重新生成时复制实际的哈希代码(与 PHP 的 microtime 唯一 id 不同)。这个就成功了。

http://php.net/manual/en/book.hash.php

所以:

for($i=0;$i<count($myArray);$i++) {
    $hashCode = "#".hash('crc32b', $myArray[$i]."-".$i);        
}

产量:

#179507fa
#8e9c5640
#f99b66d6
#67fff375
#10f8c3e3

等等

我不会假装知道如何使用所有不同的哈希算法,但对于非安全用途(如链接#anchors),这很方便。

I was looking for a very quick and simple solution (that was NOT intended to be secure in any way) that would replicate the actual hash code upon regeneration (unlike PHP's microtime unique id). This one did the trick.

http://php.net/manual/en/book.hash.php

So:

for($i=0;$i<count($myArray);$i++) {
    $hashCode = "#".hash('crc32b', $myArray[$i]."-".$i);        
}

Yields:

#179507fa
#8e9c5640
#f99b66d6
#67fff375
#10f8c3e3

etc

I won't pretend to know how all the different hash algorithms are used but for non-secure uses (like link #anchors) this is handy.

好菇凉咱不稀罕他 2024-10-05 09:12:45

此处的评论:

<?php 
function generateRandStr($length){ 
      $randstr = ""; 
      for($i=0; $i<$length; $i++){ 
         $randnum = mt_rand(0,61); 
         if($randnum < 10){ 
            $randstr .= chr($randnum+48); 
         }else if($randnum < 36){ 
            $randstr .= chr($randnum+55); 
         }else{ 
            $randstr .= chr($randnum+61); 
         } 
      } 
      return $randstr; 
   } 
?> 

Simply use: 
generateRandStr(10); 

Sample output: $%29zon(4f

您可以使用此函数来生成字母数字,或者只是字母字符。

From comments on here:

<?php 
function generateRandStr($length){ 
      $randstr = ""; 
      for($i=0; $i<$length; $i++){ 
         $randnum = mt_rand(0,61); 
         if($randnum < 10){ 
            $randstr .= chr($randnum+48); 
         }else if($randnum < 36){ 
            $randstr .= chr($randnum+55); 
         }else{ 
            $randstr .= chr($randnum+61); 
         } 
      } 
      return $randstr; 
   } 
?> 

Simply use: 
generateRandStr(10); 

Sample output: $%29zon(4f

You can mess around with this function to generate just alphanumeric, or just alphabetic characters.

帥小哥 2024-10-05 09:12:45

对于大多数目的,uniqid 就足够了,如果你需要的话为了确保绝对不发生冲突,需要采取更复杂的措施。

For most purposes uniqid will suffice, if you need to make sure there's absolutely no clash, more convoluted measures are necessary.

浅黛梨妆こ 2024-10-05 09:12:45
<?php
function keygen(){
    $chars = "bcdfghjklmnpqrstvwxyz";
    $chars .= "BCDFGHJKLMNPQRSTVWXYZ";
    $chars .= "0123456789";
    while(1){
        $key = '';
        srand((double)microtime()*1000000);
        for($i = 0; $i < 10; $i++){
            $key .= substr($chars,(rand()%(strlen($chars))), 1);
        }
        break;
    }
    return $key;
}

//echo keygen();
?>
<?php
function keygen(){
    $chars = "bcdfghjklmnpqrstvwxyz";
    $chars .= "BCDFGHJKLMNPQRSTVWXYZ";
    $chars .= "0123456789";
    while(1){
        $key = '';
        srand((double)microtime()*1000000);
        for($i = 0; $i < 10; $i++){
            $key .= substr($chars,(rand()%(strlen($chars))), 1);
        }
        break;
    }
    return $key;
}

//echo keygen();
?>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文