Solved

creating 2 user ID's

Posted on 2016-11-01
5
34 Views
Last Modified: 2016-11-01
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
Comment
Question by:Black Sulfur
  • 3
  • 2
5 Comments
 
LVL 109

Accepted Solution

by:
Ray Paseur earned 500 total points
ID: 41868408
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
 

Author Comment

by:Black Sulfur
ID: 41868453
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
 
LVL 109

Assisted Solution

by:Ray Paseur
Ray Paseur earned 500 total points
ID: 41868521
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
 

Author Comment

by:Black Sulfur
ID: 41868534
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
 
LVL 109

Expert Comment

by:Ray Paseur
ID: 41868559
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

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction HTML checkboxes provide the perfect way for a web developer to receive client input when the client's options might be none, one or many.  But the PHP code for processing the checkboxes can be confusing at first.  What if a checkbox is…
Generating table dynamically is the most common issue faced by php developers.... So it seems there is a need of an article that explains the basic concept of generating tables dynamically. It just requires a basic knowledge of html and little maths…
The viewer will learn how to create and use a small PHP class to apply a watermark to an image. This video shows the viewer the setup for the PHP watermark as well as important coding language. Continue to Part 2 to learn the core code used in creat…
This tutorial will teach you the core code needed to finalize the addition of a watermark to your image. The viewer will use a small PHP class to learn and create a watermark.

837 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question