Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[REFACTORING/IMPROVEMENT] 1-minimal deep rewrite #98

Closed
wants to merge 33 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
366eaec
Update Registration.php
nyamsprod Jun 30, 2013
41c4947
Update Registration.php
nyamsprod Jun 30, 2013
a5abd2e
Update Registration.php
nyamsprod Jun 30, 2013
fe42bc0
Update Registration.php
nyamsprod Jun 30, 2013
51a7210
Update db.php
nyamsprod Jun 30, 2013
9bbf08c
Update Registration.php
nyamsprod Jun 30, 2013
11be254
typo fix
nyamsprod Jun 30, 2013
5302c6f
Update Registration.php
nyamsprod Jun 30, 2013
0c45054
Update Registration.php
nyamsprod Jun 30, 2013
cdd481c
Registration is extended from Auth.php
nyamsprod Jul 1, 2013
9216378
Login/php extends Auth.php
nyamsprod Jul 1, 2013
2f6b2f3
Create Auth.php
nyamsprod Jul 1, 2013
04b8800
Added function to validate submitted data
nyamsprod Jul 1, 2013
4009d4e
Added PHPDocs comments
nyamsprod Jul 1, 2013
7189e45
Adding check to see if the session is not corrupted
nyamsprod Jul 1, 2013
ba8166f
Added Methods and PHPDocs comments
nyamsprod Jul 1, 2013
fe524eb
Update Login.php
nyamsprod Jul 1, 2013
35c41db
Update Registration.php
nyamsprod Jul 1, 2013
6fa71f8
Update Registration.php
nyamsprod Jul 1, 2013
cbff6b8
Update Auth.php
nyamsprod Jul 1, 2013
f3c8693
Update Registration.php
nyamsprod Jul 1, 2013
54abd4e
Update Registration.php
nyamsprod Jul 1, 2013
4d67fc1
Change method visibility
nyamsprod Jul 1, 2013
1903f8e
Update Login.php
nyamsprod Jul 1, 2013
51c8c7b
Update register.php
nyamsprod Jul 1, 2013
1400bf1
Update not_logged_in.php
nyamsprod Jul 1, 2013
25dca9c
Update not_logged_in.php
nyamsprod Jul 1, 2013
34aa25b
Update register.php
nyamsprod Jul 1, 2013
c5332c4
Update index.php
nyamsprod Jul 1, 2013
b858f08
Update register.php
nyamsprod Jul 1, 2013
0d8d0b8
Bug and indentation fixes
ignace-dev Jul 1, 2013
937125a
Bug fixes and example rewrite to help understand the new code for 1-m…
ignace-dev Jul 2, 2013
d1edbde
Update db.php
nyamsprod Jul 2, 2013
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Prev Previous commit
Next Next commit
Bug fixes and example rewrite to help understand the new code for 1-m…
…inimal
  • Loading branch information
