Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 50
  • Last Modified:

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.
0
Black Sulfur
Asked:
Black Sulfur
  • 3
  • 2
2 Solutions
 
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
 
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

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 3
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now