Sei sulla pagina 1di 25

http://daveismyname.com/login-and-registration-system-with-php-bp#.

VCuovPmSxTJ

Login and Registration system with PHP

This tutorial will cover creating a login system with registration upon registering an activation link
will be emailed containing a link to activate the account. Once active the user can login, a reset
option is available to reset the password.

Demo
Download
Please click either the Facebook Like button, the Google +1 button or send a tweet to Download
the file.

The file structure will be setup as follows:

The database will require a table to store the members, create a table called members:

1. CREATE TABLE `members` (


2. `memberID` int(11) NOT NULL AUTO_INCREMENT,
3. `username` varchar(255) NOT NULL,
4. `password` varchar(60) NOT NULL,
5. `email` varchar(255) NOT NULL,
6. `active` varchar(255) NOT NULL,
7. `resetToken` varchar(255) DEFAULT NULL,
8. `resetComplete` varchar(3) DEFAULT 'No',
9. PRIMARY KEY (`memberID`)
10.
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
In the classes folder their are two files: password.php and user.php. password.php is used to
provide the same hashing capability that exists within php 5.5 it uses the same function names
so versions 5.3 - 5.5 can use the same functions.
user.php is a class that contains methods to return the users hash (hashed password) as well as
logging in, checking if a logged in session already exists and logging the user out.
I'll be going through the user.php methods as they are put to use.

Config.php
Config.php will be included into all pages enable sessions and turn on output buffering this way
headers can be used anywhere in the project.
Set the timezone and define the credentials for the database, next attempt to make a new PDO
connection if the connection fails display the error and kill the page.
Next include the user class and make an instance of it, pass in the database object to the class
to make use of the database.

1.
2.
3.
4.
5.
6.

<?php
ob_start();
session_start();
//set timezone
date_default_timezone_set('Europe/London');

7.
8. //database credentials
9. define('DBHOST','localhost');
10.
define('DBUSER','database username');
11.
define('DBPASS','password');
12.
define('DBNAME','database name');
13.
14.
//application address
15.
define('DIR','http://domain.com/');
16.
define('SITEEMAIL','noreply@domain.com');
17.
18.
try {
19.
20.
//create PDO connection
21.
$db = new
PDO("mysql:host=".DBHOST.";port=8889;dbname=".DBNAME, DBUSER,
DBPASS);
22.
$db->setAttribute(PDO::ATTR_ERRMODE,
PDO::ERRMODE_EXCEPTION);
23.
24.
} catch(PDOException $e) {
25.
26.
27.
28.
29.
30.
31.
32.
33.

//show error
echo '<p class="bg-danger">'.$e->getMessage().'</p>';
exit;
}
//include the user class, pass in the database connection
include('classes/user.php');
$user = new User($db);
?>

Next I have a folder called layout in there is a header.php and footer.php these will contain any
layout code that will be used on every page, this saves having to include the stylesheet each
time. header.php is a typical header file, notice the title expects a $title variable, this will be
created in the pages and made available to this file, also making use of Bootstrap this is optional
and is not required.

1. <!DOCTYPE html>
2. <html lang="en">
3. <head>
4.
<meta charset="utf-8">
5.
<title><?php if(isset($title)){ echo $title; }?></title>
6.
<link
href="//netdna.bootstrapcdn.com/bootstrap/3.1.0/css/bootstrap.min.
css" rel="stylesheet">
7.
<link rel="stylesheet" href="style/main.css">
8. </head>
9. <body>
Next footer.php this simply closed the body and html, that would be a good place for placing
tracking code or any javascript includes.

1. </body>
2. </html>

index.php
This is the root page the system loads by default, on this page their is a form for users to register
to the site, along with links to the login page, if they are already a member. Also if the user is
already logged in they will be redirect to the members page.
How these pages start is by including the config file then checking if the user should be
redirected or not.
a call is made to the user object $user->is_logged_in() this will return true or false if the user is
logged in.

1.
2.
3.
4.
5.
6.

<?php
//include config
require_once('includes/config.php');
//check if already logged in move to home page
//if logged in redirect to members page

7. if( $user->is_logged_in() ){ header('Location: memberpage.php'); }


The title and header.php file is also included on every page

1.
2.
3.
4.
5.

//define page title


$title = 'Demo';
//include header template
require('layout/header.php');

For new registrations display a form consisting of username, email, password and confirm
password

1. <form role="form" method="post" action="" autocomplete="off">


2.
3.
<div class="form-group">
4.
<input type="text"
name="username" id="username" class="form-control input-lg"
placeholder="User Name" value="<?php if(isset($error)){ echo
$_POST['username']; } ?>" tabindex="1">
5.
6.
7.