ignace-dev committed Jul 2, 2013
commit 937125abb60ecea67383068d96f95f4adad1c5a2
5 changes: 3 additions & 2 deletions 1-minimal/_install/users.sql
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@ CREATE TABLE IF NOT EXISTS `users` (
`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',
PRIMARY KEY (`user_id`),
UNIQUE KEY `user_name` (`user_name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='user data' AUTO_INCREMENT=1 ;
UNIQUE KEY `user_name` (`user_name`),
UNIQUE KEY `user_email` (`user_email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='user data' AUTO_INCREMENT=1;

/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
Expand Down
53 changes: 38 additions & 15 deletions 1-minimal/classes/Auth.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ class Auth
* Database connection
* @var MySQLi
*/
private $conn;
protected $conn;

/**
* Collection of error messages
* @var array
*/
private $errors = array();
protected $errors = array();

/**
* Collection of regular expressions to validate user data
Expand All @@ -30,21 +30,28 @@ class Auth
'user_password' => '^.{6,}$'
);

/**
* action to be taken
* @var string
*/
protected $action;

/********************************************************
* Possible Error using Constants to enable localization
********************************************************/
const DATA_OK = 128; //data is ok
const DATA_MISSING = 1; //data is missing
const DATA_INVALID = 2; //data is invalid
const DATA_MISMATCH = 3; //string mismatch between 2 string
const REGISTRATION_FAILED = 1; //registration failed (db error)
const USER_EXISTS = 1; //user submitted already exists in database
const USER_UNKNOWN = 2; //user unknown (user name OR password Error)
const REGISTRATION_FAILED = 4; //registration failed (db error)
const USER_EXISTS = 5; //user submitted already exists in database
const USER_UNKNOWN = 6; //user unknown (user name OR password Error)

/**
* Used to generated a unique token for each user
* @var string
*/
private $secretKey = 'This is my hidden secret key'; //you should change this phrase
protected $secretKey = 'This is my hidden secret key'; //you should change this phrase

/**
* The Constructor initialize the db connection
Expand Down Expand Up @@ -100,7 +107,7 @@ public static function isValidEmail($str = null)
return null;
}
$str = filter_var($str, FILTER_VALIDATE_EMAIL);
if (! $str || 64 > strlen($str)) {
if (! $str || 64 < strlen($str)) {
return false;
}

Expand Down Expand Up @@ -157,7 +164,7 @@ public static function isValidUserName($str = null)
*
* @return array the user info
*/
private function getUserByName($login)
protected function getUserByName($login)
{
$login = $this->conn->real_escape_string($login);
$res = $this->conn->query("SELECT * FROM users WHERE user_name = '$login'");
Expand All @@ -174,23 +181,23 @@ private function getUserByName($login)
*
* @return boolean
*/
private function isUserExists($login, $email)
protected function isUserExists($login, $email)
{
$login = $this->conn->real_escape_string($login);
$email = $this->conn->real_escape_string($email);
$res = $this->conn->query(
"SELECT COUNT(user_id) AS nb FROM users WHERE user_name = '$login' OR user_email = '$email'"
);
$count = $res->fetch_assoc();
return (bool) $count['nb'];
return (int) $count['nb'];
}

/**
* generate a unique token
* @param string $login a string to generate the token with
* @return string the generated token
*/
private function generateToken($login)
protected function generateToken($login)
{
$userAgent = (isset($_SERVER['HTTP_USER_AGENT'])) ? $_SERVER['HTTP_USER_AGENT'] : '';
$timestamp = time();
Expand All @@ -204,16 +211,32 @@ private function generateToken($login)
* @param string $str the token to be validated
* @return boolean
*/
private function isValidateToken($str)
protected function isValidToken($str)
{
list($login, $timestamp, $secret) = explode('|', $str);
$auth = explode('|', $str);
$userAgent = (isset($_SERVER['HTTP_USER_AGENT'])) ? $_SERVER['HTTP_USER_AGENT'] : '';
if (
sha1($login.'|'.$this->secretKey.'|'.$userAgent.'|'.$timestamp) != $secret ||
strtotime('NOW - 30 MINUTES') > $timestamp
count($auth) != 3 ||
strtotime('NOW - 30 MINUTES') > $auth[1] ||
sha1($auth[0].'|'.$this->secretKey.'|'.$userAgent.'|'.$auth[1]) != $auth[2]
) {
return false;
}
return true;
}

/**
* tell if a value is null, false or set
* @param mixed $str the value to valid
* @return int
*/
protected function isDataValid($value = null)
{
if (is_null($value)) {
return self::DATA_MISSING;
} elseif (! $value) {
return self::DATA_INVALID;
}
return self::DATA_OK;
}
}
61 changes: 36 additions & 25 deletions 1-minimal/classes/Login.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,17 @@ public function __construct()
session_start();
}

$this->is_logged_in = false;
if (isset($_SESSION['session_token'])) {
//the action to take
$action = filter_input(
INPUT_GET,
'action',
FILTER_SANITIZE_STRING,
FILTER_REQUIRE_SCALAR|FILTER_FLAG_STRIP_LOW|FILTER_FLAG_STRIP_HIGH
);

if (isset($_SESSION['user_token'])) {
$this->is_logged_in = $this->loginWithSessionData();
} elseif (filter_has_var(INPUT_POST, 'login')) {
} elseif ('login' == $action) {
$this->is_logged_in = $this->loginWithPostData();
}

Expand All @@ -45,6 +52,7 @@ public function __construct()
*/
public function doLogout()
{
$this->is_logged_in = false;
$_SESSION = array();
session_destroy();
}
Expand All @@ -66,7 +74,7 @@ private function loginWithSessionData()
{
$this->errors = array();
//1 - Input Filtering and Validation
if (! $this->isValidateToken($_SESSION['user_token'])) {
if (! $this->isValidToken($_SESSION['user_token'])) {
$this->errors['user_token'] = self::DATA_INVALID;
return false;
}
Expand All @@ -77,19 +85,13 @@ private function loginWithSessionData()
if (! $login) {
$this->errors['user_name'] = self::DATA_INVALID;
return false;
}

$user = $this->getUserByName($login);
if (! $user) {
} elseif (! ($user = $this->getUserByName($login))) {
$this->errors['user_name'] = self::USER_UNKNOWN;
return false;
}

//3 - Session Update
foreach ($user as $key => $value) {
$_SESSION[$key] = $value;
}
$_SESSION['user_token'] = $this->generateToken($user['user_name']);
$this->loadSession($user);
return true;
}

Expand All @@ -102,38 +104,47 @@ private function loginWithPostData()
{

$this->errors = array();

//1 - Input Filtering and Validation
$arguments = array(
'user_name' => array('filter' => FILTER_CALLBACK, 'options' => array('Auth::isValidUserName')),
'user_password' => array('filter' => FILTER_CALLBACK, 'options' => array('Auth::isValidPassword')),
'user_name' => array('filter' => FILTER_CALLBACK, 'options' => 'Auth::isValidUserName'),
'user_password' => array('filter' => FILTER_CALLBACK, 'options' => 'Auth::isValidPassword'),
);
$params = filter_input_array(INPUT_POST, $arguments);
foreach (array_keys($arguments) as $key) {
if (! is_null($params[$key])) {
$this->errors[$key] = self::DATA_MISSING;
} else if (! $params[$key]) {
$this->errors[$key] = self::DATA_INVALID;
$this->errors = array_map(array($this, 'isDataValid'), $params);
foreach ($this->errors as $keys => $value) {
if ($value == self::DATA_OK) {
unset($this->errors[$keys]);
}
}
if (count($this->errors)) {
return false;
}

//2 - User Authentification
$user = $this->getUserByName($params['user_name']);
if (! $user) {
$this->errors['user'] = self::USER_UNKNOWN;
$this->errors['user_name'] = self::USER_UNKNOWN;
return false;
}

if (! password_verify($params['user_password'], $user['user_password_hash'])) {
$this->errors['password'] = self::DATA_INVALID;
} elseif (! password_verify($params['user_password'], $user['user_password_hash'])) {
$this->errors['user_password'] = self::DATA_INVALID;
return false;
}

//3 - Session Update
$this->loadSession($user);
return true;
}

/**
* load User Data into the session
* @return void
*/
private function loadSession(array $user)
{
foreach ($user as $key => $value) {
$_SESSION[$key] = $value;
}
$_SESSION['user_token'] = $this->generateToken($user['user_name']);
return true;
}
}
38 changes: 24 additions & 14 deletions 1-minimal/classes/Registration.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,15 @@ class Registration extends Auth
public function __construct()
{
parent::__construct();
if (filter_has_var(INPUT_POST, 'register')) {

$action = filter_input(
INPUT_GET,
'action',
FILTER_SANITIZE_STRING,
FILTER_REQUIRE_SCALAR|FILTER_FLAG_STRIP_LOW|FILTER_FLAG_STRIP_HIGH
);

if ('register' == $action) {
$this->is_registration_ok = $this->registerNewUser();
}
}
Expand Down Expand Up @@ -51,25 +59,28 @@ private function registerNewUser()
{
//1 - Input Filtering and Validation
$arguments = array(
'user_name' => array('filter' => FILTER_CALLBACK, 'options' => array('Auth::isValidUserName')),
'user_email' => array('filter' => FILTER_CALLBACK, 'options' => array('Auth::isValidEmail')),
'user_password_new' => array('filter' => FILTER_CALLBACK, 'options' => array('Auth::isValidPassword')),
'user_password_repeat' => array('filter' => FILTER_CALLBACK, 'options' => array('Auth::isValidPassword')),
'user_name' => array('filter' => FILTER_CALLBACK, 'options' => 'Auth::isValidUserName'),
'user_email' => array('filter' => FILTER_CALLBACK, 'options' => 'Auth::isValidEmail'),
'user_password_new' => array('filter' => FILTER_CALLBACK, 'options' => 'Auth::isValidPassword'),
'user_password_repeat' => array('filter' => FILTER_CALLBACK, 'options' => 'Auth::isValidPassword'),
);
$params = filter_input_array(INPUT_POST, $arguments);
foreach (array_keys($arguments) as $keys) {
if (is_null($params[$keys])) {
$this->errors[$keys] = self::DATA_MISSING;
} elseif (! $params[$keys]) {
$this->errors[$keys] = self::DATA_INVALID;
$this->errors = array_map(array($this, 'isDataValid'), $params);
foreach ($this->errors as $key => $value) {
if ($value == self::DATA_OK) {
unset($this->errors[$key]);
}
}

if (! $this->errors && ($params['user_password_new'] != $params['user_password_repeat'])) {
if (! isset($this->errors['user_password_new'], $this->errors['user_password_repeat']) &&
($params['user_password_new'] != $params['user_password_repeat'])
) {
$this->errors['user_password_repeat'] = self::DATA_MISMATCH;
}

if (! $this->errors && $this->isUserExists($params['user_name'], $params['user_email'])) {
if (! isset($this->errors['user_name'], $this->errors['user_email']) &&
$this->isUserExists($params['user_name'], $params['user_email'])
) {
$this->errors['user_name'] = self::USER_EXISTS;
}

Expand All @@ -78,13 +89,12 @@ private function registerNewUser()
}

//2 - write new user data into database
$params['user_password'] = password_hash($params['user_password_new'], PASSWORD_DEFAULT);
$params['user_password_hash'] = password_hash($params['user_password_new'], PASSWORD_DEFAULT);
unset($params['user_password_new'], $params['user_password_repeat']);
$params = array_map(array($this->conn, 'real_escape_string'), $params);
$res = $this->conn->query(
"INSERT INTO users (".implode(',', array_keys($params)).") VALUES ('".implode("','", $params)."')"
);

if (! $res) {
$this->errors['user_name'] = self::REGISTRATION_FAILED;
return false;
Expand Down
4 changes: 2 additions & 2 deletions 1-minimal/config/db.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@
const DB_HOST = "127.0.0.1";

/** name of the database. please note: database and database table are not the same thing! */
const DB_NAME = "login";
const DB_NAME = "test";

/** user for your database. the user needs to have rights for SELECT, UPDATE, DELETE and INSERT.
/** By the way, it's bad style to use "root", but for development it will work */
const DB_USER = "root";

/** The password of the above user */
const DB_PASS = "mysql";
const DB_PASS = "troldbois";

/** Required to better sanitize your data before DB insertion */
const DB_CHARSET = 'utf8';
1 change: 1 addition & 0 deletions 1-minimal/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
* @license http:https://opensource.org/licenses/MIT MIT License
*/


// 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 "libraries/password_compatibility_library.php";
Expand Down