Remember me
This commit is contained in:
parent
eb93088f87
commit
e8023c308f
|
@ -20,6 +20,9 @@ function checkLogin($args)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($Login->verifyUser($_POST['username'], $_POST['password'])) {
|
if ($Login->verifyUser($_POST['username'], $_POST['password'])) {
|
||||||
|
if (isset($_POST['remember'])) {
|
||||||
|
$Login->setRememberMe($_POST['username']);
|
||||||
|
}
|
||||||
// Renew the token. This token will be the same inside the session for multiple forms.
|
// Renew the token. This token will be the same inside the session for multiple forms.
|
||||||
$Security->generateTokenCSRF();
|
$Security->generateTokenCSRF();
|
||||||
Redirect::page('dashboard');
|
Redirect::page('dashboard');
|
||||||
|
@ -35,16 +38,45 @@ function checkLogin($args)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function checkRememberMe()
|
||||||
|
{
|
||||||
|
global $Security;
|
||||||
|
global $Login;
|
||||||
|
|
||||||
|
if ($Security->isBlocked()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Cookie::isset(REMEMBER_COOKIE_USERNAME) || !Cookie::isset(REMEMBER_COOKIE_TOKEN)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$username = Cookie::get(REMEMBER_COOKIE_USERNAME);
|
||||||
|
$token = Cookie::get(REMEMBER_COOKIE_TOKEN);
|
||||||
|
|
||||||
|
if ($Login->verifyUserByRemember($username, $token)) {
|
||||||
|
$Security->generateTokenCSRF();
|
||||||
|
Redirect::page('dashboard');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$Security->addToBlacklist();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Main before POST
|
// Main before POST
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
|
if ($_SERVER['REQUEST_METHOD']!=='POST') {
|
||||||
|
checkRememberMe();
|
||||||
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// POST Method
|
// POST Method
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
if ($_SERVER['REQUEST_METHOD']=='POST')
|
if ($_SERVER['REQUEST_METHOD']=='POST') {
|
||||||
{
|
|
||||||
checkLogin($_POST);
|
checkLogin($_POST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -110,6 +110,11 @@ define('CLI_STATUS', 'published');
|
||||||
// Cli mode, username for new pages
|
// Cli mode, username for new pages
|
||||||
define('CLI_USERNAME', 'admin');
|
define('CLI_USERNAME', 'admin');
|
||||||
|
|
||||||
|
// Remember me
|
||||||
|
define('REMEMBER_COOKIE_USERNAME', 'BLUDITREMEMBERUSERNAME');
|
||||||
|
define('REMEMBER_COOKIE_TOKEN', 'BLUDITREMEMBERTOKEN');
|
||||||
|
define('REMEMBER_COOKIE_EXPIRE_IN_DAYS', 30);
|
||||||
|
|
||||||
// Filename
|
// Filename
|
||||||
define('FILENAME', 'index.txt');
|
define('FILENAME', 'index.txt');
|
||||||
|
|
||||||
|
|
|
@ -11,8 +11,7 @@ class dbUsers extends dbJSON
|
||||||
'salt'=> array('inFile'=>false, 'value'=>'!Pink Floyd!Welcome to the machine!'),
|
'salt'=> array('inFile'=>false, 'value'=>'!Pink Floyd!Welcome to the machine!'),
|
||||||
'email'=> array('inFile'=>false, 'value'=>''),
|
'email'=> array('inFile'=>false, 'value'=>''),
|
||||||
'registered'=> array('inFile'=>false, 'value'=>'1985-03-15 10:00'),
|
'registered'=> array('inFile'=>false, 'value'=>'1985-03-15 10:00'),
|
||||||
'tokenEmail'=> array('inFile'=>false, 'value'=>''),
|
'tokenRemember'=> array('inFile'=>false, 'value'=>''),
|
||||||
'tokenEmailTTL'=> array('inFile'=>false, 'value'=>'2009-03-15 14:00'),
|
|
||||||
'tokenAuth'=> array('inFile'=>false, 'value'=>''),
|
'tokenAuth'=> array('inFile'=>false, 'value'=>''),
|
||||||
'tokenAuthTTL'=> array('inFile'=>false, 'value'=>'2009-03-15 14:00'),
|
'tokenAuthTTL'=> array('inFile'=>false, 'value'=>'2009-03-15 14:00'),
|
||||||
'twitter'=> array('inFile'=>false, 'value'=>''),
|
'twitter'=> array('inFile'=>false, 'value'=>''),
|
||||||
|
@ -119,7 +118,7 @@ class dbUsers extends dbJSON
|
||||||
return md5( uniqid().time().DOMAIN );
|
return md5( uniqid().time().DOMAIN );
|
||||||
}
|
}
|
||||||
|
|
||||||
public function generateEmailToken()
|
public function generateRememberToken()
|
||||||
{
|
{
|
||||||
return $this->generateAuthToken();
|
return $this->generateAuthToken();
|
||||||
}
|
}
|
||||||
|
@ -134,6 +133,13 @@ class dbUsers extends dbJSON
|
||||||
return sha1($password.$salt);
|
return sha1($password.$salt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setRememberToken($username, $token)
|
||||||
|
{
|
||||||
|
$args['username'] = $username;
|
||||||
|
$args['tokenRemember'] = $token;
|
||||||
|
return $this->set($args);
|
||||||
|
}
|
||||||
|
|
||||||
public function setPassword($username, $password)
|
public function setPassword($username, $password)
|
||||||
{
|
{
|
||||||
$salt = $this->generateSalt();
|
$salt = $this->generateSalt();
|
||||||
|
@ -170,18 +176,25 @@ class dbUsers extends dbJSON
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setTokenEmail($username)
|
// Returns the username with the remember token assigned, FALSE otherwise
|
||||||
|
public function getByRememberToken($token)
|
||||||
{
|
{
|
||||||
// Random hash
|
foreach ($this->db as $username=>$fields) {
|
||||||
$token = $this->generateEmailToken();
|
if ($fields['tokenRemember']==$token) {
|
||||||
$this->db[$username]['tokenEmail'] = $token;
|
return $username;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Token time to live, defined by TOKEN_EMAIL_TTL
|
// This function clean all tokens for Remember me
|
||||||
$this->db[$username]['tokenEmailTTL'] = Date::currentOffset(DB_DATE_FORMAT, TOKEN_EMAIL_TTL);
|
// This function is used when some hacker try to use an invalid remember token
|
||||||
|
public function invalidateAllRememberTokens()
|
||||||
// Save the database
|
{
|
||||||
$this->save();
|
foreach ($this->db as $username=>$values) {
|
||||||
return $token;
|
$this->db[$username]['tokenRemember'] = '';
|
||||||
|
}
|
||||||
|
return $this->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns array with the username databases filtered by username, FALSE otherwise
|
// Returns array with the username databases filtered by username, FALSE otherwise
|
||||||
|
|
|
@ -2,24 +2,28 @@
|
||||||
|
|
||||||
class Cookie {
|
class Cookie {
|
||||||
|
|
||||||
public static function get($name)
|
public static function get($key)
|
||||||
{
|
{
|
||||||
if(isset($_COOKIE[$name]))
|
if (isset($_COOKIE[$key])) {
|
||||||
{
|
return $_COOKIE[$name];
|
||||||
return($_COOKIE[$name]);
|
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
return(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function add($name, $value, $expire = 525600)
|
public static function set($key, $value, $daysToExpire=30)
|
||||||
{
|
{
|
||||||
setcookie($name, $value, time() + ($expire * 60));
|
// The time the cookie expires.
|
||||||
|
// This is a Unix timestamp so is in number of seconds since the epoch.
|
||||||
|
// In other words, you'll most likely set this with the time() function plus the number of seconds before you want it to expire.
|
||||||
|
// Or you might use mktime(). time()+60*60*24*30 will set the cookie to expire in 30 days.
|
||||||
|
// If set to 0, or omitted, the cookie will expire at the end of the session (when the browser closes).
|
||||||
|
$expire = time()+60*60*24*$daysToExpire;
|
||||||
|
setcookie($key, $value, $expire);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function isSet($name)
|
public static function isset($key)
|
||||||
{
|
{
|
||||||
return(isset($_COOKIE[$name]));
|
return isset($_COOKIE[$key]);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -9,11 +9,13 @@ class Login {
|
||||||
$this->dbUsers = $dbUsers;
|
$this->dbUsers = $dbUsers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the username of the user logged
|
||||||
public function username()
|
public function username()
|
||||||
{
|
{
|
||||||
return Session::get('username');
|
return Session::get('username');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the role of the user logged
|
||||||
public function role()
|
public function role()
|
||||||
{
|
{
|
||||||
return Session::get('role');
|
return Session::get('role');
|
||||||
|
@ -26,9 +28,8 @@ class Login {
|
||||||
$username = Session::get('username');
|
$username = Session::get('username');
|
||||||
if (!empty($username)) {
|
if (!empty($username)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
} else {
|
||||||
else {
|
Log::set(__METHOD__.LOG_SEP.'Session username empty, destroying the session.');
|
||||||
Log::set(__METHOD__.LOG_SEP.'Session username empty, destroy the session.');
|
|
||||||
Session::destroy();
|
Session::destroy();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -49,6 +50,19 @@ class Login {
|
||||||
Log::set(__METHOD__.LOG_SEP.'User logged, fingerprint: '.$this->fingerPrint());
|
Log::set(__METHOD__.LOG_SEP.'User logged, fingerprint: '.$this->fingerPrint());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setRememberMe($username)
|
||||||
|
{
|
||||||
|
$username = Sanitize::html($username);
|
||||||
|
|
||||||
|
// Set the token on the users database
|
||||||
|
$token = $this->dbUsers->generateRememberToken();
|
||||||
|
$this->dbUsers->setRememberToken($username, $token);
|
||||||
|
|
||||||
|
// Set the token on the cookies
|
||||||
|
Cookie::set(REMEMBER_COOKIE_USERNAME, $username, REMEMBER_COOKIE_EXPIRE_IN_DAYS);
|
||||||
|
Cookie::set(REMEMBER_COOKIE_TOKEN, $token, REMEMBER_COOKIE_EXPIRE_IN_DAYS);
|
||||||
|
}
|
||||||
|
|
||||||
// Check if the username and the password are valid
|
// Check if the username and the password are valid
|
||||||
// Returns TRUE if valid and set the session
|
// Returns TRUE if valid and set the session
|
||||||
// Returns FALSE for invalid username or password
|
// Returns FALSE for invalid username or password
|
||||||
|
@ -71,7 +85,7 @@ class Login {
|
||||||
}
|
}
|
||||||
|
|
||||||
$user = $this->dbUsers->getDB($username);
|
$user = $this->dbUsers->getDB($username);
|
||||||
if($user==false) {
|
if ($user==false) {
|
||||||
Log::set(__METHOD__.LOG_SEP.'Username does not exist: '.$username);
|
Log::set(__METHOD__.LOG_SEP.'Username does not exist: '.$username);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -82,65 +96,46 @@ class Login {
|
||||||
Log::set(__METHOD__.LOG_SEP.'User logged succeeded by username and password - Username: '.$username);
|
Log::set(__METHOD__.LOG_SEP.'User logged succeeded by username and password - Username: '.$username);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
Log::set(__METHOD__.LOG_SEP.'Password incorrect.');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
Log::set(__METHOD__.LOG_SEP.'Password incorrect.');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function verifyUserByToken($username, $token)
|
// Verified Remember Token
|
||||||
|
// If valid log in the user
|
||||||
|
// If not valid invalidate all remember me tokens
|
||||||
|
public function verifyUserByRemember($username, $token)
|
||||||
{
|
{
|
||||||
$username = Sanitize::html($username);
|
$username = Sanitize::html($username);
|
||||||
$token = Sanitize::html($token);
|
$token = Sanitize::html($token);
|
||||||
|
|
||||||
$username = trim($username);
|
$username = trim($username);
|
||||||
$token = trim($token);
|
$token = trim($token);
|
||||||
|
|
||||||
if(empty($username) || empty($token)) {
|
if (empty($username) || empty($token)) {
|
||||||
Log::set(__METHOD__.LOG_SEP.'Username or Token-email empty. Username: '.$username.' - Token-email: '.$token);
|
$this->dbUsers->invalidateAllRememberTokens();
|
||||||
|
Log::set(__METHOD__.LOG_SEP.'Username or Token empty. Username: '.$username.' - Token: '.$token);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($username !== $this->getByRememberToken($token)) {
|
||||||
|
$this->dbUsers->invalidateAllRememberTokens();
|
||||||
|
Log::set(__METHOD__.LOG_SEP.'The user has different token or the token doesnt exist.');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate user and login
|
||||||
$user = $this->dbUsers->getDb($username);
|
$user = $this->dbUsers->getDb($username);
|
||||||
if($user==false) {
|
$this->setLogin($username, $user['role']);
|
||||||
Log::set(__METHOD__.LOG_SEP.'Username does not exist: '.$username);
|
return true;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$currentTime = Date::current(DB_DATE_FORMAT);
|
|
||||||
if($user['tokenEmailTTL']<$currentTime) {
|
|
||||||
Log::set(__METHOD__.LOG_SEP.'Token-email expired: '.$username);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if($token === $user['tokenEmail'])
|
|
||||||
{
|
|
||||||
// Set the user loggued.
|
|
||||||
$this->setLogin($username, $user['role']);
|
|
||||||
|
|
||||||
// Invalidate the current token.
|
|
||||||
$this->dbUsers->setTokenEmail($username);
|
|
||||||
|
|
||||||
Log::set(__METHOD__.LOG_SEP.'User logged succeeded by Token-email - Username: '.$username);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Log::set(__METHOD__.LOG_SEP.'Token-email incorrect.');
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function fingerPrint()
|
public function fingerPrint()
|
||||||
{
|
{
|
||||||
// User agent
|
|
||||||
$agent = getenv('HTTP_USER_AGENT');
|
$agent = getenv('HTTP_USER_AGENT');
|
||||||
if (empty($agent)) {
|
if (empty($agent)) {
|
||||||
$agent = 'Bludit/2.0 (Mr Nibbler Protocol)';
|
$agent = 'Bludit/2.0 (Mr Nibbler Protocol)';
|
||||||
}
|
}
|
||||||
|
|
||||||
return sha1($agent);
|
return sha1($agent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,5 +143,4 @@ class Login {
|
||||||
{
|
{
|
||||||
return Session::destroy();
|
return Session::destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -37,7 +37,7 @@ h2 {
|
||||||
}
|
}
|
||||||
/* PAGES */
|
/* PAGES */
|
||||||
|
|
||||||
article.page:not(:last-child) {
|
article.page {
|
||||||
margin-bottom: 100px;
|
margin-bottom: 100px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue