PHP: How to generate a random, unique, alphanumeric string for use in a secret link?

后端 未结 28 2105
隐瞒了意图╮
隐瞒了意图╮ 2020-11-21 22:20

How would it be possible to generate a random, unique string using numbers and letters for use in a verify link? Like when you create an account on a website, and it sends y

相关标签:
28条回答
  • 2020-11-21 23:01

    Simplifying Scotts code above by removing unnecessary loops which is slowing down badly and does not make it any more secure than calling openssl_random_pseudo_bytes just once

    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
     $rnd = hexdec(bin2hex(openssl_random_pseudo_bytes($bytes)));
     return $min + $rnd%$range;
    }
    
    function getToken($length)
    {
     return bin2hex(openssl_random_pseudo_bytes($length)
    }
    
    0 讨论(0)
  • 2020-11-21 23:02

    When trying to generate a random password you are trying to :

    • First generate a cryptographically secure set of random bytes

    • Second is turning those random bytes into a printable string

    Now, there are multiple way to generate random bytes in php like :

    $length = 32;
    
    //PHP 7+
    $bytes= random_bytes($length);
    
    //PHP < 7
    $bytes= openssl_random_pseudo_bytes($length);
    

    Then you want to turn these random bytes into a printable string :

    You can use bin2hex :

    $string = bin2hex($bytes);
    

    or base64_encode :

    $string = base64_encode($bytes);
    

    However, note that you do not control the length of the string if you use base64. You can use bin2hex to do that, using 32 bytes will turn into a 64 char string. But it will only work like so in an EVEN string.

    So basically you can just do :

    $length = 32;
    
    if(PHP_VERSION>=7){
        $bytes= random_bytes($length);
    }else{
        $bytes= openssl_random_pseudo_bytes($length);
    } 
    
    $string = bin2hex($bytes);
    
    0 讨论(0)
  • 2020-11-21 23:03

    I'm late but I'm here with some good research data based on the functions provided by Scott's answer. So I set up a Digital Ocean droplet just for this 5-day long automated test and stored the generated unique strings in a MySQL database.

    During this test period, I used 5 different lengths (5, 10, 15, 20, 50) and +/-0.5 million records were inserted for each length. During my test, only the length 5 generated +/-3K duplicates out of 0.5 million and the remaining lengths didn't generate any duplicates. So we can say that if we use a length of 15 or above with Scott's functions, then we can generate highly reliable unique strings. Here is the table showing my research data:

    Update: I created a simple Heroku app using these functions that returns the token as a JSON response. The app can be accessed at https://uniquestrings.herokuapp.com/api/token?length=15

    I hope this helps.

    0 讨论(0)
  • 2020-11-21 23:03

    Here is what I'm using on one of my projects, it's working great and it generates a UNIQUE RANDOM TOKEN:

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

    Please note that I multiplied the timestamp by three to create a confusion for whoever user might be wondering how this token is generated ;)

    I hope it helps :)

    0 讨论(0)
  • 2020-11-21 23:05

    I use this one-liner:

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

    where length is the length of the desired string (divisible by 4, otherwise it gets rounded down to the nearest number divisible by 4)

    0 讨论(0)
  • 2020-11-21 23:05

    Here is what I use:

    md5(time() . rand());    
    // Creates something like 0c947c3b1047334f5bb8a3b7adc1d97b
    
    0 讨论(0)
提交回复
热议问题