Hello! I have been doing my reading on log-in/username system security and I want to post what I have done! I still feel like my system is lacking in security, so I'd love any and all input!

I've completely obscured the MySQL table values to my liking (A LOT of fun!!!). My username password encryption is as follows:

//encrypt password
$enc_mypassword=md5($mypassword);

// To protect MySQL injection
$myusername = stripslashes($myusername);
$enc_mypassword = stripslashes($mypassword);
$enc_myusername = mysql_real_escape_string($myusername);
$enc2_mypassword = mysql_real_escape_string($enc_mypassword);
$enc3_mypassword = md5($enc2_mypassword);

And is then followed (after determining that the user is valid) by:

session_register("myusername");
$_SESSION["loginusername"] = $myusername;

Here's where I feel that I'm lacking...on each page following it performs this check:

session_start();
if(!session_is_registered(myusername)){
header("location:registerform.php");
}

And that's it. What else can I do? THANKS SO MUCH!!!

I really appreciate it :D!

-Jeff

session_register and session_is_registered are depreciated. use the $_SESSION array instead.

md5 isn't secure anymore. you should use something like sha1 with a random salt.

Oooh I'm thrilled I asked! So I'd wanna do:

$_SESSION = ...;

and

$password = sha1('salt'.$_POST); ?

Is the salt just a random keyword or does it have a significance? I've looked up sha1 and the acronym just lives and breathes SECURITY :). Thanks!

for the session question...yes.

as for the password encryption, here are some functions you should find useful:

function encryptPassword( $pass,$salt=false,$saltLength=4 ) {
		if ( $salt === false ) {
			$res = '';
			for( $i=0;$i<$saltLength;$i++ ) {
				$res .= pack( 's',mt_rand() );
			}
			$salt = substr( base64_encode( $res ),0,$saltLength );
		}
		return $salt . sha1( $salt . $pass );
	}

	function checkPassword( $pass,$hash,$saltLength=4 ) {
		if ( encryptPassword( $pass,substr( $hash,0,$saltLength ) ) === $hash ) {
			return true;
		}
		return false;
	}

to use, just run encryptPassword( $_POST );
then to check a password (like logins ect.) run checkPassword( $_POST,$hash ); $_POST would be the value someone submitted and $hash would be that hashed password found for that user. hope you understand.

Oooh that's very interesting! Thank you! Now for my questions on its use :P:

The $hash value gets uploaded to the MySQL database? I love the first function, but am sort of unclear on when the second comes into play. Wouldn't I just run the encryptPassword function (upon login) on the password the user inputs, and then compare it to the $hash value in the MySQL database?

Thanks a ton!

no, because the salt would be different, giving you different hashes.

you would need to check for a usernames existance in the database and then return the hash. then use the checkPassword function to compare the two. heres an example (from my last login i created):

