Revamped the login system. Now you can be logged in on more devices, for longer periods of time. Todo: create script to clean user_login-table.
parent
cc94a18c18
commit
02bd4d4131
|
@ -39,7 +39,8 @@ if(isset($_POST) && !empty($_POST)){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$err = loginUser($data['loginEmail'], $data['loginPwd']);
|
$stayLoggedIn = isset($_POST['stayLoggedIn']);
|
||||||
|
$err = loginUser($data['loginEmail'], $data['loginPwd'], $stayLoggedIn);
|
||||||
if($err === true){
|
if($err === true){
|
||||||
header("Location: ".$returnToPage);
|
header("Location: ".$returnToPage);
|
||||||
die();
|
die();
|
||||||
|
@ -94,6 +95,12 @@ if(isset($_POST) && !empty($_POST)){
|
||||||
I agree to save a temporary cookie in my browser for the logged in functions to work.
|
I agree to save a temporary cookie in my browser for the logged in functions to work.
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-check" style="margin: 3px 0;">
|
||||||
|
<input class="form-check-input" type="checkbox" id="rememberCheck" name="stayLoggedIn">
|
||||||
|
<label class="form-check-label" for="rememberCheck">
|
||||||
|
Remember me (for 30 days)
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
<button type="submit" class="btn btn-primary mb-3 w-100">Login</button>
|
<button type="submit" class="btn btn-primary mb-3 w-100">Login</button>
|
||||||
</form>
|
</form>
|
||||||
<p>Do you not have an account? <a href="register.php">Register</a> </p>
|
<p>Do you not have an account? <a href="register.php">Register</a> </p>
|
||||||
|
|
|
@ -1,13 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
require 'webdata/init.php';
|
require 'webdata/init.php';
|
||||||
|
|
||||||
if(checkLogin()){
|
logoutUser();
|
||||||
logoutUser();
|
|
||||||
echo "logged out?";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
echo "not logged in";
|
|
||||||
}
|
|
||||||
|
|
||||||
header("Location: ");
|
header("Location: ".getConfig('projectRoot')."/");
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ class Store {
|
||||||
// html += " <input type='text' class='form-control newItemName' placeholder='New Item Name' data-toggle='tooltip' title='New Item Name' aria-label='New Item Name'>";
|
// html += " <input type='text' class='form-control newItemName' placeholder='New Item Name' data-toggle='tooltip' title='New Item Name' aria-label='New Item Name'>";
|
||||||
// html += " <input type='number' class='form-control newItemPrice' value='0' min='0' step='.01' data-toggle='tooltip' title='Price' aria-label='Price'>";
|
// html += " <input type='number' class='form-control newItemPrice' value='0' min='0' step='.01' data-toggle='tooltip' title='Price' aria-label='Price'>";
|
||||||
html += " <div class='form-control form-floating'>";
|
html += " <div class='form-control form-floating'>";
|
||||||
html += " <input type='text' id='newItemName0' class='form-control newItemName' placeholder='New Item Name' aria-label='New Item Name'>";
|
html += " <input type='text' id='newItemName0' class='form-control newItemName' placeholder='New Item Name' aria-label='New Item Name' autocomplete='off' autocapitalize='on'>";
|
||||||
html += " <label for='newItemName0'>New Item Name</label>";
|
html += " <label for='newItemName0'>New Item Name</label>";
|
||||||
html += " </div>";
|
html += " </div>";
|
||||||
html += " <div class='form-control form-floating'>";
|
html += " <div class='form-control form-floating'>";
|
||||||
|
|
|
@ -69,7 +69,7 @@ function getHtmlHeaders($prepend = ""){
|
||||||
\n";
|
\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
function loginUser($email, $pass) {
|
function loginUser($email, $pass, $stayLoggedIn = false) {
|
||||||
global $db;
|
global $db;
|
||||||
|
|
||||||
|
|
||||||
|
@ -89,23 +89,27 @@ function loginUser($email, $pass) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if(password_verify(PwdGen($pass), $dbPass)){
|
if(password_verify(PwdGen($pass), $dbPass)){
|
||||||
if(!isset($_SESSION)){
|
if(!isset($_SESSION)){
|
||||||
session_start();
|
session_start();
|
||||||
}
|
}
|
||||||
else {
|
session_regenerate_id();
|
||||||
// session_regenerate_id(true);
|
|
||||||
session_regenerate_id();
|
|
||||||
}
|
|
||||||
|
|
||||||
$_SESSION['user_id'] = $dbUserId;
|
$md5agent = md5($_SERVER['HTTP_USER_AGENT']);
|
||||||
$_SESSION['user_name'] = $dbUserName;
|
|
||||||
$_SESSION['user_agent'] = md5($_SERVER['HTTP_USER_AGENT']);
|
|
||||||
$userKey = GenKey();
|
$userKey = GenKey();
|
||||||
$updateUserSQL = "UPDATE user SET ctime = ".time().", ckey = '$userKey' WHERE user_id = $dbUserId;";
|
$shaUserKey = sha1($userKey);
|
||||||
|
$expire = $stayLoggedIn?30:0; // if "stay logged in", stay logged in for 30 days.
|
||||||
|
|
||||||
|
$updateUserSQL = "INSERT INTO user_login (user_id, ckey, ctime, expire, agent) VALUES ('$dbUserId', '$userKey', '".time()."', $expire, '$md5agent');";
|
||||||
if($db->query($updateUserSQL)){
|
if($db->query($updateUserSQL)){
|
||||||
$_SESSION['user_key'] = sha1($userKey);
|
$_SESSION['user_id'] = $dbUserId;
|
||||||
|
$_SESSION['user_name'] = $dbUserName;
|
||||||
|
$_SESSION['user_agent'] = $md5agent;
|
||||||
|
$_SESSION['user_key'] = $shaUserKey;
|
||||||
|
|
||||||
|
if($stayLoggedIn){
|
||||||
|
setcookie("auth", $shaUserKey.".".$dbUserId, time() + (30 * 24*60*60), "/", $_SERVER['HTTP_HOST'], isset($_SERVER['HTTPS']), true );
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -119,9 +123,46 @@ function loginUser($email, $pass) {
|
||||||
return $err;
|
return $err;
|
||||||
}
|
}
|
||||||
|
|
||||||
function logoutUser(){
|
function loginFromAuth($auth): bool {
|
||||||
if(checkLogin()){
|
global $db;
|
||||||
|
$db = $db ?? database();
|
||||||
|
|
||||||
|
$md5agent = md5($_SERVER['HTTP_USER_AGENT']);
|
||||||
|
|
||||||
|
$cookieSplode = explode('.', $auth);
|
||||||
|
if(count($cookieSplode) == 2){
|
||||||
|
$tkey = $cookieSplode[0];
|
||||||
|
$tuid = $cookieSplode[1];
|
||||||
|
$verifyLoginCookieRes = $db->query("SELECT ul.user_id, ul.ckey, ul.ctime, ul.expire, ul.agent, u.full_name FROM user_login ul INNER JOIN user u ON ul.user_id = u.user_id WHERE ul.user_id = '$tuid' ORDER BY ctime DESC");
|
||||||
|
while($row = $verifyLoginCookieRes->fetch_assoc()){
|
||||||
|
if($row['expire'] == 0){ $row['expire'] = 1; }
|
||||||
|
if(
|
||||||
|
sha1($row['ckey']) == $tkey &&
|
||||||
|
$row['agent'] == $md5agent &&
|
||||||
|
($row['ctime']+($row['expire']*24*60*60) > time())
|
||||||
|
){
|
||||||
|
session_regenerate_id();
|
||||||
|
$_SESSION['user_id'] = $row['user_id'];
|
||||||
|
$_SESSION['user_name'] = $row['full_name'];
|
||||||
|
$_SESSION['user_agent'] = $md5agent;
|
||||||
|
$_SESSION['user_key'] = sha1($row['ckey']);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function logoutUser($everywhere = false){
|
||||||
|
if(checkLogin()){
|
||||||
|
global $db;
|
||||||
|
|
||||||
|
$logoutSql = "DELETE FROM user_login WHERE user_id = $_SESSION[user_id]";
|
||||||
|
if(!$everywhere){ $logoutSql .= " AND agent = '".md5($_SERVER['HTTP_USER_AGENT'])."'"; }
|
||||||
|
|
||||||
|
$db = $db ?? database();
|
||||||
|
$db->query($logoutSql);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete session-cookie
|
// Delete session-cookie
|
||||||
|
@ -131,6 +172,8 @@ function logoutUser(){
|
||||||
$params["secure"], $params["httponly"]
|
$params["secure"], $params["httponly"]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
setcookie('auth', '', time() - 42000, "/", $_SERVER['HTTP_HOST'], isset($_SERVER['HTTPS']), true );
|
||||||
|
|
||||||
// Finally, destroy the session.
|
// Finally, destroy the session.
|
||||||
session_destroy();
|
session_destroy();
|
||||||
}
|
}
|
||||||
|
@ -147,7 +190,7 @@ function PwdGen($pass, $returnHashed = false): string {
|
||||||
return password_hash($pwd_peppered, PASSWORD_ARGON2ID, ['threads' => 2]);
|
return password_hash($pwd_peppered, PASSWORD_ARGON2ID, ['threads' => 2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function GenKey($length = 7): string{
|
function GenKey($length = 21): string{
|
||||||
$password = "";
|
$password = "";
|
||||||
$possible = "0123456789abcdefghijkmnopqrstuvwxyz";
|
$possible = "0123456789abcdefghijkmnopqrstuvwxyz";
|
||||||
|
|
||||||
|
@ -166,8 +209,8 @@ function GenKey($length = 7): string{
|
||||||
return $password;
|
return $password;
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkLogin(): bool{
|
function checkLogin(): bool {
|
||||||
global $db, $_SESSION;
|
global $db, $_SESSION, $_COOKIE;
|
||||||
|
|
||||||
if($db == null){
|
if($db == null){
|
||||||
$db = database();
|
$db = database();
|
||||||
|
@ -177,16 +220,25 @@ function checkLogin(): bool{
|
||||||
session_start();
|
session_start();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!isset($_SESSION['user_id'])){
|
if(isset($_SESSION['user_id'])){
|
||||||
return false;
|
$md5agent = md5($_SERVER['HTTP_USER_AGENT']);
|
||||||
|
if($md5agent == @$_SESSION['user_agent']){
|
||||||
|
$verifyLoginSessionRes = $db->query("SELECT expire, ctime, ckey FROM user_login WHERE user_id = ".$_SESSION['user_id']." and agent = '$md5agent'");
|
||||||
|
if($verifyLoginSessionRes->num_rows > 0){
|
||||||
|
while ($row = $verifyLoginSessionRes->fetch_assoc()){
|
||||||
|
if(
|
||||||
|
(sha1($row['ckey']) == $_SESSION['user_key']) &&
|
||||||
|
($row['expire'] == 0 || $row['ctime']+($row['expire']*24*60*60) > time())
|
||||||
|
){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(md5($_SERVER['HTTP_USER_AGENT']) == @$_SESSION['user_agent']){
|
if(isset($_COOKIE['auth']) && loginFromAuth($_COOKIE['auth'])){
|
||||||
$verifyLoginRes = $db->query("SELECT ckey FROM user WHERE user_id = ".$_SESSION['user_id']);
|
return true;
|
||||||
list($cKey) = $verifyLoginRes->fetch_row();
|
|
||||||
if(sha1($cKey) == $_SESSION['user_key']){
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unset($_SESSION['user_id']);
|
unset($_SESSION['user_id']);
|
||||||
|
|
|
@ -5,7 +5,7 @@ $msg = array();
|
||||||
|
|
||||||
$missingConfig = false;
|
$missingConfig = false;
|
||||||
|
|
||||||
if($_SERVER['HTTP_HOST'] != "localhost"){
|
if($_SERVER['REMOTE_ADDR'] != "127.0.0.1"){
|
||||||
$err[] = "You need to use this page from localhost";
|
$err[] = "You need to use this page from localhost";
|
||||||
$fatalErr = true;
|
$fatalErr = true;
|
||||||
}
|
}
|
||||||
|
@ -15,29 +15,50 @@ if($_SERVER['HTTP_HOST'] != "localhost"){
|
||||||
|
|
||||||
// CREATE TABLES
|
// CREATE TABLES
|
||||||
$sql = "CREATE OR REPLACE TABLE `user` (
|
$sql = "CREATE OR REPLACE TABLE `user` (
|
||||||
`user_id` BIGINT(20) NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
`user_id` BIGINT(20) NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||||
`md5_id` VARCHAR(200) UNIQUE,
|
`md5_id` VARCHAR(200) UNIQUE,
|
||||||
`full_name` TINYTEXT,
|
`full_name` TINYTEXT,
|
||||||
`user_email` VARCHAR(220) NOT NULL UNIQUE,
|
`user_email` VARCHAR(220) NOT NULL UNIQUE,
|
||||||
`user_level` TINYINT(4) NOT NULL DEFAULT 1,
|
`user_level` TINYINT(4) NOT NULL DEFAULT 1,
|
||||||
`pwd` VARCHAR(220),
|
`pwd` VARCHAR(220),
|
||||||
`date` DATE NOT NULL DEFAULT(CURRENT_DATE),
|
`date` DATE NOT NULL DEFAULT(CURRENT_DATE)
|
||||||
`ckey` VARCHAR(220),
|
|
||||||
`ctime` VARCHAR(220)
|
|
||||||
) DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;
|
) DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;
|
||||||
|
|
||||||
|
CREATE OR REPLACE TABLE `user_login` (
|
||||||
|
user_id bigint not null,
|
||||||
|
ckey varchar(220) not null,
|
||||||
|
ctime varchar(220) not null,
|
||||||
|
expire smallint default 0 not null,
|
||||||
|
agent varchar(255) null,
|
||||||
|
primary key (user_id, ctime),
|
||||||
|
constraint user_id_FK foreign key (user_id) references user (user_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE OR REPLACE TABLE `option` (
|
||||||
|
`option` varchar(100) not null primary key
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE OR REPLACE TABLE `user_option` (
|
||||||
|
user_id BIGINT(20) NOT NULL,
|
||||||
|
`option` varchar(100) NOT NULL,
|
||||||
|
value varchar(100) NOT NULL,
|
||||||
|
PRIMARY KEY (user_id,`option`),
|
||||||
|
CONSTRAINT user_options_FK FOREIGN KEY (user_id) REFERENCES `user`(user_id),
|
||||||
|
CONSTRAINT option_FK FOREIGN KEY (`option`) REFERENCES `option`(`option`)
|
||||||
|
)
|
||||||
|
|
||||||
CREATE OR REPLACE TABLE `plan_space` (
|
CREATE OR REPLACE TABLE `plan_space` (
|
||||||
`space_id` INT auto_increment PRIMARY KEY,
|
`space_id` INT auto_increment PRIMARY KEY,
|
||||||
`space_name` tinytext,
|
`space_name` tinytext,
|
||||||
`owner_id` BIGINT(20),
|
`owner_id` BIGINT(20),
|
||||||
|
`space_type` enum('STORE','CHECK','CALORIES') NOT NULL DEFAULT 'STORE', # not sure if needed
|
||||||
CONSTRAINT plan_space_owner_FK FOREIGN KEY (`owner_id`) REFERENCES `user`(`user_id`)
|
CONSTRAINT plan_space_owner_FK FOREIGN KEY (`owner_id`) REFERENCES `user`(`user_id`)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE OR REPLACE TABLE `plan_space_member` (
|
CREATE OR REPLACE TABLE `plan_space_member` (
|
||||||
`space_id` INT auto_increment NOT NULL,
|
`space_id` INT auto_increment NOT NULL,
|
||||||
`member_id` BIGINT(20) NOT NULL,
|
`member_id` BIGINT(20) NOT NULL,
|
||||||
`timestamp` DATETIME default current_timestamp() NOT NULL,
|
`timestamp` DATETIME default current_timestamp() NOT NULL,
|
||||||
PRIMARY KEY (`space_id`, `member_id`),
|
PRIMARY KEY (`space_id`, `member_id`),
|
||||||
CONSTRAINT space_member_FK FOREIGN KEY (`member_id`) REFERENCES `user`(`user_id`),
|
CONSTRAINT space_member_FK FOREIGN KEY (`member_id`) REFERENCES `user`(`user_id`),
|
||||||
CONSTRAINT space_member_space_FK FOREIGN KEY (`space_id`) REFERENCES `plan_space`(`space_id`)
|
CONSTRAINT space_member_space_FK FOREIGN KEY (`space_id`) REFERENCES `plan_space`(`space_id`)
|
||||||
|
@ -45,22 +66,22 @@ CREATE OR REPLACE TABLE `plan_space_member` (
|
||||||
|
|
||||||
CREATE OR REPLACE TABLE `plan_store` (
|
CREATE OR REPLACE TABLE `plan_store` (
|
||||||
`plan_store_id` INT auto_increment,
|
`plan_store_id` INT auto_increment,
|
||||||
`space_id` INT NOT NULL,
|
`space_id` INT NOT NULL,
|
||||||
`name` varchar(100) NOT NULL,
|
`name` varchar(100) NOT NULL,
|
||||||
`created` DATETIME default current_timestamp() NOT NULL,
|
`created` DATETIME default current_timestamp() NOT NULL,
|
||||||
`state` ENUM('planning', 'shopping', 'closed') default 'planning',
|
`state` ENUM('planning', 'shopping', 'closed') default 'planning',
|
||||||
PRIMARY KEY (plan_store_id),
|
PRIMARY KEY (plan_store_id),
|
||||||
CONSTRAINT plan_store_user_FK FOREIGN KEY (`space_id`) REFERENCES `plan_space`(`space_id`)
|
CONSTRAINT plan_store_user_FK FOREIGN KEY (`space_id`) REFERENCES `plan_space`(`space_id`)
|
||||||
) DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;
|
) DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;
|
||||||
|
|
||||||
CREATE OR REPLACE TABLE `plan_store_item` (
|
CREATE OR REPLACE TABLE `plan_store_item` (
|
||||||
`plan_item_id` INT auto_increment NOT NULL,
|
`plan_item_id` INT auto_increment NOT NULL,
|
||||||
`plan_store_id` INT NOT NULL,
|
`plan_store_id` INT NOT NULL,
|
||||||
`pos` tinyint(3) unsigned,
|
`pos` tinyint(3) unsigned,
|
||||||
`name` varchar(200) NOT NULL,
|
`name` varchar(200) NOT NULL,
|
||||||
`price` decimal(8,2) NOT NULL,
|
`price` decimal(8,2) NOT NULL,
|
||||||
`amount` tinyint(3) unsigned DEFAULT 1,
|
`amount` tinyint(3) unsigned DEFAULT 1,
|
||||||
`checked` BOOLEAN default 0,
|
`checked` BOOLEAN default 0,
|
||||||
PRIMARY KEY (plan_item_id),
|
PRIMARY KEY (plan_item_id),
|
||||||
CONSTRAINT plan_store_item_FK FOREIGN KEY (plan_store_id) REFERENCES `plan_store`(`plan_store_id`)
|
CONSTRAINT plan_store_item_FK FOREIGN KEY (plan_store_id) REFERENCES `plan_store`(`plan_store_id`)
|
||||||
) DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;
|
) DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;
|
||||||
|
|
Loading…
Reference in New Issue