| @@ -1,88 +1,105 @@ | ||
| <?php | ||
| /** | ||
| * Class registration | ||
| * handles the user registration | ||
| */ | ||
| class Registration | ||
| { | ||
| /** | ||
| * @var object $db_connection The database connection | ||
| */ | ||
| private $db_connection = null; | ||
| /** | ||
| * @var array $errors Collection of error messages | ||
| */ | ||
| public $errors = array(); | ||
| /** | ||
| * @var array $messages Collection of success / neutral messages | ||
| */ | ||
| public $messages = array(); | ||
| /** | ||
| * the function "__construct()" automatically starts whenever an object of this class is created, | ||
| * you know, when you do "$registration = new Registration();" | ||
| */ | ||
| public function __construct() | ||
| { | ||
| if (isset($_POST["register"])) { | ||
| $this->registerNewUser(); | ||
| } | ||
| } | ||
| /** | ||
| * handles the entire registration process. checks all error possibilities | ||
| * and creates a new user in the database if everything is fine | ||
| */ | ||
| private function registerNewUser() | ||
| { | ||
| if (empty($_POST['user_name'])) { | ||
| $this->errors[] = "Empty Username"; | ||
| } elseif (empty($_POST['user_password_new']) || empty($_POST['user_password_repeat'])) { | ||
| $this->errors[] = "Empty Password"; | ||
| } elseif ($_POST['user_password_new'] !== $_POST['user_password_repeat']) { | ||
| $this->errors[] = "Password and password repeat are not the same"; | ||
| } elseif (strlen($_POST['user_password_new']) < 6) { | ||
| $this->errors[] = "Password has a minimum length of 6 characters"; | ||
| } elseif (strlen($_POST['user_name']) > 64 || strlen($_POST['user_name']) < 2) { | ||
| $this->errors[] = "Username cannot be shorter than 2 or longer than 64 characters"; | ||
| } elseif (!preg_match('/^[a-z\d]{2,64}$/i', $_POST['user_name'])) { | ||
| $this->errors[] = "Username does not fit the name scheme: only a-Z and numbers are allowed, 2 to 64 characters"; | ||
| } elseif (empty($_POST['user_email'])) { | ||
| $this->errors[] = "Email cannot be empty"; | ||
| } elseif (strlen($_POST['user_email']) > 64) { | ||
| $this->errors[] = "Email cannot be longer than 64 characters"; | ||
| } elseif (!filter_var($_POST['user_email'], FILTER_VALIDATE_EMAIL)) { | ||
| $this->errors[] = "Your email address is not in a valid email format"; | ||
| } elseif (!empty($_POST['user_name']) | ||
| && strlen($_POST['user_name']) <= 64 | ||
| && strlen($_POST['user_name']) >= 2 | ||
| && preg_match('/^[a-z\d]{2,64}$/i', $_POST['user_name']) | ||
| && !empty($_POST['user_email']) | ||
| && strlen($_POST['user_email']) <= 64 | ||
| && filter_var($_POST['user_email'], FILTER_VALIDATE_EMAIL) | ||
| && !empty($_POST['user_password_new']) | ||
| && !empty($_POST['user_password_repeat']) | ||
| && ($_POST['user_password_new'] === $_POST['user_password_repeat']) | ||
| ) { | ||
| // create a database connection | ||
| $this->db_connection = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME); | ||
| // change character set to utf8 and check it | ||
| if (!$this->db_connection->set_charset("utf8")) { | ||
| $this->errors[] = $this->db_connection->error; | ||
| } | ||
| // if no connection errors (= working database connection) | ||
| if (!$this->db_connection->connect_errno) { | ||
| // escaping, additionally removing everything that could be (html/javascript-) code | ||
| $user_name = $this->db_connection->real_escape_string(strip_tags($_POST['user_name'], ENT_QUOTES)); | ||
| $user_email = $this->db_connection->real_escape_string(strip_tags($_POST['user_email'], ENT_QUOTES)); | ||
| $user_password = $_POST['user_password_new']; | ||
| // crypt the user's password with PHP 5.5's password_hash() function, results in a 60 character | ||
| // hash string. the PASSWORD_DEFAULT constant is defined by the PHP 5.5, or if you are using | ||
| // PHP 5.3/5.4, by the password hashing compatibility library | ||
| $user_password_hash = password_hash($user_password, PASSWORD_DEFAULT); | ||
| // check if user or email address already exists | ||
| $sql = "SELECT * FROM users WHERE user_name = '" . $user_name . "' OR user_email = '" . $user_email . "';"; | ||
| $query_check_user_name = $this->db_connection->query($sql); | ||
| if ($query_check_user_name->num_rows == 1) { | ||
| $this->errors[] = "Sorry, that username / email address is already taken."; | ||
| } else { | ||
| // write new user's data into database | ||
| $sql = "INSERT INTO users (user_name, user_password_hash, user_email) | ||
| VALUES('" . $user_name . "', '" . $user_password_hash . "', '" . $user_email . "');"; | ||
| $query_new_user_insert = $this->db_connection->query($sql); | ||
| // if user has been added successfully | ||
| if ($query_new_user_insert) { | ||
| $this->messages[] = "Your account has been created successfully. You can now log in."; | ||
| } else { | ||
| $this->errors[] = "Sorry, your registration failed. Please go back and try again."; | ||
| } | ||
| } | ||
| } else { | ||
| $this->errors[] = "Sorry, no database connection."; | ||
| } | ||
| } else { | ||
| $this->errors[] = "An unknown error occurred."; | ||
| } | ||
| } | ||
| } |
| @@ -0,0 +1,78 @@ | ||
| # php-login-minimal | ||
|
|
||
| A simple, but secure PHP login script. 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 these versions too). | ||
|
|
||
| ## Why does this script exist ? | ||
|
|
||
| In the PHP world every beginner tries to build login systems from scratch, doing all the typical mistakes, usually going from saving plain text passwords to using (horribly wrong) MD5 hashing. This script tries to give beginners a usable code base with a fully implemented user authentication ("login") system, preventing less-experienced developers at least from the worst security issues. | ||
|
|
||
| This script was originally part of the "php-login project", a collection of 4 different login scripts made in the 2012-2013 PHP era to give especially beginners and security-inexperienced users a set of basic auth functions that fitted the most modern password hashing standards possible. You know, this was the time when even major companies like SONY and LinkedIn used horrible outdated MD5-hashing for their passwords (or even saved everything in plain text) and when the big PHP frameworks didn't have proper user auth solution out-of-the-box. | ||
|
|
||
| [](https://affiliates.host1plus.com/ref/devmetal/36f4d828.html) | ||
|
|
||
| Find the other versions here: | ||
|
|
||
| **One-file version** (not maintained anymore) | ||
| Full login script in one file. Uses a one-file SQLite database (no MySQL needed) and PDO: Register, login, logout. | ||
| https://github.com/panique/php-login-one-file | ||
|
|
||
| **Minimal version** (not maintained anymore) | ||
| All the basic functions in a clean file structure, uses MySQL and mysqli. Register, login, logout. | ||
| https://github.com/panique/php-login-minimal | ||
|
|
||
| **Advanced version** (not maintained anymore) | ||
| 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 | ||
|
|
||
| **HUGE (professional version)** | ||
| Quite professional MVC framework structure, useful for real applications. Additional features like: URL rewriting, 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., OAuth2, Composer integration, etc. | ||
| https://github.com/panique/huge | ||
|
|
||
| ## 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](http://stackoverflow.com/q/134099/1114320). | ||
| - activated mysqli (last letter is an "i") extension (activated by default on most server setups) | ||
|
|
||
| ## Installation (quick setup) | ||
|
|
||
| Create a database *login* and the table *users* via the SQL statements in the `_install` folder. | ||
| Change mySQL database user and password in `config/db.php` (*DB_USER* and *DB_PASS*). | ||
|
|
||
| ## Installation (detailed setup tutorials) | ||
|
|
||
| - [Detailed tutorial for installation on Ubuntu 12.04 LTS](http://www.dev-metal.com/install-php-login-nets-1-minimal-login-script-ubuntu/) | ||
| - [Detailed tutorial for installation on Windows 7 and 8 (useful for development)](http://www.dev-metal.com/how-to-install-php-login-minimal-on-windows-7-8/) | ||
|
|
||
| ## 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. | ||
|
|
||
| ## Useful links | ||
|
|
||
| - [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](http://www.dev-metal.com/use-php-5-5-password-hashing-functions/) | ||
| - [How to setup latest version of PHP 5.5 on Ubuntu 12.04 LTS](http://www.dev-metal.com/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)](http://www.dev-metal.com/setup-latest-version-php-5-5-debian-wheezy-7-07-1-fix-gpg-key-error/) | ||
| - [Notes on password & hashing salting in upcoming PHP versions (PHP 5.5.x & 5.6 etc.)](https://github.com/panique/php-login/wiki/Notes-on-password-&-hashing-salting-in-upcoming-PHP-versions-%28PHP-5.5.x-&-5.6-etc.%29) | ||
| - [Some basic "benchmarks" of all PHP hash/salt algorithms](https://github.com/panique/php-login/wiki/Which-hashing-&-salting-algorithm-should-be-used-%3F) | ||
|
|
||
| ## License | ||
|
|
||
| Licensed under [MIT](http://www.opensource.org/licenses/mit-license.php). You can use this script for free for any | ||
| private or commercial projects. | ||
|
|
||
| ## Contribute | ||
|
|
||
| Please create a feature-branch if possible when committing to the project, if not then simply commit to master branch. | ||
|
|
||
| ## Support | ||
|
|
||
| If you think this script is useful and saves you a lot of work, then think about supporting the project by renting | ||
| a server at [HOST1PLUS](https://affiliates.host1plus.com/ref/devmetal/36f4d828.html). | ||
|
|
||
| ## I'm blogging... | ||
|
|
||
| at **[DEV METAL](http://www.dev-metal.com)**, mostly about PHP and IT-related stuff. Have a look if you like. |
| @@ -0,0 +1 @@ | ||
| CREATE DATABASE IF NOT EXISTS `login`; |
| @@ -0,0 +1,9 @@ | ||
| CREATE TABLE IF NOT EXISTS `login`.`users` ( | ||
| `user_id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'auto incrementing user_id of each user, unique index', | ||
| `user_name` varchar(64) COLLATE utf8_unicode_ci NOT NULL COMMENT 'user''s name, unique', | ||
| `user_password_hash` varchar(255) COLLATE utf8_unicode_ci NOT NULL COMMENT 'user''s password in salted and hashed format', | ||
| `user_email` varchar(64) COLLATE utf8_unicode_ci NOT NULL COMMENT 'user''s email, unique', | ||
| PRIMARY KEY (`user_id`), | ||
| UNIQUE KEY `user_name` (`user_name`), | ||
| UNIQUE KEY `user_email` (`user_email`) | ||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='user data'; |
| @@ -0,0 +1,128 @@ | ||
| <?php | ||
|
|
||
| /** | ||
| * Class login | ||
| * handles the user's login and logout process | ||
| */ | ||
| class Login | ||
| { | ||
| /** | ||
| * @var object The database connection | ||
| */ | ||
| private $db_connection = null; | ||
| /** | ||
| * @var array Collection of error messages | ||
| */ | ||
| public $errors = array(); | ||
| /** | ||
| * @var array Collection of success / neutral messages | ||
| */ | ||
| public $messages = array(); | ||
|
|
||
| /** | ||
| * the function "__construct()" automatically starts whenever an object of this class is created, | ||
| * you know, when you do "$login = new Login();" | ||
| */ | ||
| public function __construct() | ||
| { | ||
| // create/read session, absolutely necessary | ||
| session_start(); | ||
|
|
||
| // check the possible login actions: | ||
| // if user tried to log out (happen when user clicks logout button) | ||
| if (isset($_GET["logout"])) { | ||
| $this->doLogout(); | ||
| } | ||
| // login via post data (if user just submitted a login form) | ||
| elseif (isset($_POST["login"])) { | ||
| echo "<p>Woot</p>"; | ||
| // $this->dologinWithPostData(); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * log in with post data | ||
| */ | ||
| private function dologinWithPostData() | ||
| { | ||
| // check login form contents | ||
| if (empty($_POST['user_name'])) { | ||
| $this->errors[] = "Username field was empty."; | ||
| } elseif (empty($_POST['user_password'])) { | ||
| $this->errors[] = "Password field was empty."; | ||
| } elseif (!empty($_POST['user_name']) && !empty($_POST['user_password'])) { | ||
|
|
||
| // create a database connection, using the constants from config/db.php (which we loaded in index.php) | ||
| $this->db_connection = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME); | ||
|
|
||
| // change character set to utf8 and check it | ||
| if (!$this->db_connection->set_charset("utf8")) { | ||
| $this->errors[] = $this->db_connection->error; | ||
| } | ||
|
|
||
| // if no connection errors (= working database connection) | ||
| if (!$this->db_connection->connect_errno) { | ||
|
|
||
| // escape the POST stuff | ||
| $user_name = $this->db_connection->real_escape_string($_POST['user_name']); | ||
|
|
||
| // database query, getting all the info of the selected user (allows login via email address in the | ||
| // username field) | ||
| $sql = "SELECT user_name, user_email, user_password_hash | ||
| FROM users | ||
| WHERE user_name = '" . $user_name . "' OR user_email = '" . $user_name . "';"; | ||
| $result_of_login_check = $this->db_connection->query($sql); | ||
|
|
||
| // if this user exists | ||
| if ($result_of_login_check->num_rows == 1) { | ||
|
|
||
| // get result row (as an object) | ||
| $result_row = $result_of_login_check->fetch_object(); | ||
|
|
||
| // using PHP 5.5's password_verify() function to check if the provided password fits | ||
| // the hash of that user's password | ||
| if (password_verify($_POST['user_password'], $result_row->user_password_hash)) { | ||
|
|
||
| // write user data into PHP SESSION (a file on your server) | ||
| $_SESSION['user_name'] = $result_row->user_name; | ||
| $_SESSION['user_email'] = $result_row->user_email; | ||
| $_SESSION['user_login_status'] = 1; | ||
|
|
||
| } else { | ||
| $this->errors[] = "Wrong password. Try again."; | ||
| } | ||
| } else { | ||
| $this->errors[] = "This user does not exist."; | ||
| } | ||
| } else { | ||
| $this->errors[] = "Database connection problem."; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * perform the logout | ||
| */ | ||
| public function doLogout() | ||
| { | ||
| // delete the session of the user | ||
| $_SESSION = array(); | ||
| session_destroy(); | ||
| // return a little feeedback message | ||
| $this->messages[] = "You have been logged out."; | ||
|
|
||
| } | ||
|
|
||
| /** | ||
| * simply return the current state of the user's login | ||
| * @return boolean user's login status | ||
| */ | ||
| public function isUserLoggedIn() | ||
| { | ||
| if (isset($_SESSION['user_login_status']) AND $_SESSION['user_login_status'] == 1) { | ||
| return true; | ||
| } | ||
| // default return | ||
| return false; | ||
| } | ||
| } |
| @@ -0,0 +1,116 @@ | ||
| <?php | ||
|
|
||
| /** | ||
| * Class registration | ||
| * handles the user registration | ||
| */ | ||
| class Registration | ||
| { | ||
| /** | ||
| * @var object $db_connection The database connection | ||
| */ | ||
| private $db_connection = null; | ||
| /** | ||
| * @var array $errors Collection of error messages | ||
| */ | ||
| public $errors = array(); | ||
| /** | ||
| * @var array $messages Collection of success / neutral messages | ||
| */ | ||
| public $messages = array(); | ||
|
|
||
| /** | ||
| * the function "__construct()" automatically starts whenever an object of this class is created, | ||
| * you know, when you do "$registration = new Registration();" | ||
| */ | ||
| public function __construct() | ||
| { | ||
| if (isset($_POST["register"])) { | ||
| $this->registerNewUser(); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * handles the entire registration process. checks all error possibilities | ||
| * and creates a new user in the database if everything is fine | ||
| */ | ||
| private function registerNewUser() | ||
| { | ||
| if (empty($_POST['user_name'])) { | ||
| $this->errors[] = "Empty Username"; | ||
| } elseif (empty($_POST['user_password_new']) || empty($_POST['user_password_repeat'])) { | ||
| $this->errors[] = "Empty Password"; | ||
| } elseif ($_POST['user_password_new'] !== $_POST['user_password_repeat']) { | ||
| $this->errors[] = "Password and password repeat are not the same"; | ||
| } elseif (strlen($_POST['user_password_new']) < 6) { | ||
| $this->errors[] = "Password has a minimum length of 6 characters"; | ||
| } elseif (strlen($_POST['user_name']) > 64 || strlen($_POST['user_name']) < 2) { | ||
| $this->errors[] = "Username cannot be shorter than 2 or longer than 64 characters"; | ||
| } elseif (!preg_match('/^[a-z\d]{2,64}$/i', $_POST['user_name'])) { | ||
| $this->errors[] = "Username does not fit the name scheme: only a-Z and numbers are allowed, 2 to 64 characters"; | ||
| } elseif (empty($_POST['user_email'])) { | ||
| $this->errors[] = "Email cannot be empty"; | ||
| } elseif (strlen($_POST['user_email']) > 64) { | ||
| $this->errors[] = "Email cannot be longer than 64 characters"; | ||
| } elseif (!filter_var($_POST['user_email'], FILTER_VALIDATE_EMAIL)) { | ||
| $this->errors[] = "Your email address is not in a valid email format"; | ||
| } elseif (!empty($_POST['user_name']) | ||
| && strlen($_POST['user_name']) <= 64 | ||
| && strlen($_POST['user_name']) >= 2 | ||
| && preg_match('/^[a-z\d]{2,64}$/i', $_POST['user_name']) | ||
| && !empty($_POST['user_email']) | ||
| && strlen($_POST['user_email']) <= 64 | ||
| && filter_var($_POST['user_email'], FILTER_VALIDATE_EMAIL) | ||
| && !empty($_POST['user_password_new']) | ||
| && !empty($_POST['user_password_repeat']) | ||
| && ($_POST['user_password_new'] === $_POST['user_password_repeat']) | ||
| ) { | ||
| // create a database connection | ||
| $this->db_connection = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME); | ||
|
|
||
| // change character set to utf8 and check it | ||
| if (!$this->db_connection->set_charset("utf8")) { | ||
| $this->errors[] = $this->db_connection->error; | ||
| } | ||
|
|
||
| // if no connection errors (= working database connection) | ||
| if (!$this->db_connection->connect_errno) { | ||
|
|
||
| // escaping, additionally removing everything that could be (html/javascript-) code | ||
| $user_name = $this->db_connection->real_escape_string(strip_tags($_POST['user_name'], ENT_QUOTES)); | ||
| $user_email = $this->db_connection->real_escape_string(strip_tags($_POST['user_email'], ENT_QUOTES)); | ||
|
|
||
| $user_password = $_POST['user_password_new']; | ||
|
|
||
| // crypt the user's password with PHP 5.5's password_hash() function, results in a 60 character | ||
| // hash string. the PASSWORD_DEFAULT constant is defined by the PHP 5.5, or if you are using | ||
| // PHP 5.3/5.4, by the password hashing compatibility library | ||
| $user_password_hash = password_hash($user_password, PASSWORD_DEFAULT); | ||
|
|
||
| // check if user or email address already exists | ||
| $sql = "SELECT * FROM users WHERE user_name = '" . $user_name . "' OR user_email = '" . $user_email . "';"; | ||
| $query_check_user_name = $this->db_connection->query($sql); | ||
|
|
||
| if ($query_check_user_name->num_rows == 1) { | ||
| $this->errors[] = "Sorry, that username / email address is already taken."; | ||
| } else { | ||
| // write new user's data into database | ||
| $sql = "INSERT INTO users (user_name, user_password_hash, user_email) | ||
| VALUES('" . $user_name . "', '" . $user_password_hash . "', '" . $user_email . "');"; | ||
| $query_new_user_insert = $this->db_connection->query($sql); | ||
|
|
||
| // if user has been added successfully | ||
| if ($query_new_user_insert) { | ||
| $this->messages[] = "Your account has been created successfully. You can now log in."; | ||
| } else { | ||
| $this->errors[] = "Sorry, your registration failed. Please go back and try again."; | ||
| } | ||
| } | ||
| } else { | ||
| $this->errors[] = "Sorry, no database connection."; | ||
| } | ||
| } else { | ||
| $this->errors[] = "An unknown error occurred."; | ||
| } | ||
| } | ||
| } |
| @@ -0,0 +1,17 @@ | ||
| <?php | ||
|
|
||
| /** | ||
| * Configuration for: Database Connection | ||
| * | ||
| * For more information about constants please @see http://php.net/manual/en/function.define.php | ||
| * If you want to know why we use "define" instead of "const" @see http://stackoverflow.com/q/2447791/1114320 | ||
| * | ||
| * DB_HOST: database host, usually it's "127.0.0.1" or "localhost", some servers also need port info | ||
| * DB_NAME: name of the database. please note: database and database table are not the same thing | ||
| * DB_USER: user for your database. the user needs to have rights for SELECT, UPDATE, DELETE and INSERT. | ||
| * DB_PASS: the password of the above user | ||
| */ | ||
| define("DB_HOST", "127.0.0.1"); | ||
| define("DB_NAME", "login"); | ||
| define("DB_USER", "root"); | ||
| define("DB_PASS", "mysql"); |
| @@ -0,0 +1,43 @@ | ||
| <?php | ||
|
|
||
| /** | ||
| * A simple, clean and secure PHP Login Script / MINIMAL VERSION | ||
| * For more versions (one-file, advanced, framework-like) visit http://www.php-login.net | ||
| * | ||
| * Uses PHP SESSIONS, modern password-hashing and salting and gives the basic functions a proper login system needs. | ||
| * | ||
| * @author Panique | ||
| * @link https://github.com/panique/php-login-minimal/ | ||
| * @license http://opensource.org/licenses/MIT MIT License | ||
| */ | ||
|
|
||
| // checking for minimum PHP version | ||
| if (version_compare(PHP_VERSION, '5.3.7', '<')) { | ||
| exit("Sorry, Simple PHP Login does not run on a PHP version smaller than 5.3.7 !"); | ||
| } else if (version_compare(PHP_VERSION, '5.5.0', '<')) { | ||
| // if you are using PHP 5.3 or PHP 5.4 you have to include the password_api_compatibility_library.php | ||
| // (this library adds the PHP 5.5 password hashing functions to older versions of PHP) | ||
| require_once("libraries/password_compatibility_library.php"); | ||
| } | ||
|
|
||
| // include the configs / constants for the database connection | ||
| require_once("config/db.php"); | ||
|
|
||
| // load the login class | ||
| require_once("classes/Login.php"); | ||
|
|
||
| // create a login object. when this object is created, it will do all login/logout stuff automatically | ||
| // so this single line handles the entire login process. in consequence, you can simply ... | ||
| $login = new Login(); | ||
|
|
||
| // ... ask if we are logged in here: | ||
| if ($login->isUserLoggedIn() == true) { | ||
| // the user is logged in. you can do whatever you want here. | ||
| // for demonstration purposes, we simply show the "you are logged in" view. | ||
| include("views/logged_in.php"); | ||
|
|
||
| } else { | ||
| // the user is not logged in. you can do whatever you want here. | ||
| // for demonstration purposes, we simply show the "you are not logged in" view. | ||
| include("views/not_logged_in.php"); | ||
| } |
| @@ -0,0 +1,222 @@ | ||
| <?php | ||
| /** | ||
| * A Compatibility library with PHP 5.5's simplified password hashing API. | ||
| * | ||
| * @author Anthony Ferrara <ircmaxell@php.net> | ||
| * @license http://www.opensource.org/licenses/mit-license.html MIT License | ||
| * @copyright 2012 The Authors | ||
| */ | ||
|
|
||
| if (!defined('PASSWORD_DEFAULT')) { | ||
|
|
||
| define('PASSWORD_BCRYPT', 1); | ||
| define('PASSWORD_DEFAULT', PASSWORD_BCRYPT); | ||
|
|
||
| /** | ||
| * Hash the password using the specified algorithm | ||
| * | ||
| * @param string $password The password to hash | ||
| * @param int $algo The algorithm to use (Defined by PASSWORD_* constants) | ||
| * @param array $options The options for the algorithm to use | ||
| * | ||
| * @return string|false The hashed password, or false on error. | ||
| */ | ||
| function password_hash($password, $algo, array $options = array()) { | ||
| if (!function_exists('crypt')) { | ||
| trigger_error("Crypt must be loaded for password_hash to function", E_USER_WARNING); | ||
| return null; | ||
| } | ||
| if (!is_string($password)) { | ||
| trigger_error("password_hash(): Password must be a string", E_USER_WARNING); | ||
| return null; | ||
| } | ||
| if (!is_int($algo)) { | ||
| trigger_error("password_hash() expects parameter 2 to be long, " . gettype($algo) . " given", E_USER_WARNING); | ||
| return null; | ||
| } | ||
| switch ($algo) { | ||
| case PASSWORD_BCRYPT: | ||
| // Note that this is a C constant, but not exposed to PHP, so we don't define it here. | ||
| $cost = 10; | ||
| if (isset($options['cost'])) { | ||
| $cost = $options['cost']; | ||
| if ($cost < 4 || $cost > 31) { | ||
| trigger_error(sprintf("password_hash(): Invalid bcrypt cost parameter specified: %d", $cost), E_USER_WARNING); | ||
| return null; | ||
| } | ||
| } | ||
| // The length of salt to generate | ||
| $raw_salt_len = 16; | ||
| // The length required in the final serialization | ||
| $required_salt_len = 22; | ||
| $hash_format = sprintf("$2y$%02d$", $cost); | ||
| break; | ||
| default: | ||
| trigger_error(sprintf("password_hash(): Unknown password hashing algorithm: %s", $algo), E_USER_WARNING); | ||
| return null; | ||
| } | ||
| if (isset($options['salt'])) { | ||
| switch (gettype($options['salt'])) { | ||
| case 'NULL': | ||
| case 'boolean': | ||
| case 'integer': | ||
| case 'double': | ||
| case 'string': | ||
| $salt = (string) $options['salt']; | ||
| break; | ||
| case 'object': | ||
| if (method_exists($options['salt'], '__tostring')) { | ||
| $salt = (string) $options['salt']; | ||
| break; | ||
| } | ||
| case 'array': | ||
| case 'resource': | ||
| default: | ||
| trigger_error('password_hash(): Non-string salt parameter supplied', E_USER_WARNING); | ||
| return null; | ||
| } | ||
| if (strlen($salt) < $required_salt_len) { | ||
| trigger_error(sprintf("password_hash(): Provided salt is too short: %d expecting %d", strlen($salt), $required_salt_len), E_USER_WARNING); | ||
| return null; | ||
| } elseif (0 == preg_match('#^[a-zA-Z0-9./]+$#D', $salt)) { | ||
| $salt = str_replace('+', '.', base64_encode($salt)); | ||
| } | ||
| } else { | ||
| $buffer = ''; | ||
| $buffer_valid = false; | ||
| if (function_exists('mcrypt_create_iv') && !defined('PHALANGER')) { | ||
| $buffer = mcrypt_create_iv($raw_salt_len, MCRYPT_DEV_URANDOM); | ||
| if ($buffer) { | ||
| $buffer_valid = true; | ||
| } | ||
| } | ||
| if (!$buffer_valid && function_exists('openssl_random_pseudo_bytes')) { | ||
| $buffer = openssl_random_pseudo_bytes($raw_salt_len); | ||
| if ($buffer) { | ||
| $buffer_valid = true; | ||
| } | ||
| } | ||
| if (!$buffer_valid && is_readable('/dev/urandom')) { | ||
| $f = fopen('/dev/urandom', 'r'); | ||
| $read = strlen($buffer); | ||
| while ($read < $raw_salt_len) { | ||
| $buffer .= fread($f, $raw_salt_len - $read); | ||
| $read = strlen($buffer); | ||
| } | ||
| fclose($f); | ||
| if ($read >= $raw_salt_len) { | ||
| $buffer_valid = true; | ||
| } | ||
| } | ||
| if (!$buffer_valid || strlen($buffer) < $raw_salt_len) { | ||
| $bl = strlen($buffer); | ||
| for ($i = 0; $i < $raw_salt_len; $i++) { | ||
| if ($i < $bl) { | ||
| $buffer[$i] = $buffer[$i] ^ chr(mt_rand(0, 255)); | ||
| } else { | ||
| $buffer .= chr(mt_rand(0, 255)); | ||
| } | ||
| } | ||
| } | ||
| $salt = str_replace('+', '.', base64_encode($buffer)); | ||
| } | ||
| $salt = substr($salt, 0, $required_salt_len); | ||
|
|
||
| $hash = $hash_format . $salt; | ||
|
|
||
| $ret = crypt($password, $hash); | ||
|
|
||
| if (!is_string($ret) || strlen($ret) <= 13) { | ||
| return false; | ||
| } | ||
|
|
||
| return $ret; | ||
| } | ||
|
|
||
| /** | ||
| * Get information about the password hash. Returns an array of the information | ||
| * that was used to generate the password hash. | ||
| * | ||
| * array( | ||
| * 'algo' => 1, | ||
| * 'algoName' => 'bcrypt', | ||
| * 'options' => array( | ||
| * 'cost' => 10, | ||
| * ), | ||
| * ) | ||
| * | ||
| * @param string $hash The password hash to extract info from | ||
| * | ||
| * @return array The array of information about the hash. | ||
| */ | ||
| function password_get_info($hash) { | ||
| $return = array( | ||
| 'algo' => 0, | ||
| 'algoName' => 'unknown', | ||
| 'options' => array(), | ||
| ); | ||
| if (substr($hash, 0, 4) == '$2y$' && strlen($hash) == 60) { | ||
| $return['algo'] = PASSWORD_BCRYPT; | ||
| $return['algoName'] = 'bcrypt'; | ||
| list($cost) = sscanf($hash, "$2y$%d$"); | ||
| $return['options']['cost'] = $cost; | ||
| } | ||
| return $return; | ||
| } | ||
|
|
||
| /** | ||
| * Determine if the password hash needs to be rehashed according to the options provided | ||
| * | ||
| * If the answer is true, after validating the password using password_verify, rehash it. | ||
| * | ||
| * @param string $hash The hash to test | ||
| * @param int $algo The algorithm used for new password hashes | ||
| * @param array $options The options array passed to password_hash | ||
| * | ||
| * @return boolean True if the password needs to be rehashed. | ||
| */ | ||
| function password_needs_rehash($hash, $algo, array $options = array()) { | ||
| $info = password_get_info($hash); | ||
| if ($info['algo'] != $algo) { | ||
| return true; | ||
| } | ||
| switch ($algo) { | ||
| case PASSWORD_BCRYPT: | ||
| $cost = isset($options['cost']) ? $options['cost'] : 10; | ||
| if ($cost != $info['options']['cost']) { | ||
| return true; | ||
| } | ||
| break; | ||
| } | ||
| return false; | ||
| } | ||
|
|
||
| /** | ||
| * Verify a password against a hash using a timing attack resistant approach | ||
| * | ||
| * @param string $password The password to verify | ||
| * @param string $hash The hash to verify against | ||
| * | ||
| * @return boolean If the password matches the hash | ||
| */ | ||
| function password_verify($password, $hash) { | ||
| if (!function_exists('crypt')) { | ||
| trigger_error("Crypt must be loaded for password_verify to function", E_USER_WARNING); | ||
| return false; | ||
| } | ||
| $ret = crypt($password, $hash); | ||
| if (!is_string($ret) || strlen($ret) != strlen($hash) || strlen($ret) <= 13) { | ||
| return false; | ||
| } | ||
|
|
||
| $status = 0; | ||
| for ($i = 0; $i < strlen($ret); $i++) { | ||
| $status |= (ord($ret[$i]) ^ ord($hash[$i])); | ||
| } | ||
|
|
||
| return $status === 0; | ||
| } | ||
| } | ||
|
|
||
|
|
||
|
|
| @@ -0,0 +1,34 @@ | ||
| <?php | ||
|
|
||
| /** | ||
| * A simple, clean and secure PHP Login Script / MINIMAL VERSION | ||
| * For more versions (one-file, advanced, framework-like) visit http://www.php-login.net | ||
| * | ||
| * Uses PHP SESSIONS, modern password-hashing and salting and gives the basic functions a proper login system needs. | ||
| * | ||
| * @author Panique | ||
| * @link https://github.com/panique/php-login-minimal/ | ||
| * @license http://opensource.org/licenses/MIT MIT License | ||
| */ | ||
|
|
||
| // checking for minimum PHP version | ||
| if (version_compare(PHP_VERSION, '5.3.7', '<')) { | ||
| exit("Sorry, Simple PHP Login does not run on a PHP version smaller than 5.3.7 !"); | ||
| } else if (version_compare(PHP_VERSION, '5.5.0', '<')) { | ||
| // if you are using PHP 5.3 or PHP 5.4 you have to include the password_api_compatibility_library.php | ||
| // (this library adds the PHP 5.5 password hashing functions to older versions of PHP) | ||
| require_once("libraries/password_compatibility_library.php"); | ||
| } | ||
|
|
||
| // include the configs / constants for the database connection | ||
| require_once("config/db.php"); | ||
|
|
||
| // load the registration class | ||
| require_once("classes/Registration.php"); | ||
|
|
||
| // create the registration object. when this object is created, it will do all registration stuff automatically | ||
| // so this single line handles the entire registration process. | ||
| $registration = new Registration(); | ||
|
|
||
| // show the register view (with the registration form, and messages/errors) | ||
| include("views/register.php"); |
| @@ -0,0 +1,5 @@ | ||
| # This file prevents that your .php view files are accessed directly from the outside | ||
| <Files ~ "\.(htaccess|php)$"> | ||
| order allow,deny | ||
| deny from all | ||
| </Files> |
| @@ -0,0 +1,6 @@ | ||
| <!-- if you need user information, just put them into the $_SESSION variable and output them here --> | ||
| Hey, <?php echo $_SESSION['user_name']; ?>. You are logged in. | ||
| Try to close this browser tab and open it again. Still logged in! ;) | ||
|
|
||
| <!-- because people were asking: "index.php?logout" is just my simplified form of "index.php?logout=true" --> | ||
| <a href="index.php?logout">Logout</a> |
| @@ -0,0 +1,30 @@ | ||
| <?php | ||
| // show potential errors / feedback (from login object) | ||
| if (isset($login)) { | ||
| if ($login->errors) { | ||
| foreach ($login->errors as $error) { | ||
| echo $error; | ||
| } | ||
| } | ||
| if ($login->messages) { | ||
| foreach ($login->messages as $message) { | ||
| echo $message; | ||
| } | ||
| } | ||
| } | ||
| ?> | ||
|
|
||
| <!-- login form box --> | ||
| <form method="post" action="index.php" name="loginform"> | ||
|
|
||
| <label for="login_input_username">Username</label> | ||
| <input id="login_input_username" class="login_input" type="text" name="user_name" required /> | ||
|
|
||
| <label for="login_input_password">Password</label> | ||
| <input id="login_input_password" class="login_input" type="password" name="user_password" autocomplete="off" required /> | ||
|
|
||
| <input type="submit" name="login" value="Log in" /> | ||
|
|
||
| </form> | ||
|
|
||
| <a href="register.php">Register new account</a> |
| @@ -0,0 +1,38 @@ | ||
| <?php | ||
| // show potential errors / feedback (from registration object) | ||
| if (isset($registration)) { | ||
| if ($registration->errors) { | ||
| foreach ($registration->errors as $error) { | ||
| echo $error; | ||
| } | ||
| } | ||
| if ($registration->messages) { | ||
| foreach ($registration->messages as $message) { | ||
| echo $message; | ||
| } | ||
| } | ||
| } | ||
| ?> | ||
|
|
||
| <!-- register form --> | ||
| <form method="post" action="register.php" name="registerform"> | ||
|
|
||
| <!-- the user name input field uses a HTML5 pattern check --> | ||
| <label for="login_input_username">Username (only letters and numbers, 2 to 64 characters)</label> | ||
| <input id="login_input_username" class="login_input" type="text" pattern="[a-zA-Z0-9]{2,64}" name="user_name" required /> | ||
|
|
||
| <!-- the email input field uses a HTML5 email type check --> | ||
| <label for="login_input_email">User's email</label> | ||
| <input id="login_input_email" class="login_input" type="email" name="user_email" required /> | ||
|
|
||
| <label for="login_input_password_new">Password (min. 6 characters)</label> | ||
| <input id="login_input_password_new" class="login_input" type="password" name="user_password_new" pattern=".{6,}" required autocomplete="off" /> | ||
|
|
||
| <label for="login_input_password_repeat">Repeat password</label> | ||
| <input id="login_input_password_repeat" class="login_input" type="password" name="user_password_repeat" pattern=".{6,}" required autocomplete="off" /> | ||
| <input type="submit" name="register" value="Register" /> | ||
|
|
||
| </form> | ||
|
|
||
| <!-- backlink --> | ||
| <a href="index.php">Back to Login Page</a> |