if ( $_form->isValid( 'login' ) ) { //check to see if the submit button with the name of 'login' is in the post array and then validates the form if it is
	$_db->LoadTable('mem_data'); //loads table table login to the database class so we can use it.
	$_sess->SetScope('FIELD'); //set the session scope to only let the session functions to pull and put data in the fields portion of this pages session array
	$email = $_db->clean( $_sess->get('email') ); //cleans and sets email from form in the $email var
	$passw = $_db->clean( $_sess->get('pass') ); //cleans and sets password from form in the $passw var
	$query = $_db->GetTable('mem_data')->select( array( 'id','password','admin','confirmed','suspended' ),"`email` = '{$email}'" ); //queries database to see if there is a row with the email submitted
	$total = $query->numRows(); //puts number of rows found into the $total var (should be 1)
	if ( $total == 0 ) { //if no rows are found set errors
		$_form->setError( 'email','Email and/or Password incorrect' );
		$_form->setError( 'pass' );
	}
	elseif ( $total == 1 ) { //if 1 row is found then...
		list( $id,$mpass,$admin,$confd,$suspd ) = $query->fetchRow(); //sets data form the query into usable vars
		if ( !appFunc::checkPassword( $passw,$mpass ) ) { // makes sure password matches
			$_form->setError( 'email','Email and/or Password incorrect' );
			$_form->setError( 'pass' );
		}
		elseif ( $confd == 0 ) { //makes sure that the member has confirmed his/her email address
			$_form->setError( 'email','Email address not confirmed!' );
			$_form->setError( 'pass' );
		}
		elseif ( $suspd == 1 ) { //makes sure the member is not suspended by the admin
			$_form->setError( 'email','Account suspended' );
			$_form->setError( 'pass' );
		}
		else { //if everything is good so far, set the session variable, clear the session fields and redirect to members area.
			$_db->GetTable('mem_data')->update( array( 'last_login'=>time() ),$id ); //update login table with the time of the login
			$_sess->set( 'mem_id',$id,'GLOBAL' ); //sets mem_id into the global part of the session array
			if ( $admin == 1 ) { //if the user is an admin then add it to the session so the admin page will know
				$_sess->set( 'adm_id',$id,'GLOBAL' ); //sets the adm_id id into the global part of the session
			}
			$_sess->ClearPage(); //clears page from session array because its no longer needed
			$location = 'member';
			if ( $_sess->_isset( 'redirect','GLOBAL' ) ) {
				$location = $_sess->get( 'redirect','GLOBAL' );
			}
			header( "Location: {$location}" ); //redirects to members area
			exit;
		}
	}
}

i don't know if you will be able to follow, because of how i have everything setup but I don't have a less complicated example.

I truly thank you :D. So here is where the checkPassword is being used:

if ( !appFunc::checkPassword( $passw,$mpass ) ) { // makes sure password matches
			$_form->setError( 'email','Email and/or Password incorrect' );
			$_form->setError( 'pass' );

You have defined $passw as being the password submitted from the form. $mpass I'm guessing is the master pass, which is taken from the SQL table (encrypted) and equal to the $hash variable as defined above. I would check the $passw to the $hash, and it would returns equal then it would be true? For example:

function checkPassword( $pass,$hash,$saltLength=4 ) {
		if ( encryptPassword( $pass,substr( $hash,0,$saltLength ) ) === $hash ) {
			echo "true";
		}
		return false;
	}

checkPassword($pass,$hash);

Would it echo "true", being that $pass is the value that the user inputted and $hash is the encrypted value in the database? Thanks for being helpful here :D

yes.

you have to use the encrypted password in the database to check the password you get from the user. this is because you have use the same salt to check it. the salt is appended to the hash and the function gets it by using substr.

That sounds like a wonderful system. Now how do we go about validating that the user is logged in on each page? Thanks so much, I know I've been a pain :).

Really!?!? Yay! I'm glad it's something that simple :D! Thank you I will let you know how implementing the password functions works out!

Ahh, I'm just having some trouble calling upon the encryptPassword(); function.

I have my form with the inputted variable password...how do I run the function to work with password?

This isn't working:

$pass2 = encryptPassword($pass,$salt=false,$saltLength=4);

THANKS!

...it's beautiful :-P!

I had to run it like this for anyone else who may read the fabulous thread:

$pass2 = encryptPassword( $pass );
echo $pass2;

Now to begin checking the password :).

Sorry I'm being such a bother :P. So I have this long string alphanumeric string saved in my MySQL database, and I want to check to see if the user exists by comparing their inputted password to the one in the database using the wonderful checkPassword function, and if it returns a row where the inputted username has a corresponding password of the one inputted, it returns true. So I have this:

--Login to MySQL Database and Establish Connection

function encryptPassword( $pass,$salt=false,$saltLength=4 ) {
		if ( $salt === false ) {
			$res = '';
			for( $i=0;$i<$saltLength;$i++ ) {
				$res .= pack( 's',mt_rand() );
			}
			$salt = substr( base64_encode( $res ),0,$saltLength );
		}
		return $salt . sha1( $salt . $pass );
	}
	
function checkPassword( $pass,$hash,$saltLength=4 ) {
		if ( encryptPassword( $pass,substr( $hash,0,$saltLength ) ) === $hash ) {
			echo "true";
		}
		echo "false";
	}
	
