Solved

creating 2 user ID's

Posted on 2016-11-01
5
26 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 108

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 108

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 108

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

Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Suggested Solutions

Consider the following scenario: You are working on a website and make something great - something that lets the server work with information submitted by your users. This could be anything, from a simple guestbook to a e-Money solution. But what…
Since pre-biblical times, humans have sought ways to keep secrets, and share the secrets selectively.  This article explores the ways PHP can be used to hide and encrypt information.
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
The viewer will learn how to look for a specific file type in a local or remote server directory using PHP.

746 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

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now