For learning purposes I am trying to implement a simple, PDO-based, single user login script with hashed passwords as an upgrade to MD5, which is stored in a MySQL database, following this tutorial. The script works, I am able to login and out with the correct login credentials, but every time I get the following error message:
Notice: Trying to get property of non-object in /var/www/login.php on line 23
line 23 in login.php is if ( crypt($password, $user->hash) == $user->hash ) { //
I already tried if( ! $user = $sth->fetch(PDO::FETCH_OBJ) ) {die('no rows returned');} which returns 'no rows returned', ie. no object is fetched. var_dump($user); returns bool(false).
This is how I hash the password:
$username = 'YourUsername';
$password = 'YourPassword';
// A higher "cost" is more secure but consumes more processing power
$cost = 10;
// Create a random salt
$salt = strtr(base64_encode(mcrypt_create_iv(16, MCRYPT_DEV_URANDOM)), '+', '.');
// Prefix information about the hash so PHP knows how to verify it later.
// "$2a$" Means we're using the Blowfish algorithm. The following two digits are the cost parameter.
echo $salt = sprintf("$2a$%02d$", $cost) . $salt;
// Value:
// $2a$10$IkCxeZMOEYCWFDsZ2zYvFA==
// Hash the password with the salt
echo $hash = crypt($password, $salt);
// Value:
// $2a$10$IkCxeZMOEYCWFDsZ2zYvF.gMDDP.ttroo0U9YDPlp6GiXxt02.JSy
$hash is then saved in table 'users' of the MySQL database:
CREATE TABLE users(
id INT AUTO_INCREMENT,
username varchar(65) UNIQUE NOT NULL,
hash varchar(123) NOT NULL,
first_name varchar(50) NOT NULL,
last_name varchar(50) NOT NULL,
email_address varchar(100) NOT NULL,
PRIMARY KEY (id)
);
INSERT INTO users ( username, hash, first_name, last_name, email_address )
VALUES ( 'YourUsername', '$2a$10$IkCxeZMOEYCWFDsZ2zYvF.gMDDP.ttroo0U9YDPlp6GiXxt02.JSy', 'YourName', 'YourLastName', 'test@example.com' );
This is the login.php, where the error occurs on line 23:
<?php
include 'blog.php';
session_start();
$status = '';
if ( $_SERVER['REQUEST_METHOD'] == 'POST' ) {
$username = $_POST['username'];
$password = $_POST['password'];
$sth = $conn->prepare('SELECT hash FROM users WHERE username = :username LIMIT 1');
$sth->bindParam(':username', $username);
$sth->execute();
$user = $sth->fetch(PDO::FETCH_OBJ);
// Hashing the password with its hash as the salt returns the same hash
if ( crypt($password, $user->hash) == $user->hash ) {
$_SESSION['username'] = $username;
header("Location: admin/index.php");
}
else
{
$status="Your Login Name or Password is invalid.";
}
}
view_login("login/login", array("status" => $status));
PDO is pulled in through blog.php and db.php:
blog.php
<?php
require 'functions.php';
require 'db.php';
// Connect to the db
$conn = Blog\DB\connect($config);
if ( !$conn ) die('Problem connecting to the db.');
db.php
<?php namespace Blog\DB;
require 'config.php';
function connect($config)
{
try {
$conn = new \PDO($config['DB_HOST'],
$config['DB_USERNAME'],
$config['DB_PASSWORD']);
$conn->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
return $conn;
} catch(Exception $e) {
return false;
}
}
config.php
<?php
// Database configuration
$config = array(
'DB_HOST' => 'mysql:host=localhost;dbname=blog',
'DB_USERNAME' => 'YourUsername',
'DB_PASSWORD' => 'YourPassword'
);
I would appreciate your advise how to fix this error.
Secondly, do you consider this a safe login method considering a single user system without registration option?