if (isset($_POST['submit'])) {
$pass = $_POST['password'];
$pass2 = encryptPassword( $pass );
mysql_query("INSERT INTO  `Password Test` (  `Password` ) 
VALUES ('$pass2')");
	}

if (isset($_POST['check'])) {
checkPassword($_POST['password'],$hash); }
?>

<form action="" method="post" name="testform">
<input type="text" name="password" />
<input type="text" name="username" />
<input type="submit" name="submit" />
<input type="submit" value="Check" name="check">
</form>

I'm thinking it's gotta be something like this:

$sql="SELECT * FROM $tbl_name WHERE `Client`='$_POST['username']' and `Password`='$_POST['password']";
$result=mysql_query($sql);

// Mysql_num_row is counting table row
$count=mysql_num_rows($result);

if($count==1){
echo "true"; }

Could you please help guide me through the checkPassword function in conjunction with the database :). Thanks so much, if there's anyway I can thank you for this on Daniweb please let me know!!!

i decided instead of explaining that I would create an entire example so you can see how it all works. It will include registration, login, and basic members page.

should be done within the hour.

This needs to be stickied or search-spidered a lot, because this is probably one of the hardest things to come by when it comes to user-active site development! Thanks a million, I'm sure the entire community will say the same as well!

PHP/MYSQL USER REGISTRATION AND LOGIN EXAMPLE

Database table
-------------------------------------------------------------
Todo - Create this table in your database

CREATE TABLE `login` (
`id` INT NOT NULL AUTO_INCREMENT ,
`username` VARCHAR( 30 ) NOT NULL ,
`password` VARCHAR( 100 ) NOT NULL ,
PRIMARY KEY ( `id` ) ,
UNIQUE ( `username` )
) ENGINE = MYISAM

Database connection page - includes/dbconnect.php
-------------------------------------------------------------
Description - Holds database connection. This is used to get rid of redundant code in each page. It also helps if you change your username/password/database name you won't have to update every page, just one.
Todo - Fill the variables with the proper information

<?php

$host = 'localhost';
$user = '';
$pass = '';
$dbname = '';

$con = mysql_connect( $host,$user,$pass ) or die('Unable to connect');
mysql_select_db( $dbname ) or die('Unable to select database');

?>

Functions page - includes/functions.php
-------------------------------------------------------------
Description - Holds the functions. Used so you don't have to repeat the functions in each page. Also, if you need to update a function, you only will have to do it once.

<?php

function encryptPassword( $pass,$salt=false,$saltLength=4 ) {
		if ( $salt === false ) {
			$res = '';
			for( $i=0;$i<$saltLength;$i++ ) {
				$res .= pack( 's',mt_rand() );
			}
			$salt = substr( base64_encode( $res ),0,$saltLength );
		}
		return $salt . sha1( $salt . $pass );
}
	
function checkPassword( $pass,$hash,$saltLength=4 ) {
		if ( encryptPassword( $pass,substr( $hash,0,$saltLength ) ) === $hash ) {
			return true;
		}
		return false;
}

?>

Registration page - register.php
-------------------------------------------------------------
Description - Gets username and password from user, validates them, and inserts into database

<?php

require('includes/functions.php'); //include functions
require('includes/dbconnect.php'); //include db connection

