creating 2 user ID's

I am not sure if this is a worthwhile idea but at the moment when a user is stored in the database they get ID's starting from 1. In a url string that would should something like page.php?userID=1

That seems to easy to manipulate. So, I created another column in the database for another unique ID that I would use in the URL instead. I just wanted to know if a) this is worth doing or if it's pointless and b) Is this good enough to use? The below code was actually an example for something else but it seemed like a good choice (I think).

function randUserId() {
    return strtr(
        base64_encode(
            random_bytes(9)
        ),
        '+/',
        '-_'
    );
}

Open in new window


I was also concerned that there is a chance that there could be a duplicate entry so perhaps before the user is able to register, I have some code to check that it doesn't exist before continuing. Not sure what I would do if it did exist though because the user isn't in control of what is generated.
LVL 1
Black SulfurAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Ray PaseurCommented:
If you're storing this in a database, you can use UNIQUE constraints and any attempt to insert a duplicate value in a UNIQUE column will cause MySQL to throw errno==1062.  You can trap this and retry the value generation process.

The main advantage of having non-sequential numbers for database keys appears when you're using a security-by-obscurity approach to URL parameters.  If your clients are numbered sequentially from 1, 2, 3, ... it's going to be pretty easy to guess the next sequence.  Random keys reduce the risk of a hacker guessing your client identifiers and stealing your database.

I think the strtr() code is unnecessary.  Base64_encode() will give you URL-safe values for the random string.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Black SulfurAuthor Commented:
Okay, great. I just wanted to make sure I wasn't wasting my time. I thought that the 1,2,3 was way too easy.

Yes, I am storing it in the database. Good call on setting it to UNIQUE in MySQL.
1
Ray PaseurCommented:
FWIW, here is one of my thought-experiments about random and unique keys.  Your little function may be a better solution!
<?php // demo/random_unique_string.php
/**
 * Generate a short unique random string for use as some kind of key.
 *
 * We deliberately omit look-alike letters like o and 0, I and 1.
 * If lower case letters are included, it's wise to omit lower-case l.
 *
 * In some fonts we might want to omit s,5 and z,2.
 *
 * Note that the data base must have the rand_key field defined as "unique"
 * Note that the length argument must match throughout so we define() it.
 */
error_reporting(E_ALL);
echo "<pre>";


define('ARG_LENGTH', 7);


Class Randu
{
    public $keys, $errs, $cnt;
    protected $mytable  = 'myKeys';
    protected $mycolumn = 'rand_key';

    public function __construct()
    {
        $this->keys = array();
        $this->errs = array();
        $this->cnt  = -1;

        // DATABASE CONNECTION AND SELECTION VARIABLES - GET THESE FROM YOUR HOSTING COMPANY
        $db_host = "localhost"; // PROBABLY THIS IS OK
        $db_name = "??";
        $db_user = "??";
        $db_word = "??";
        
        // OPEN A CONNECTION TO THE DATA BASE SERVER AND SELECT THE DB
        $this->mysqli = new mysqli($db_host, $db_user, $db_word, $db_name);

        // DID THE CONNECT/SELECT WORK OR FAIL?
        if ($this->mysqli->connect_errno)
        {
            $err
            = "CONNECT FAIL: "
            . $this->mysqli->connect_errno
            . ' '
            . $this->mysqli->connect_error
            ;
            trigger_error($err, E_USER_ERROR);
        }


        // IN REAL LIFE, THIS WOULD BE A PERMANENT TABLE
        $len = ARG_LENGTH;
        $sql
        =
        "
        CREATE TEMPORARY TABLE $this->mytable
        ( id                 INT                   NOT NULL AUTO_INCREMENT PRIMARY KEY
        , $this->mycolumn    VARCHAR($len)  UNIQUE NOT NULL DEFAULT '?'
        )
        ENGINE=MyISAM DEFAULT CHARSET=ascii
        "
        ;
        // IF mysqli::query() RETURNS FALSE, LOG AND SHOW THE ERROR
        if (!$res = $this->mysqli->query($sql))
        {
            $err
            = 'QUERY FAILURE:'
            . ' ERRNO: '
            . $this->mysqli->errno
            . ' ERROR: '
            . $this->mysqli->error
            . ' QUERY: '
            . $sql
            ;
            trigger_error($err, E_USER_ERROR);
        }
    }

    // FUNCTION TO MAKE A RANDOM STRING
    public function random_string($length)
    {
        // POSSIBLE COMBINATIONS > HUNDREDS OF MILLIONS IF LENGTH > 6
        //           1...5...10...15...20...25...30.
        $alphabet = "ABCDEFGHJKMNPQRSTUVWXYZ23456789";
        $strlen   = strlen($alphabet);
        $string   = NULL;
        while(strlen($string) < $length)
        {
            $random = mt_rand(0,$strlen);
            $string .= substr($alphabet, $random, 1);
        }
        return($string);
    }

    // FUNCTION TO ENSURE THE RANDOM STRING IS UNIQUE
    public function make_random_key()
    {
        $key = NULL;
        $this->cnt++;

        // GENERATE A UNIQUE AND RANDOM TOKEN
        while ($key == NULL)
        {
            $key = $this->random_string(ARG_LENGTH);
            $sql = "INSERT INTO $this->mytable ( $this->mycolumn ) VALUES ( '$key' )";
            $res = $this->mysqli->query($sql);

            // IF THERE IS A QUERY ERROR
            if (!$res)
            {
                // THE EXPECTED QUERY ERROR WOULD BE A DUPLICATE VALUE, NULLIFY THE KEY AND START OVER
                if ($this->mysqli->errno == 1062)
                {
                    // trigger_error("1062 Duplicate Key Event: $key at " . number_format($this->cnt), E_USER_NOTICE);
                    echo PHP_EOL   . "1062 Duplicate Key Event: $key at " . number_format($this->cnt);
                    $this->errs[$this->cnt] = $key;
                    $key = NULL;
                }
                // OTHER UNEXPECTED QUERY ERROR
                else
                {
                    $err
                    = 'QUERY FAILURE:'
                    . ' ERRNO: '
                    . $this->mysqli->errno
                    . ' ERROR: '
                    . $this->mysqli->error
                    . ' QUERY: '
                    . $sql
                    ;
                    trigger_error($err, E_USER_ERROR);
                }
            }
        }
        $this->keys[$this->cnt] = $key;
        return $key;
    }

}


// MAKE LOTS OF UNIQUE AND RANDOM STRINGS
$num = 0;
$max = 100000;
$ran = new Randu;
$aaa = time();
while ($num < $max)
{
    $thing = $ran->make_random_key();
    $num++;
}

// SHOW THE WORK PRODUCT
$zzz = time();
$lap = $zzz - $aaa;
echo PHP_EOL . "CREATED $max UNIQUE KEYS IN $lap SECONDS" . PHP_EOL;
echo PHP_EOL . number_format(count($ran->errs)) . " DUPLICATE KEYS";
echo PHP_EOL;
print_r($ran->errs);
echo PHP_EOL ;
// print_r($ran->keys);

Open in new window

0
Black SulfurAuthor Commented:
Thanks, Ray. Always nice to see other examples.

I am a simple man and the less code it takes to do something the better so I probably will stick to what I have if it's deemed acceptable by geniuses such as yourself ;)
0
Ray PaseurCommented:
Agree with "simpler == better."

There is also a per-request unique string available in $_SERVER["UNIQUE_ID"]
http://httpd.apache.org/docs/current/mod/mod_unique_id.html
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
PHP

From novice to tech pro — start learning today.