</div>
<div class="form-group">
<input type="email" name="email"
id="email" class="form-control input-lg" placeholder="Email
Address" value="<?php if(isset($error)){ echo $_POST['email']; }
?>" tabindex="2">
8.
</div>
9.
<div class="row">
10.
<div class="col-xs-6 colsm-6 col-md-6">
11.
<div class="formgroup">
12.
<input
type="password" name="password" id="password" class="form-control
input-lg" placeholder="Password" tabindex="3">
13.
</div>
14.
</div>

15.
<div class="col-xs-6 colsm-6 col-md-6">
16.
<div class="formgroup">
17.
<input
type="password" name="passwordConfirm" id="passwordConfirm"
class="form-control input-lg" placeholder="Confirm Password"
tabindex="4">
18.
</div>
19.
</div>
20.
</div>
21.
22.
<div class="row">
23.
<div class="col-xs-6 colmd-6"><input type="submit" name="submit" value="Register"
class="btn btn-primary btn-block btn-lg" tabindex="5"></div>
24.
</div>
25.
</form>
This is a standard form, one thing to note I make use of sticky forms which means if their has
been a validation error the fields that have been filled out will be populated again with the
supplied data, except for passwords. Username and email would be restored.
This is done by doing an if statement, if the array $error is set meaning it exists then retrain the
$_POST

1. value="<?php if(isset($error)){ echo $_POST['email']; } ?>"


If an error has been created it will be stored in an error array to display them loop through the
array:

1. //check for any errors


2. if(isset($error)){
3. foreach($error as $error){
4.
echo '<p class="bg-danger">'.$error.'</p>';
5. }

6. }
Once the new registration has been saved the form will post back to the same page appending a
$_GET key on the end of the URL the key will be called action it will have a value of joined
(this technique is used through the project)

1. if(isset($_GET['action']) && $_GET['action'] == 'joined'){


2. echo "<h2 class='bg-success'>Registration successful, please
check your email to activate your account.</h2>";
3. }
The form should only be processed if it has been submitted this can be checked by an if
statement:

1. //if form has been submitted process it