$error = array(); //define $error to prevent error later in script
$message = '';
if ( isset( $_POST['submit'] ) ) {
    $error = array();
    array_map( 'stripslashes',&$_POST ); //Strips slashes
    array_map( 'mysql_real_escape_string',&$_POST ); //Escapes data to protect against sql injection
    $user = $_POST['username'];
    $pass = $_POST['password'];
    if ( empty( $user ) ) { //check if username is blank
        $error[] = 'Username is blank';
    }
    elseif ( strlen( $user ) > 30 ) { //make sure the username is not longer than 30 chars
        $error[] = 'Username is longer than 30 characters';
    }
    else { //if there aren't any errors with $user at this point, check to make sure no one else has the same username
        $query = mysql_query( "SELECT * FROM `login` WHERE `username` = '{$user}'",$con );
        if ( mysql_num_rows( $query ) > 0 ) {
            $error[] = 'Username already exists';
        }
    }
    if ( empty( $pass ) ) { //check if password is blank
        $error[] = 'Password is blank';
    }
    elseif ( strlen( $pass ) < 9 ) { //make sure password is longer than 8 characters
        $error[] = 'Password must be longer than 8 characters';
    }
    elseif ( !preg_match( "/^.*(?=.{3,})(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).*$/",$pass ) ) { //check to see if its a valid password
        $error[] = 'Password invalid - it must contain at least 1 number, 1 uppercase letter, 1 lowercase letter';
    }
    if ( count( $error ) == 0 ) { //if there are no errors, then insert into database
        $pass = encryptPassword( $pass ); //hash password before inserting into database
        $query = mysql_query( "INSERT INTO `login` (`username`,`password`) VALUES ('{$user}','{$pass}')",$con );
        $message = 'User registration successful!';
    }
}

$errmsg = '';
if ( count( $error ) > 0 ) { //if there are errors, build the error list to be displayed.
    $errmsg = '<div>Errors:<br /><ul>';
    foreach( $error as $err ) { //loop through errors and put then in the list
        $errmsg .= "<li>{$err}</li>";
    }
    $errmsg .= '</ul></div>';
}

$html =<<<HTML
<html>
<head>
<title>Registration</title>
</head>
<body>
    <h3>Member Registration</h3>
    {$errmsg}
    <div>
        <form action="{$_SERVER['PHP_SELF']}" method="post">
            Username: <input type="text" name="username" /><br />
            Password: <input type="password" name="password" /><br />
            <input type="submit" name="submit" value="Register" />
        </form>
    </div>
    <div style="color:#ff0000">{$message}</div>
</body>
</html>
HTML;

echo $html;

?>

Login page - login.php
-------------------------------------------------------------
Description - Gets username and password from user, validates them, and check to see if user is present in database and sets a session.

<?php

session_start(); //start session so we can login

require('includes/functions.php'); //include functions
require('includes/dbconnect.php'); //include database connection

$error = array(); //define $error to prevent error later in script.
if ( isset( $_POST['submit'] ) ) {
    $error = array();
    array_map( 'stripslashes',&$_POST ); //Strips slashes
    array_map( 'mysql_real_escape_string',&$_POST ); //Escapes data to protect against sql injection
    $user = $_POST['username'];
    $pass = $_POST['password'];
    if ( empty( $user ) ) { //check if username is blank
        $error[] = 'Username is blank';
    }
    elseif ( strlen( $user ) > 30 ) { //make sure the username is not longer than 30 chars
        $error[] = 'Username is longer than 30 characters';
    }
    if ( empty( $pass ) ) { //check if password is blank
        $error[] = 'Password is blank';
    }
    elseif ( strlen( $pass ) < 9 ) { //make sure password is longer than 8 characters
        $error[] = 'Password must be longer than 8 characters';
    }
    elseif ( !preg_match( "/^.*(?=.{3,})(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).*$/",$pass ) ) { //check to see if its a valid password
        $error[] = 'Password invalid - it must contain at least 1 number, 1 uppercase letter, 1 lowercase letter';
    }
    if ( count( $error ) == 0 ) { //if everything is ok so far, keep going (i do this because i don't want to hit the database if the username or password is blank)
        $query = mysql_query( "SELECT `id`,`password` FROM `login` WHERE `username` = '{$user}' LIMIT 1",$con );
        if ( mysql_num_rows( $query ) !== 1 ) { //checks to see if a row was found with username provided by user
            $error[] = 'Username and/or Password incorrect'; //never be specific with errors, makes it hard to crack
        }
        else {
            list( $id,$hash ) = mysql_fetch_row( $query ); //puts the id and password from result into $id and $pass variables
            if ( !checkPassword( $pass,$hash ) ) { //check password from user against the hash in the database.
                $error[] = 'Username and/or Password incorrect';
            }
            if ( count( $error ) == 0 ) { //if now errors found, then set session for login
                $_SESSION['auth'] = $id;
                header('Location: member.php'); //redirect to secure area
                exit; //exit script since we are redirecting anyway
            }
        }
    }
}

