Very long back, we had published a simple PHP login system using PHP, which works only with MySQL database. Today, we are providing you an easy registration and login process using PDO connection with better password encryption, which has an advantage of working on different database systems. PDO is a PHP extension that allow us to implement code which is portable across many databases and platforms. This registration process is used in our Wall Script 8. Here is the demo of this cool & simple login / registration process.
Download Script Live Demo
Users Table
User table contains all the users registration details.
CREATE TABLE `users` (
`uid` int NOT NULL PRIMARY KEY AUTO_INCREMENT ,
`username` varchar(25) NOT NULL UNIQUE,
`password` varchar(200) NOT NULL ,
`email` varchar(100) NOT NULL,
`name` varchar(100) NOT NULL,
`profile_pic` varchar(200) NOT NULL,
);
`uid` int NOT NULL PRIMARY KEY AUTO_INCREMENT ,
`username` varchar(25) NOT NULL UNIQUE,
`password` varchar(200) NOT NULL ,
`email` varchar(100) NOT NULL,
`name` varchar(100) NOT NULL,
`profile_pic` varchar(200) NOT NULL,
);
Enable PDO extension for PHP, find this in php.ini configuration file.
config.php
Database connection configuration file, here you have to modify username, password and database details. If you are using other database modify PDO() driver connection value.
<?php
session_start();
/* DATABASE CONFIGURATION */
define('DB_SERVER', 'localhost');
define('DB_USERNAME', 'username');
define('DB_PASSWORD', 'password');
define('DB_DATABASE', 'databasename');
define("BASE_URL", "http://localhost/PHPLoginHash/"); // Eg. http://yourwebsite.com
function getDB()
{
$dbhost=DB_SERVER;
$dbuser=DB_USERNAME;
$dbpass=DB_PASSWORD;
$dbname=DB_DATABASE;
try {
$dbConnection = new PDO("mysql:host=$dbhost;dbname=$dbname", $dbuser, $dbpass);
$dbConnection->exec("set names utf8");
$dbConnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $dbConnection;
}
catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
}
}
?>
session_start();
/* DATABASE CONFIGURATION */
define('DB_SERVER', 'localhost');
define('DB_USERNAME', 'username');
define('DB_PASSWORD', 'password');
define('DB_DATABASE', 'databasename');
define("BASE_URL", "http://localhost/PHPLoginHash/"); // Eg. http://yourwebsite.com
function getDB()
{
$dbhost=DB_SERVER;
$dbuser=DB_USERNAME;
$dbpass=DB_PASSWORD;
$dbname=DB_DATABASE;
try {
$dbConnection = new PDO("mysql:host=$dbhost;dbname=$dbname", $dbuser, $dbpass);
$dbConnection->exec("set names utf8");
$dbConnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $dbConnection;
}
catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
}
}
?>
PostgreSQL PDO connection
Enable PDO_PGSQL extension and use pgsql:host=$dbhost;port=5432;dbname=$dbname;$dbuser, $dbpass
HTML Login Form
Contains simple HTML code.
<div id="login">
<h3>Login</h3>
<form method="post" action="" name="login">
<label>Username or Email</label>
<input type="text" name="usernameEmail" autocomplete="off" />
<label>Password</label>
<input type="password" name="password" autocomplete="off"/>
<div class="errorMsg"><?php echo $errorMsgLogin; ?></div>
<input type="submit" class="button" name="loginSubmit" value="Login">
</form>
</div>
<h3>Login</h3>
<form method="post" action="" name="login">
<label>Username or Email</label>
<input type="text" name="usernameEmail" autocomplete="off" />
<label>Password</label>
<input type="password" name="password" autocomplete="off"/>
<div class="errorMsg"><?php echo $errorMsgLogin; ?></div>
<input type="submit" class="button" name="loginSubmit" value="Login">
</form>
</div>
HTML Signup Code
User registration page.
<div id="signup">
<h3>Registration</h3>
<form method="post" action="" name="signup">
<label>Name</label>
<input type="text" name="nameReg" autocomplete="off" />
<label>Email</label>
<input type="text" name="emailReg" autocomplete="off" />
<label>Username</label>
<input type="text" name="usernameReg" autocomplete="off" />
<label>Password</label>
<input type="password" name="passwordReg" autocomplete="off"/>
<div class="errorMsg"><?php echo $errorMsgReg; ?></div>
<input type="submit" class="button" name="signupSubmit" value="Signup">
</form>
</div>
<h3>Registration</h3>
<form method="post" action="" name="signup">
<label>Name</label>
<input type="text" name="nameReg" autocomplete="off" />
<label>Email</label>
<input type="text" name="emailReg" autocomplete="off" />
<label>Username</label>
<input type="text" name="usernameReg" autocomplete="off" />
<label>Password</label>
<input type="password" name="passwordReg" autocomplete="off"/>
<div class="errorMsg"><?php echo $errorMsgReg; ?></div>
<input type="submit" class="button" name="signupSubmit" value="Signup">
</form>
</div>
CSS Code
#login,#signup{
width: 300px; border: 1px solid #d6d7da;
padding: 0px 15px 15px 15px;
border-radius: 5px;font-family: arial;
line-height: 16px;color: #333333; font-size: 14px;
background: #ffffff;rgba(200,200,200,0.7) 0 4px 10px -1px
}
#login{float:left;}
#signup{float:right;}
h3{color:#365D98}
form label{font-weight: bold;}
form label, form input{display: block;margin-bottom: 5px;width: 90%}
form input{
border: solid 1px #666666;padding: 10px;
border: solid 1px #BDC7D8; margin-bottom: 20px
}
.button {
background-color: #5fcf80 ;
border-color: #3ac162;
font-weight: bold;
padding: 12px 15px;
max-width: 100px;
color: #ffffff;
}
.errorMsg{color: #cc0000;margin-bottom: 10px}
width: 300px; border: 1px solid #d6d7da;
padding: 0px 15px 15px 15px;
border-radius: 5px;font-family: arial;
line-height: 16px;color: #333333; font-size: 14px;
background: #ffffff;rgba(200,200,200,0.7) 0 4px 10px -1px
}
#login{float:left;}
#signup{float:right;}
h3{color:#365D98}
form label{font-weight: bold;}
form label, form input{display: block;margin-bottom: 5px;width: 90%}
form input{
border: solid 1px #666666;padding: 10px;
border: solid 1px #BDC7D8; margin-bottom: 20px
}
.button {
background-color: #5fcf80 ;
border-color: #3ac162;
font-weight: bold;
padding: 12px 15px;
max-width: 100px;
color: #ffffff;
}
.errorMsg{color: #cc0000;margin-bottom: 10px}
userClass.php
This class contains there methods userLogin, userRegistion and userDetails.
<?php
class userClass
{
/* User Login */
public function userLogin($usernameEmail,$password)
{
try{
$db = getDB();
$hash_password= hash('sha256', $password); //Password encryption
$stmt = $db->prepare("SELECT uid FROM users WHERE (username=:usernameEmail or email=:usernameEmail) AND password=:hash_password");
$stmt->bindParam("usernameEmail", $usernameEmail,PDO::PARAM_STR) ;
$stmt->bindParam("hash_password", $hash_password,PDO::PARAM_STR) ;
$stmt->execute();
$count=$stmt->rowCount();
$data=$stmt->fetch(PDO::FETCH_OBJ);
$db = null;
if($count)
{
$_SESSION['uid']=$data->uid; // Storing user session value
return true;
}
else
{
return false;
}
}
catch(PDOException $e) {
echo '{"error":{"text":'. $e->getMessage() .'}}';
}
}
/* User Registration */
public function userRegistration($username,$password,$email,$name)
{
try{
$db = getDB();
$st = $db->prepare("SELECT uid FROM users WHERE username=:username OR email=:email");
$st->bindParam("username", $username,PDO::PARAM_STR);
$st->bindParam("email", $email,PDO::PARAM_STR);
$st->execute();
$count=$st->rowCount();
if($count<1)
{
$stmt = $db->prepare("INSERT INTO users(username,password,email,name) VALUES (:username,:hash_password,:email,:name)");
$stmt->bindParam("username", $username,PDO::PARAM_STR) ;
$hash_password= hash('sha256', $password); //Password encryption
$stmt->bindParam("hash_password", $hash_password,PDO::PARAM_STR) ;
$stmt->bindParam("email", $email,PDO::PARAM_STR) ;
$stmt->bindParam("name", $name,PDO::PARAM_STR) ;
$stmt->execute();
$uid=$db->lastInsertId(); // Last inserted row id
$db = null;
$_SESSION['uid']=$uid;
return true;
}
else
{
$db = null;
return false;
}
}
catch(PDOException $e) {
echo '{"error":{"text":'. $e->getMessage() .'}}';
}
}
/* User Details */
public function userDetails($uid)
{
try{
$db = getDB();
$stmt = $db->prepare("SELECT email,username,name FROM users WHERE uid=:uid");
$stmt->bindParam("uid", $uid,PDO::PARAM_INT);
$stmt->execute();
$data = $stmt->fetch(PDO::FETCH_OBJ); //User data
return $data;
}
catch(PDOException $e) {
echo '{"error":{"text":'. $e->getMessage() .'}}';
}
}
}
?>
class userClass
{
/* User Login */
public function userLogin($usernameEmail,$password)
{
try{
$db = getDB();
$hash_password= hash('sha256', $password); //Password encryption
$stmt = $db->prepare("SELECT uid FROM users WHERE (username=:usernameEmail or email=:usernameEmail) AND password=:hash_password");
$stmt->bindParam("usernameEmail", $usernameEmail,PDO::PARAM_STR) ;
$stmt->bindParam("hash_password", $hash_password,PDO::PARAM_STR) ;
$stmt->execute();
$count=$stmt->rowCount();
$data=$stmt->fetch(PDO::FETCH_OBJ);
$db = null;
if($count)
{
$_SESSION['uid']=$data->uid; // Storing user session value
return true;
}
else
{
return false;
}
}
catch(PDOException $e) {
echo '{"error":{"text":'. $e->getMessage() .'}}';
}
}
/* User Registration */
public function userRegistration($username,$password,$email,$name)
{
try{
$db = getDB();
$st = $db->prepare("SELECT uid FROM users WHERE username=:username OR email=:email");
$st->bindParam("username", $username,PDO::PARAM_STR);
$st->bindParam("email", $email,PDO::PARAM_STR);
$st->execute();
$count=$st->rowCount();
if($count<1)
{
$stmt = $db->prepare("INSERT INTO users(username,password,email,name) VALUES (:username,:hash_password,:email,:name)");
$stmt->bindParam("username", $username,PDO::PARAM_STR) ;
$hash_password= hash('sha256', $password); //Password encryption
$stmt->bindParam("hash_password", $hash_password,PDO::PARAM_STR) ;
$stmt->bindParam("email", $email,PDO::PARAM_STR) ;
$stmt->bindParam("name", $name,PDO::PARAM_STR) ;
$stmt->execute();
$uid=$db->lastInsertId(); // Last inserted row id
$db = null;
$_SESSION['uid']=$uid;
return true;
}
else
{
$db = null;
return false;
}
}
catch(PDOException $e) {
echo '{"error":{"text":'. $e->getMessage() .'}}';
}
}
/* User Details */
public function userDetails($uid)
{
try{
$db = getDB();
$stmt = $db->prepare("SELECT email,username,name FROM users WHERE uid=:uid");
$stmt->bindParam("uid", $uid,PDO::PARAM_INT);
$stmt->execute();
$data = $stmt->fetch(PDO::FETCH_OBJ); //User data
return $data;
}
catch(PDOException $e) {
echo '{"error":{"text":'. $e->getMessage() .'}}';
}
}
}
?>
index.php
Contains PHP and HTML code, works base on user form submit.
<?php
include("config.php");
include('class/userClass.php');
$userClass = new userClass();
$errorMsgReg='';
$errorMsgLogin='';
/* Login Form */
if (!empty($_POST['loginSubmit']))
{
$usernameEmail=$_POST['usernameEmail'];
$password=$_POST['password'];
if(strlen(trim($usernameEmail))>1 && strlen(trim($password))>1 )
{
$uid=$userClass->userLogin($usernameEmail,$password);
if($uid)
{
$url=BASE_URL.'home.php';
header("Location: $url"); // Page redirecting to home.php
}
else
{
$errorMsgLogin="Please check login details.";
}
}
}
/* Signup Form */
if (!empty($_POST['signupSubmit']))
{
$username=$_POST['usernameReg'];
$email=$_POST['emailReg'];
$password=$_POST['passwordReg'];
$name=$_POST['nameReg'];
/* Regular expression check */
$username_check = preg_match('~^[A-Za-z0-9_]{3,20}$~i', $username);
$email_check = preg_match('~^[a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\.([a-zA-Z]{2,4})$~i', $email);
$password_check = preg_match('~^[A-Za-z0-9!@#$%^&*()_]{6,20}$~i', $password);
if($username_check && $email_check && $password_check && strlen(trim($name))>0)
{
$uid=$userClass->userRegistration($username,$password,$email,$name);
if($uid)
{
$url=BASE_URL.'home.php';
header("Location: $url"); // Page redirecting to home.php
}
else
{
$errorMsgReg="Username or Email already exists.";
}
}
}
?>
//HTML Code
....Login Form HTML Code....
....Signup Form HTML Code...
include("config.php");
include('class/userClass.php');
$userClass = new userClass();
$errorMsgReg='';
$errorMsgLogin='';
/* Login Form */
if (!empty($_POST['loginSubmit']))
{
$usernameEmail=$_POST['usernameEmail'];
$password=$_POST['password'];
if(strlen(trim($usernameEmail))>1 && strlen(trim($password))>1 )
{
$uid=$userClass->userLogin($usernameEmail,$password);
if($uid)
{
$url=BASE_URL.'home.php';
header("Location: $url"); // Page redirecting to home.php
}
else
{
$errorMsgLogin="Please check login details.";
}
}
}
/* Signup Form */
if (!empty($_POST['signupSubmit']))
{
$username=$_POST['usernameReg'];
$email=$_POST['emailReg'];
$password=$_POST['passwordReg'];
$name=$_POST['nameReg'];
/* Regular expression check */
$username_check = preg_match('~^[A-Za-z0-9_]{3,20}$~i', $username);
$email_check = preg_match('~^[a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\.([a-zA-Z]{2,4})$~i', $email);
$password_check = preg_match('~^[A-Za-z0-9!@#$%^&*()_]{6,20}$~i', $password);
if($username_check && $email_check && $password_check && strlen(trim($name))>0)
{
$uid=$userClass->userRegistration($username,$password,$email,$name);
if($uid)
{
$url=BASE_URL.'home.php';
header("Location: $url"); // Page redirecting to home.php
}
else
{
$errorMsgReg="Username or Email already exists.";
}
}
}
?>
//HTML Code
....Login Form HTML Code....
....Signup Form HTML Code...
Note: You have to include JavaScript validations for better user experience.
session.php
This will validate and store user session value.
<?php
if(!empty($_SESSION['uid']))
{
$session_uid=$_SESSION['uid'];
include('class/userClass.php');
$userClass = new userClass();
}
if(empty($session_uid))
{
$url=BASE_URL.'index.php';
header("Location: $url");
}
?>
if(!empty($_SESSION['uid']))
{
$session_uid=$_SESSION['uid'];
include('class/userClass.php');
$userClass = new userClass();
}
if(empty($session_uid))
{
$url=BASE_URL.'index.php';
header("Location: $url");
}
?>
home.php
User welcome page, display user details base on user session value.
<?php
include('config.php');
include('session.php');
$userDetails=$userClass->userDetails($session_uid);
?>
<h1>Welcome <?php echo $userDetails->name; ?></h1>
<h4><a href="<?php echo BASE_URL; ?>logout.php">Logout</a></h4>
include('config.php');
include('session.php');
$userDetails=$userClass->userDetails($session_uid);
?>
<h1>Welcome <?php echo $userDetails->name; ?></h1>
<h4><a href="<?php echo BASE_URL; ?>logout.php">Logout</a></h4>
logout.php
This code will clear user session values.
<?php
include('config.php');
$session_uid='';
$_SESSION['uid']='';
if(empty($session_uid) && empty($_SESSION['uid']))
{
$url=BASE_URL.'index.php';
header("Location: $url");
//echo "<script>window.location='$url'</script>";
}
?>
include('config.php');
$session_uid='';
$_SESSION['uid']='';
if(empty($session_uid) && empty($_SESSION['uid']))
{
$url=BASE_URL.'index.php';
header("Location: $url");
//echo "<script>window.location='$url'</script>";
}
?>
thanks for the article!
ReplyDeleteThanks
ReplyDeletethanks. i just do not like to use pdo directly, you recomend any ORM Library for small to medium php projects?
ReplyDeleteThanks for the article bro..
ReplyDeleteThanks For tutorial on PDO
ReplyDeleteI like to see a real login system this is for simple, no risk login, this is a good information, But for real life good process and/or secure login, with use salt and session regeneration.
ReplyDeleteSame here
Deletegood
DeleteOttimo!!! grazie!!!
ReplyDeleteBRAVISSIMO E COMPLIMENTI
To avoid session hijacking
ReplyDelete$_SESSION['ip'] = $_SERVER['REMOTE_ADDR'];
if($_SESSION['ip'] != $_SERVER['REMOTE_ADDR'])
{
//die('Session MAY have been hijacked');
$url=BASE_URL.'logout.php';
header("Location: $url");
}
Unable to login in localhost & in demo too .
ReplyDeleteYep!This doesn't work at all, It doesn't even add the credentials in the database.
DeleteHi... Awesome article for one just learning to use PDO, thanks so much! Curious, when the files are uploaded and one registers/logs in, should the object information (users information) be displayed at the top of the "home.php" page? I was following along with the article, but perhaps I missed something, not sure. Thanks again!
ReplyDeleteThe reason that the login doesn't work is because the password field in users table is limited to 50 characters while the actual hash is longer than that. To solve this, increase the limit to at least 64 (I increased it to 250) as the SHA256 generates a hash of length 64
ReplyDeleteThanks updated password length to 200
DeleteHi, how can I upload profile image and recovery to home.php?
ReplyDeleteThanks
How can i connect different hosting, if my script on server A and database at server B, i have also allow the IP of script at database hosting server, please tell how it will be possible
ReplyDeleteEnsure to open the port address of the database hosting server and include the IP Address on the connection class, something like $server = "" // the ip address of the database server.
DeleteYou'r the best ;)
ReplyDeletegood article
ReplyDeleteThis is vulnerable -- add:
ReplyDelete$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
I'm new to PDO. Can you please elaborate? It would be a great help. Thank You
DeleteWhat about session_destroy(); ??
ReplyDeleteHi, nice tutorial.
ReplyDeleteI have a question, how to populate an user's table by using this UserClass.php and this config.php? would you give me an good idea? thanks!
for security purpose, it's good to add:
ReplyDelete$dbConnection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
in your connection :-)
hi thanks for code... can u help in ..
ReplyDeleteafter login , when i open home.php in new tab it go to index.php and ask again for login . what can i do for that.. it is still loged in
why i cant ?fatal error, warning ??/ how to solve ,,??
ReplyDeleteindex.php how do i add login html and signup html
ReplyDeletehey men one help me ?
ReplyDeletei upload doc,ppt, pdf file in MySQL database using php pdo.
how to view any file like doc, ppt & pdf in Bootstrap modal dynamically from database.
I request put your next tutorial in your blog fastly.
Thanks.........
After entering correct credentials index.php do not redirect to home.php
ReplyDeleteIf i manually browse home.php i can see i'm logged-in.
Why redirection does not work after a successfull login ?
Thanks for your help,
Try to enable ob_start() method is config.php.
Deletethanks so much!!!!!
ReplyDeleteWarning: session_start(): Cannot send session cache limiter - headers already sent (output started at /home/teksiml/sepuluh.teksi.ml/php-login-hash/home.php:1) in /home/teksiml/sepuluh.teksi.ml/php-login-hash/config.php on line 2
ReplyDeleteTry to enable ob_start() method is config.php.
DeleteNice work but i have big problems
ReplyDeletewhen register it dont say i am registred, it does nothing.
If try register again it says already registred so it works.
Need it to show i am registred, and send me to some other page
and when log in i can see in url it send me to home.php but it only show same contents as main page with login and register, infact no matter what page im on it only show login and register, i am using the files downloaded from here and only set up config file, also im running this from hosted domain. tried it with php56 php71 php72
and tested in firefox v61.01 64 bit and in google chrome Version 68.0.3440.84 (Officiel version) (64-bit)
ok solved i deleted .htaccess file server had created
ReplyDeleteif you like to see the .htaccess file its here
ReplyDeleteOptions +FollowSymLinks
RewriteEngine On
AddEncoding gzip .gz
AddEncoding gzip .gzip
ForceType text/javascript
ForceType text/css
RewriteCond %{REQUEST_URI} !^/index\.php
RewriteCond %{REQUEST_URI} !/ow_updates/index\.php
RewriteCond %{REQUEST_URI} !/ow_updates/
RewriteCond %{REQUEST_URI} !/ow_cron/run\.php
RewriteCond %{REQUEST_URI} !/e500\.php
RewriteCond %{REQUEST_URI} !/captcha\.php
#RewriteCond %{REQUEST_URI} (/|\.php|\.html|\.htm|\.xml|\.feed|robots\.txt|\.raw|/[^.]*)$ [NC]
RewriteCond %{REQUEST_FILENAME} (/|\.php|\.html|\.htm|\.xml|\.feed|robots\.txt|\.raw|/[^.]*)$ [NC]
RewriteRule (.*) index.php
# php -- BEGIN cPanel-generated handler, do not edit
# Set the “ea-php71” package as the default “PHP” programming language.
AddType application/x-httpd-ea-php71 .php .php7 .phtml
# php -- END cPanel-generated handler, do not edit
that was great
ReplyDelete