2. if(isset($_POST['submit'])){
This way only if the form has been submitted does the validation start and database interactions
commence.

Validation
The validation used is fairly basic and can be improved upon
This example checks the length of the username if it's less then 3 characters an error is created,
if the first check passes the username is looked up to see if it already exists by passing the
username to the database if a record is found an error is created.

1. if(strlen($_POST['username']) < 3){


2.
$error[] = 'Username is too short.';
3. } else {
4.
$stmt = $db->prepare('SELECT username FROM members WHERE
username = :username');
5.
$stmt->execute(array(':username' => $_POST['username']));
6.
$row = $stmt->fetch(PDO::FETCH_ASSOC);

7.
8.
9.
10.
11.
12.

if(!empty($row['username'])){
$error[] = 'Username provided is already in use.';
}
}

These check the password to make sure the email has not been used, it's important the email
address is only used once, in the event the user wants to reset their password a link will be
emailed to that user.

1. if(strlen($_POST['password']) < 3){


2.
$error[] = 'Password is too short.';
3.
4.
5.
6.
7.
8.
9.

}
if(strlen($_POST['passwordConfirm']) < 3){
$error[] = 'Confirm password is too short.';
}
if($_POST['password'] != $_POST['passwordConfirm']){

10.
$error[] = 'Passwords do not match.';
11.
}
12.
13.
//email validation
14.
if(!filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)){
15.
$error[] = 'Please enter a valid email address';
16.
} else {
17.
$stmt = $db->prepare('SELECT email FROM members WHERE
email = :email');
18.
$stmt->execute(array(':email' => $_POST['email']));
19.
$row = $stmt->fetch(PDO::FETCH_ASSOC);
20.
21.
22.
23.
24.

if(!empty($row['email'])){
$error[] = 'Email provided is already in use.';
}

25.

After the validation if no errors have been created then carry on


The password provided cannot be stored as it is, that would be a huge security concern instead
it's hashed by passing it to the user object inside a password_hash call this returns a hashed
password which can then be stored in the database, this way no one can know what the
password was apart from the user who entered it.
If your wondering how can the system login a user in without knowing the password; what
happens when the user fills in the login form the password they enter is again hashed and then
compared with the hash to see if its a match.
We also want to send an activation link to the user when they register to ensure their email
address is active, for this we generate an activation code it will be sent in the emails and will form
part of a url to validate the email address.

1. //if no errors have been created carry on


2.
if(!isset($error)){
3.
4.
5.
6.
7.
8.

//hash the password


$hashedpassword = $user>password_hash($_POST['password'], PASSWORD_BCRYPT);
//create the activation code
$activasion = md5(uniqid(rand(),true));

Next the user's details are saved to the database using a prepared statement, the first page of
the query tells MySQL what action to perform in this case to add a new row and the
table,columns to insert into.
where their are columns starting with : like :username these are place holders that will be used to
bind the username value to $stmt->execute call. This is done to avoid passing user provided
data to the query directly and avoid chances of MySQL Injection.
calling lastInsertId followed by the primary key will return the id of the record just saved, this is
needed for the next step.

1. $stmt = $db->prepare('INSERT INTO members


(username,password,email,active) VALUES (:username, :password,
:email, :active)');
2. $stmt->execute(array(
3.
':username' => $_POST['username'],
4.
':password' => $hashedpassword,
5.
':email' => $_POST['email'],
6.
':active' => $activasion
7. ));
8. $id = $db->lastInsertId('memberID');
Next send an email to the newly created user. Two constants defined in config.php will be used
here
DIR - contains the full website address
SITEEMAIL - the email address used for emails
in the body of the email is a link activate.php?x=$id&y=$activasion this link is passing the id of
the user $id and also the activation code when the user received this email, clicking the link will
activate their account.

1. $to = $_POST['email'];
2. $subject = "Registration Confirmation";
3. $body = "Thank you for registering at demo site.nn To activate
your account, please click on this link:nn
".DIR."activate.php?x=$id&y=$activasionnn Regards Site Admin nn";
4. $additionalheaders = "From: <".SITEEMAIL.">rn";
5. $additionalheaders .= "Reply-To: $".SITEEMAIL."";
6. mail($to, $subject, $body, $additionalheaders);
The last step is to redirect the page back to itself and adding an action with the value of joined so
the page know if to show a success message.

1. header('Location: index.php?action=joined');
2. exit;

activate.php

This page checks for the id and activation code being passed from the url (this happens when
the user clicks the link from their email)
once the data has been verified the users record is updated, the column active is changed from
the token to hold 'Yes' to say they are active, this will only happen if the id and token passed
match what's stored against that user.

1. <?php
2. require('includes/config.php');
3.
4. //collect values from the url
5. $memberID = trim($_GET['x']);
6. $active = trim($_GET['y']);
7.
8. //if id is number and the active token is not empty carry on
9. if(is_numeric($memberID) && !empty($active)){
10.
11.
//update users record set the active column to Yes
where the memberID and active value match the ones provided in the
array
12.
$stmt = $db->prepare("UPDATE members SET active =
'Yes' WHERE memberID = :memberID AND active = :active");
13.
$stmt->execute(array(
14.
':memberID' => $memberID,
15.
':active' => $active
16.
));
17.
18.
//if the row was updated redirect the user
19.
if($stmt->rowCount() == 1){
20.
21.
//redirect to login page
22.
23.
24.
25.
26.
27.
28.

header('Location: login.php?action=active');
exit;
} else {
echo "Your account could not be activated.";
}

29.
30.

}
?>

Login.php
Now users can register they need a way to login, start off with a form that expects their username
and password

1. <form role="form" method="post" action="" autocomplete="off">


2.
3.
4.

<div class="form-group">
<input type="text" name="username" id="username"
class="form-control input-lg" placeholder="User Name" value="<?php
if(isset($error)){ echo $_POST['username']; } ?>" tabindex="1">
5.
</div>
6.
7.
<div class="form-group">
8.
<input type="password" name="password" id="password"
class="form-control input-lg" placeholder="Password" tabindex="3">
9.
</div>
10.
11.
<div class="row">
12.
<div class="col-xs-9 col-sm-9 col-md-9">
13.
<a href='reset.php'>Forgot your
Password?</a>
14.
</div>
15.
</div>
16.
17.
<hr>
18.
<div class="row">
19.
<div class="col-xs-6 col-md-6"><input
type="submit" name="submit" value="Login" class="btn btn-primary
btn-block btn-lg" tabindex="5"></div>
20.
</div>
21.
</form>

The login page will be used to show messages if the users account has been activated or
password has been changed, the page will know which message to show based on the value
contained inside $_GET['action']

1. if(isset($_GET['action'])){
2.
3.
//check the action
4.
switch ($_GET['action']) {
5.
case 'active':
6.
echo "<h2 class='bg-success'>Your account is
now active you may now log in.</h2>";
7.
break;
8.
case 'reset':
9.
echo "<h2 class='bg-success'>Please check your
inbox for a reset link.</h2>";
10.
break;
11.
case 'resetAccount':
12.
echo "<h2 class='bg-success'>Password
changed, you may now login.</h2>";
13.
break;
14.
}
15.
16.

Next attempt to log the user in. Collect the username and password from the form pass them to
the users object in the login method this internally will fetch the users hash by looking for the
username in the database once the hash is returned it's then passed to password_verify if the
hash and user's hash match it returns true which in turns sets a session $_SESSION['loggedin']
to true otherwise false is returned.

1. public function login($username,$password){


2.
3.
4.
5.
6.
7.

$hashed = $this->get_user_hash($username);
if($this->password_verify($password,$hashed) == 1){
$_SESSION['loggedin'] = true;

8.
9.
10.
11.
12.
13.
14.
15.
16.
17.

return true;
}
}
<pre lang="php">
//process login form if submitted
if(isset($_POST['submit'])){
$username = $_POST['username'];
$password = $_POST['password'];

18.
19.
if($user->login($username,$password)){
20.
21.
header('Location: memberpage.php');
22.
exit;
23.
24.
} else {
25.
$error[] = 'Wrong username or password or your
account has not been activated.';
26.
}
27.
28.

}//end if submit

Logout.php
To log a user out its very easy:

1. //logout
2. $user->logout();
Once the user is logged out redirect them.

memberpage.php
Once the user is logged in redirect them to the members only page (optional). To ensure a user
can only access the page if logged in do a check:

1. //if not logged in redirect to login page


2. if(!$user->is_logged_in()){ header('Location: login.php'); }
In this example their is not a lot to the members page namely:

1. <h2>Member only page</h2>


2. <p><a href='logout.php'>Logout</a></p>

reset.php
every system need the ability to reset a password in case it's forgotten, how this will work is a
user enters their email address, a check is made to make sure its belongs to a user.
Next a token is created and saved to the users record, an email is sent to them containing a link
to when clicked the token from the link is verified, if it passed the user is provided with a form to
enter their new password, its then saved to the database.
This may seem like a long winded approach but it does prevent the password being sent by
email which is not recommended.
To start with the form:

1. <form role="form" method="post" action="" autocomplete="off">


2.
<div class="form-group">
3.
<input type="email" name="email" id="email"
class="form-control input-lg" placeholder="Email" value=""
tabindex="1">
4.
</div>
5.
6.
<hr>
7.
8.

<div class="row">
<div class="col-xs-6 col-md-6"><input type="submit"
name="submit" value="Sent Reset Link" class="btn btn-primary btnblock btn-lg" tabindex="2"></div>
9.
</div>
10.
</form>

If their is an $_GET['action'] show the correct message

1. <?php
2. if(isset($_GET['action'])){
3.
4.
//check the action
5.
switch ($_GET['action']) {
6.
case 'active':
7.
echo "<h2 class='bg-success'>Your account is
now active you may now log in.</h2>";
8.
break;
9.
case 'reset':
10.
echo "<h2 class='bg-success'>Please
check your inbox for a reset link.</h2>";
11.
break;
12.
}
13.
}
14.
?>
Next process the form ensure the email matches a user:

1. //email validation
2. if(!filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)){
3.
$error[] = 'Please enter a valid email address';
4. } else {
5.
$stmt = $db->prepare('SELECT email FROM members WHERE email =
:email');
6.
$stmt->execute(array(':email' => $_POST['email']));
7.
$row = $stmt->fetch(PDO::FETCH_ASSOC);
8.
9.
if(empty($row['email'])){
10.
recognised.';
11.
}
12.
13.
}

$error[] = 'Email provided is not on

Create the token

1. //create the activation code


2. $token = md5(uniqid(rand(),true));
Next update the users record and set resetToken to the value of the token and resetComplete to
No that will be needed if the link is clicked and password has been changed. Send an email to
the user containing a link that points to resetPassword.php?key=$token passing the token.

1. $stmt = $db->prepare("UPDATE members SET resetToken = :token,


resetComplete='No' WHERE email = :email");
2. $stmt->execute(array(
3.
':email' => $row['email'],
4.
':token' => $token
5. ));
6.
7. //send email
8. $to = $row['email'];
9. $subject = "Password Reset";
10.
$body = "Someone requested that the password be reset. nnIf
this was a mistake, just ignore this email and nothing will
happen.nnTo reset your password, visit the following address:
".DIR."resetPassword.php?key=$token";
11.
$additionalheaders = "From: <".SITEEMAIL.">rn";
12.
$additionalheaders .= "Reply-To: $".SITEEMAIL."";
13.
mail($to, $subject, $body, $additionalheaders);
14.
15.
//redirect to index page
16.
header('Location: login.php?action=reset');
17.
exit;

resetPassword.php
First check the token been passed to the page matches a user

1. $stmt = $db->prepare('SELECT resetToken, resetComplete FROM


members WHERE resetToken = :token');

2.
3.
4.
5.
6.
7.

$stmt->execute(array(':token' => $_GET['key']));


$row = $stmt->fetch(PDO::FETCH_ASSOC);

//if no token from db then kill the page


if(empty($row['resetToken'])){
$stop = 'Invalid token provided, please use the link provided
in the reset email.';
8. } elseif($row['resetComplete'] == 'Yes') {
9.
$stop = 'Your password has already been changed!';
10.
}
If $stop has been set then display that

1. if(isset($stop)){
2.
echo "<p class='bg-danger'>$stop</p>";
3. }
If no errors have been created show a form to change the password

1. <form role="form" method="post" action="" autocomplete="off">


2.
3.
4.
5.

6.
7.
8.
9.

<div class="row">
<div class="col-xs-6 col-sm-6 col-md-6">
<div class="form-group">
<input type="password" name="password"
id="password" class="form-control input-lg" placeholder="Password"
tabindex="1">
</div>
</div>
<div class="col-xs-6 col-sm-6 col-md-6">
<div class="form-group">

10.
<input type="password"
name="passwordConfirm" id="passwordConfirm" class="form-control
input-lg" placeholder="Confirm Password" tabindex="1">
11.
</div>
12.
</div>
13.
</div>
14.

15.
<hr>
16.
<div class="row">
17.
<div class="col-xs-6 col-md-6"><input
type="submit" name="submit" value="Change Password" class="btn
btn-primary btn-block btn-lg" tabindex="3"></div>
18.
</div>
19.
</form>
Once the form has been submitted validate the data then hash the password update the users
row and set resetComplete to Yes to indicate the process is finished if the reset link is clicked
again from email the process will be halted.

1.
2. //if form has been submitted process it
3. if(isset($_POST['submit'])){
4.
5.
//basic validation
6.
if(strlen($_POST['password']) < 3){
7.
$error[] = 'Password is too short.';
8.
}
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.

if(strlen($_POST['passwordConfirm']) < 3){


$error[] = 'Confirm password is too short.';
}
if($_POST['password'] != $_POST['passwordConfirm']){
$error[] = 'Passwords do not match.';
}
//if no errors have been created carry on
if(!isset($error)){

20.
21.
//hash the password
22.
$hashedpassword = $user>password_hash($_POST['password'], PASSWORD_BCRYPT);
23.
24.
try {

25.
26.
$stmt = $db->prepare("UPDATE members SET
password = :hashedpassword, resetComplete = 'Yes' WHERE
resetToken = :token");
27.
$stmt->execute(array(
28.
':hashedpassword' =>
$hashedpassword,
29.
':token' => $row['resetToken']
30.
));
31.
32.
//redirect to index page
33.
header('Location:
login.php?action=resetAccount');
34.
exit;
35.
36.
//else catch the exception and show the error.
37.
} catch(PDOException $e) {
38.
$error[] = $e->getMessage();
39.
}
40.
41.
}
42.
43.

Conclusion
That covers the foundations, this can be used as a starting point to build members based sites or
even a start to an admin panel

A PHP login script (ADVANCED VERSION)


A simple, but secure PHP login script. Similar to minimal version, but much more
features: PDO, Register, login, logout, email verification, password reset, edit user
data, gravatars, captchas, remember me / stay logged in cookies, "remember me"
supports parallel login from multiple devices, login with email,

i18n/internationalization, mail sending via PHPMailer (SMTP or PHP's mail()


function/linux sendmail). Uses the ultra-modern & future-proof PHP 5.5. BLOWFISH
hashing/salting functions (includes the official PHP 5.3 & PHP 5.4 compatibility pack,
which makes those functions available in those versions too).

Please also note: This version is not maintained anymore. The php-login
project will focus on developing the Professional MVC Version and highly
recommends you to also use that version.
Follow the project on Twitter, Facebook or Google+ and have a look on the official
support blog Dev Metal. Ask questions in the Official Support Forum.
This script is part of the php-login project, a collection of 4 different login
scripts. See php-login.net for more info.
1. One-file version: Full login script in one file. Uses a one-file SQLite database
(no MySQL needed) and PDO. Features: Register, login,
logout. https://github.com/panique/php-login-one-file
2. Minimal version All the basic functions in a clean file structure, uses MySQL
and mysqli. Register, login, logout. https://github.com/panique/php-loginminimal
3. Advanced version Similar to the minimal version, but full of features. Uses
PDO, Captchas, mail sending via SMTP and much
more. https://github.com/panique/php-login-advanced
4. Professional version Everything comes with a professional MVC framework
structure, perfect for building real applications. Additional features like: URL
rewriting, professional usage of controllers and actions, PDO, MySQL, mail
sending via PHPMailer (SMTP or PHP's mail() function/linux sendmail), user

profile pages, public user profiles, gravatars and local avatars, account
upgrade/downgrade etc., login via Facebook, Composer integration,
etc.https://github.com/panique/php-login

Live-demo
Live demo here, live demo's phpinfo(). here

Requirements

PHP 5.3.7+

MySQL 5 database (please use a modern version of MySQL (5.5, 5.6, 5.7) as
very old versions have a exotic bug that makes PDO injections possible.

activated PHP's GD graphic functions (the tutorial shows how)

enabled OpenSSL module (the tutorial shows how)

this version uses mail sending, so you need to have an SMTP mail sending
account somewhere OR you know how to get linux's sendmail etc. to run.
As it's nearly impossible to send real mails with PHP's mail() function (due to
anti-spam blocking of nearly every major mail provider in the world) you
should really use SMTP mail sending.

Installation (quick setup)

1. create database login and table users via the SQL statements in
the _installation folder.

2. in config/config.php, change mySQL user and password


(DB_USER and DB_PASS).

3. in config/config.php, change COOKIE_DOMAIN to your domain name


(and don't forget to put the dot in front of the domain!)

4. in config/config.php, change COOKIE_SECRET_KEY to a random string.


this will make your cookies more secure

5. change the URL part of EMAIL_PASSWORDRESET_URL and


EMAIL_VERIFICATION_URL inconfig/config.php to your URL! You need to
provide the URL of your project here to link to your project from within
verification/password reset mails.

i.

as this version uses email sending, you'll need to a) provide an SMTP


account in the config OR b) install a mail server tool on your server.
Using a real SMTP provider (like SMTP2GOetc.) is highly
recommended. Sending emails manually via mail() is something for
hardcore admins. Usually mails sent via mail() will never reach the
receiver. Please also don't try weird Gmail setups, this can fail to a lot
of reasons. Get professional and send mails like mail should be sent.
It's extremely cheap and works.

To enable OpenSSL, do sudo apt-get install openssl (and restart the


apache via sudo service apache2 restart)

To enable PHP's GD graphic functions, do sudo apt-get install php5gd (and restart the apache via sudo service apache2 restart)

Installation (very detailed setup)


A very detailed guideline on how to install the script here in this blog post.

Troubleshooting & useful stuff


Please use a real SMTP provider for sending mail. Using something like gmail.com
or even trying to send mails via mail() will bring you into a lot of problems (unless you
really really know what you are doing). Sending mails is a huge topic. But if you still
want to use Gmail: Gmail is very popular as an SMTP mail sending service and
would work for smaller projects, but sometimes gmail.com will not send mails
anymore, usually because of:
1. "SMTP Connect error": PHPMailer says "smtp login failed", but login is
correct: Gmail.com thinks you are a spammer. You'll need to "unlock" your
application for gmail.com by logging into your gmail account via your browser,
go to http://www.google.com/accounts/DisplayUnlockCaptchaand then, within
the next 10minutes, send an email via your app. Gmail will then white-list your
app server. Have a look here for full
explanaition: https://support.google.com/mail/answer/14257?p=client_login&rd
=1
2. "SMTP data quota exceeded": gmail blocks you because you have sent more
than 500 mails per day (?) or because your users have provided too much

fake email addresses. The only way to get around this is renting professional
SMTP mail sending, prices are okay, 10.000 mails for $5.

Security notice
This script comes with a handy .htaccess in the views folder that denies direct
access to the files within the folder (so that people cannot render the views directly).
However, these .htaccess files only work if you have set AllowOverride to All in your
apache vhost configs. There are lots of tutorials on the web on how to do this.

How this script works


If you look into the code and at the file/folder-structure everything should be selfexplaining.
Please note: This version is not maintained anymore. The php-login project will focus
on developing the Professional MVC Version and highly recommends you to also
use that version.

Useful links

How to use PDO

A little guideline on how to use the PHP 5.5 password hashing functions and
its "library plugin" based PHP 5.3 & 5.4 implementation

How to setup latest version of PHP 5.5 on Ubuntu 12.04 LTS. Same for
Debian 7.0 / 7.1:

How to setup latest version of PHP 5.5 on Debian Wheezy 7.0/7.1 (and how
to fix the GPG key error)

Notes on password & hashing salting in upcoming PHP versions (PHP 5.5.x &
5.6 etc.)

Some basic "benchmarks" of all PHP hash/salt algorithms

Themes / User Interfaces / Styles


Bookmark the highly related partner-project "php-login-styles" which will host
beautiful themes for all the php-login versions. Currently this is only a placeholder,
the project starts in 2014.

License
Licensed under MIT. You can use this script for free for any private or commercial
projects.

Contribute
This script is not developed any further, so only commit bugfixes, not new features. If
you want to add new features etc, please contribute into
the https://github.com/panique/php-login repo. Please commit only
in develop branch. The master branch will always contain the stable version.

Support / Donate
If you think this script is useful and saves you a lot of work, then think about
supporting the project:
1. Rent your next server at A2 Hosting or DigitalOcean.
2. Donate via PayPal or GitTip
3. Contribute to this project.