$errmsg = '';
if ( count( $error ) > 0 ) { //if there are errors, build the error list to be displayed.
    $errmsg = '<div>Errors:<br /><ul>';
    foreach( $error as $err ) { //loop through errors and put then in the list
        $errmsg .= "<li>{$err}</li>";
    }
    $errmsg .= '</ul></div>';
}

$html =<<<HTML
<html>
<head>
<title>Login</title>
</head>
<body>
    <h3>Member Login</h3>
    {$errmsg}
    <div>
        <form action="{$_SERVER['PHP_SELF']}" method="post">
            Username: <input type="text" name="username" /><br />
            Password: <input type="password" name="password" /><br />
            <input type="submit" name="submit" value="Login" />
        </form>
    </div>
</body>
</html>
HTML;

echo $html;

?>

Member area - member.php
-------------------------------------------------------------
Description - place where people who are successfully logged in go. Information on this page is only for members to access, no one else can see it.

<?php

session_start(); //start session so we can see if the user is logged in.

if ( !isset( $_SESSION['auth'] ) ) { // if auth is not in the $_SESSION array (meaning they haven't been to the login page where its set) redirect them to the login page
    header('Location: login.php');
    exit;
}

require('includes/dbconnect.php'); //include database connection

$memid = $_SESSION['auth']; //set member id into $memid.

$query = mysql_query( "SELECT `username` FROM `login` WHERE `id` = {$memid}" ); //
$member = mysql_fetch_assoc( $query );

echo "Welcome, {$member['username']} <a href=\"logout.php\">Logout</a>";

?>

Logout page - logout.php
-------------------------------------------------------------
Description - logs out member and redirects to login page

<?php

session_start(); //start session so we can logout

unset( $_SESSION['auth'] ); //remove auth from the $_SESSION array

header('Location: login.php');
exit;

?>

Any questions? Ask them.

Comments
He is a Godly figure.

Oh my God...that's absolutely divine. It's wonderful!!! And that's secure to the bone? Is there anything else that could possibly be done? Now I've got me some exciting work to do in incorporating this :). I believe everyone who reads this will thank you in immense proportions ;).

Pretty secure. Maybe add session_regenerate_id() to add some more session security. If you want to display any data from the user on the page, make sure its ran through htmlentities() first to prevent xss.

The only thing I should of added is a token system to prevent csrf (cross-site request forgery) and a form timeout. I will probably add those soon and add the new page.

I added the token system and form timeout. New login.php and register.php below.

Register page - register.php

<?php

session_start();

require('includes/functions.php'); //include functions
require('includes/dbconnect.php'); //include db connection

$min_form_time = 5; //in seconds
$max_form_time = 30; //in seconds

$error = array(); //define $error to prevent error later in script
$message = '';
if ( isset( $_POST['submit'] ) ) {
    $error = array();
    array_map( 'stripslashes',&$_POST ); //Strips slashes
    array_map( 'mysql_real_escape_string',&$_POST ); //Escapes data to protect against sql injection
    $user = $_POST['username'];
    $pass = $_POST['password'];
    $token = $_POST['token'];
    if ( $token !== $_SESSION['token'] ) {
        $error[] = 'Token is invalid';
    }
    else {
        if ( time() <= ( $_SESSION['time'] + $min_form_time ) ) {
            $error[] = 'Form submitted too quickly, please slow down and try again';
        }
        elseif ( time() >= ( $_SESSION['time'] + $max_form_time ) ) {
            $error[] = 'Form has expired';
        }
        else {
            if ( empty( $user ) ) { //check if username is blank
                $error[] = 'Username is blank';
            }
            elseif ( strlen( $user ) > 30 ) { //make sure the username is not longer than 30 chars
                $error[] = 'Username is longer than 30 characters';
            }
            else { //if there aren't any errors with $user at this point, check to make sure no one else has the same username
                $query = mysql_query( "SELECT * FROM `login` WHERE `username` = '{$user}'",$con );
                if ( mysql_num_rows( $query ) > 0 ) {
                    $error[] = 'Username already exists';
                }
            }
            if ( empty( $pass ) ) { //check if password is blank
                $error[] = 'Password is blank';
            }
            elseif ( strlen( $pass ) < 9 ) { //make sure password is longer than 8 characters
                $error[] = 'Password must be longer than 8 characters';
            }
            elseif ( !preg_match( "/^.*(?=.{3,})(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).*$/",$pass ) ) { //check to see if its a valid password
                $error[] = 'Password invalid - it must contain at least 1 number, 1 uppercase letter, 1 lowercase letter';
            }
            if ( count( $error ) == 0 ) { //if there are no errors, then insert into database
                $pass = encryptPassword( $pass ); //hash password before inserting into database
                $query = mysql_query( "INSERT INTO `login` (`username`,`password`) VALUES ('{$user}','{$pass}')",$con );
                $message = 'User registration successful!';
            }
        }
    }
}

