I don't mean to muddy up this even more, but I wrote a nice login/registration tutorial (without authentication though it could easily be implemented).
common.inc.php file:
<?php
//Start session
session_start();
// create an user $_SESSION array:
$_SESSION['user'] = NULL;
// Set error message to Null
$errMsg = NULL;
// Create the database connection as a PDO object:
try {
$db_options = array(
PDO::ATTR_EMULATE_PREPARES => false // important! use actual prepared statements (default: emulate prepared statements)
, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION // throw exceptions on errors (default: stay silent)
, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC // fetch associative arrays (default: mixed arrays)
);
$pdo = new PDO('mysql:host=localhost;dbname=demo_login_system;charset=utf8', 'your_username', 'your_password', $db_options);
} catch (PDOException $e) { // Report the Error!
$errMsg = "<p>Something is not right, check your php.ini settings or code</p>";
}
// A nice little function that sanitizes the data output:
function html_escape($raw_input) {
return htmlspecialchars($raw_input, ENT_QUOTES | ENT_HTML401, 'UTF-8'); // important! don't forget to specify ENT_QUOTES and the correct encoding
}
The next two file use common.inc.php which I put in folder called includes (though I would change it on a live website .... assuming this code is used)
register.php:
<?php
/*
********* TABLE Structure *********
CREATE TABLE IF NOT EXISTS `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(30) NOT NULL,
`password` char(60) NOT NULL,
`date_added` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=5 ;
*/
// common.inc.php file contains required
// database connection & initialization info:
require 'includes/common.inc.php';
// A nice password hashing library for PHP 5
// Find it here: https://github.com/ircmaxell/password_compat/blob/master/lib/password.php
// Read the Documentation for further help:
// NOTE: if you're not using PHP 5, there are plenty of
// other good password hashing libraries out there ---> JUST GOOGLE IT!
require 'includes/password.inc.php';
// Check to see if user has submitted form:
if (isset($_POST['action']) && $_POST['action'] == 'register') {
// Grab the user's input from form:
$username = $_POST['username'];
$password = $_POST['password'];
// Using Regex to check username:
if (preg_match("/^[0-9a-zA-Z_]{5,}$/", $username) === 0) {
$errMsg = '<p>Username must be bigger that 5 chars and contain only digits, letters and underscore<p>';
}
// Using Regex to check password:
if (preg_match("/^.*(?=.{8,})(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z]).*$/", $password) === 0) {
$errMsg .= '<p>Password must be at least 8 characters, and must contain at least one lower case letter, one upper case letter and one digit.</p>';
}
// Function to check if username is available:
function isUsernameAvailable($username, $pdo) {
// The PDO Query:
$query = "
SELECT
1
FROM users
WHERE
username = :username1
";
// The prepared property/attribute:
$query_params = array(
':username1' => $username
);
// These two statements run the query against your database table.
$stmt = $pdo->prepare($query);
$result = $stmt->execute($query_params);
// The fetch() method returns an array representing the "next" row from
// the selected results, or false if there are no more rows to fetch.
return $row = $stmt->fetch();
// If a row was returned, then we know a matching username was found in
// the database already and we should return a boolean value back.
}
// Check to see if username is available:
$result = isUsernameAvailable($username, $pdo);
// If username is taken then assign to $errMsg:
if ($result) {
$errMsg .= '<p>Username: ' . $username . ' is already taken.</p>';
}
// Hash the password - See above for details:
$password = password_hash($password, PASSWORD_BCRYPT, array("cost" => 15));
// Store user's credentials, if form data is validated:
if(!$errMsg) {
// Using prepared statements:
$query = 'INSERT INTO users ( username, password ) VALUES ( :username, :password )';
$stmt = $pdo->prepare($query);
$result = $stmt->execute(array(':username' => $username, ':password' => $password));
$errMsg = 'You have successfully registered to our great website!';
}
}
?>
<!--/Display Errors if there are any - using a ternary operator-->
<?php echo (isset($errMsg)) ? $errMsg : '<h1>Registration Page</h1>'; ?>
<form action="register.php" method="post"/>
<input type="hidden" name="action" value="register" />
Username: <input type="text" name="username"/><br />
Password: <input type="password" name="password"/><br />
<input type="submit" value="register!"/>
</form>
login.php:
<?php
// common.inc.php file contains required
// database connection initialization info:
require 'includes/common.inc.php';
// A nice password hashing library for PHP 5
// Find it here: https://github.com/ircmaxell/password_compat/blob/master/lib/password.php
// Read the Documentation for further help:
require 'includes/password.inc.php';
if (isset($_POST['action']) && $_POST['action'] == 'login') {
// This query retreives the user's information from the database using
// their username.
$query = '
SELECT
id,
username,
password,
DATE_FORMAT(date_added, "%e %M %Y") as date_added
FROM users
WHERE
username = :username
';
// The parameter values
$query_params = array(
':username' => $_POST['username']
);
try
{
// Execute the query against the database
$stmt = $pdo->prepare($query);
$result = $stmt->execute($query_params);
}
catch(PDOException $ex)
{
// Note: On a production website, you should not output $ex->getMessage().
// It may provide an attacker with helpful information about your code.
die("Failed to run query: " . $ex->getMessage());
}
// This variable tells us whether the user has successfully logged in or not.
// We initialize it to false, assuming they have not.
// If we determine that they have entered the right details, then we switch it to true.
$login_ok = false;
// Retrieve the user data from the database. If $row is false, then the username
// they entered is not registered.
$row = $stmt->fetch();
if($row)
{
// Verify Stored Hashed Password:
$result = password_verify($_POST['password'], $row['password']);
if ($result) {
$login_ok = true;
} else {
$errMsg = '<p>Your credientials do not match!</p>';
}
}
// If login is OK:
if ($login_ok) {
// It's not wise to store the password in $_SESSION:
unset($row['password']);
// This stores the user's data into the session at the index 'user'.
// We will check this index on the private members-only page to determine whether
// or not the user is logged in. We can also use it to retrieve
// the user's details.
$_SESSION['user'] = $row;
// The following output is just to prove that it works:
echo '<pre>';
print_r($_SESSION);
echo '</pre>';
// Redirect the user to the private members-only page.
//header("Location: admin.php");
//die("Redirecting to: admin.php");
}
}
/*
* This was just to help people who are just getting started
* learning how to program in the PHP Language. The PDO portion
* is written in Object-Oriented Style, but this doesn't mean
* that you now know OOP or that you have to use it. It's pretty
* straight forward in my opinion. I have tested this out, but I make
* no guarantees that it works 100 percent and it diffentely needs
* updating/styling. However, that is up to you and besides it's
* a good way to learn PHP.
*/
?>
<!--/Display Errors if there are any - using a ternary operator-->
<?php echo (isset($errMsg)) ? $errMsg : '<h1>Login Page:</h1>'; ?>
<form action="login.php" method="post"/>
<input type="hidden" name="action" value="login" />
Username: <input type="text" name="username"/><br />
Password: <input type="password" name="password"/><br />
<input type="submit" value="submit"/>
</form>
This is far from perfect, but I do know one thing that it works. Even if none of the code is used, I think it shows how to go about writing a basic login/registration system in PHP. I didn't take in the part of sanitizing the variables, but it is using PDO prepared statements.