$errmsg = '';
if ( count( $error ) > 0 ) { //if there are errors, build the error list to be displayed.
    $errmsg = '<div>Errors:<br /><ul>';
    foreach( $error as $err ) { //loop through errors and put then in the list
        $errmsg .= "<li>{$err}</li>";
    }
    $errmsg .= '</ul></div>';
}

$token = md5(uniqid(rand(),true));
$_SESSION['token'] = $token;
$_SESSION['time'] = time();

$html =<<<HTML
<html>
<head>
<title>Registration</title>
</head>
<body>
    <h3>Member Registration</h3>
    {$errmsg}
    <div>
        <form action="{$_SERVER['PHP_SELF']}" method="post">
            Username: <input type="text" name="username" /><br />
            Password: <input type="password" name="password" /><br />
            <input type="hidden" name="token" value="{$token}" />
            <input type="submit" name="submit" value="Register" />
        </form>
    </div>
    <div style="color:#ff0000">{$message}</div>
</body>
</html>
HTML;

echo $html;

?>

Login page - login.php

<?php

session_start(); //start session so we can login

require('includes/functions.php'); //include functions
require('includes/dbconnect.php'); //include database connection

$min_form_time = 5; //in seconds
$max_form_time = 30; //in seconds

$error = array(); //define $error to prevent error later in script.
if ( isset( $_POST['submit'] ) ) {
    $error = array();
    array_map( 'stripslashes',&$_POST ); //Strips slashes
    array_map( 'mysql_real_escape_string',&$_POST ); //Escapes data to protect against sql injection
    $user = $_POST['username'];
    $pass = $_POST['password'];
    $token = $_POST['token'];
    if ( $token !== $_SESSION['token'] ) {
        $error[] = 'Token is invalid';
    }
    else {
        if ( time() <= ( $_SESSION['time'] + $min_form_time ) ) {
            $error[] = 'Form submitted too quickly, please slow down and try again';
        }
        elseif ( time() >= ( $_SESSION['time'] + $max_form_time ) ) {
            $error[] = 'Form has expired';
        }
        else {
            if ( empty( $user ) ) { //check if username is blank
                $error[] = 'Username is blank';
            }
            elseif ( strlen( $user ) > 30 ) { //make sure the username is not longer than 30 chars
                $error[] = 'Username is longer than 30 characters';
            }
            if ( empty( $pass ) ) { //check if password is blank
                $error[] = 'Password is blank';
            }
            elseif ( strlen( $pass ) < 9 ) { //make sure password is longer than 8 characters
                $error[] = 'Password must be longer than 8 characters';
            }
            elseif ( !preg_match( "/^.*(?=.{3,})(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).*$/",$pass ) ) { //check to see if its a valid password
                $error[] = 'Password invalid - it must contain at least 1 number, 1 uppercase letter, 1 lowercase letter';
            }
            if ( count( $error ) == 0 ) { //if everything is ok so far, keep going (i do this because i don't want to hit the database if the username or password is blank)
                $query = mysql_query( "SELECT `id`,`password` FROM `login` WHERE `username` = '{$user}' LIMIT 1",$con );
                if ( mysql_num_rows( $query ) !== 1 ) { //checks to see if a row was found with username provided by user
                    $error[] = 'Username and/or Password incorrect'; //never be specific with errors, makes it hard to crack
                }
                else {
                    list( $id,$hash ) = mysql_fetch_row( $query ); //puts the id and password from result into $id and $pass variables
                    if ( !checkPassword( $pass,$hash ) ) { //check password from user against the hash in the database.
                        $error[] = 'Username and/or Password incorrect';
                    }
                    if ( count( $error ) == 0 ) { //if now errors found, then set session for login
                        $_SESSION['auth'] = $id;
                        header('Location: member.php'); //redirect to secure area
                        exit; //exit script since we are redirecting anyway
                    }
                }
            }
        }
    }
}

$errmsg = '';
if ( count( $error ) > 0 ) { //if there are errors, build the error list to be displayed.
    $errmsg = '<div>Errors:<br /><ul>';
    foreach( $error as $err ) { //loop through errors and put then in the list
        $errmsg .= "<li>{$err}</li>";
    }
    $errmsg .= '</ul></div>';
}

$token = md5(uniqid(rand(),true));
$_SESSION['token'] = $token;
$_SESSION['time'] = time();

$html =<<<HTML
<html>
<head>
<title>Login</title>
</head>
<body>
    <h3>Member Login</h3>
    {$errmsg}
    <div>
        <form action="{$_SERVER['PHP_SELF']}" method="post">
            Username: <input type="text" name="username" /><br />
            Password: <input type="password" name="password" /><br />
            <input type="hidden" name="token" value="{$token}" />
            <input type="submit" name="submit" value="Login" />
        </form>
    </div>
</body>
</html>
HTML;

echo $html;

?>

One of my favorite parts of this script is the error console. Could you show me how to use this error console to check three variables, $var1 $var2 and $var 3, for content and escape any special characters? Thanks :).

This is what I wrote as a template that isn't working:

<form action="" method="post" name="form">
<input type="text" name="text">
<input type="submit" name="submit">
</form>

<?php
$error = array(); //define $error to prevent error later in script.
if ( isset( $_POST['submit'] ) ) {
    $error = array();
    array_map( 'stripslashes',&$_POST ); //Strips slashes
    array_map( 'mysql_real_escape_string',&$_POST ); //Escapes data to protect against sql injection
	$text = $_POST['text'];    
            if ( empty( $text ) ) { //check if username is blank
                $error[] = 'Text is blank';
            }
            
                    if ( count( $error ) == 0 ) { //if now errors found, then set session for login
                        echo $text . "1"; }
                        exit; //exit script since we are redirecting anyway
                    
$errmsg = '';
print_r($error);
if ( count( $error ) > 0 ) { //if there are errors, build the error list to be displayed.
    $errmsg = '<div>Errors:<br /><ul>';
    foreach( $error as $err ) { //loop through errors and put then in the list
        $errmsg .= "<li>{$err}</li>";
    }
    $errmsg .= '</ul></div>';
	echo $errmsg; } }


?>

Am I missing something with this? The more I read it the more and more I think it's right...:/

looks ok. the only thing is see is that you have exit; outside of the if ( count( $error ) == 0 ) if statement. that would stop everything underneath that piece of code not to run, therefore not displaying errors.

Hi Keith, i was looking for a php login example to take as a reference on building a small cms for myself and got curious about security practices. I've found this one, which seems nice and is perfectly explained. I wanted to ask, since this post has more than a year, if there's anything more we should take care of regarding security. I've been following this example but it's quite messy:
code:
http://www.devshed.com/c/a/PHP/Creating-a-Secure-PHP-Login-Script-59941/
review:
http://blog.ircmaxell.com/2011/08/security-review-creating-secure-php.html
(The review is also a good source but doesnt fix everything).
Thanks!

This article has been dead for over six months. Start a new discussion instead.