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){
|
||||
header("Location: ".$returnToPage);
|
||||
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.
|
||||
</label>
|
||||
</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>
|
||||
</form>
|
||||
<p>Do you not have an account? <a href="register.php">Register</a> </p>
|
||||
|
|
|
@ -1,13 +1,7 @@
|
|||
<?php
|
||||
require 'webdata/init.php';
|
||||
|
||||
if(checkLogin()){
|
||||
logoutUser();
|
||||
echo "logged out?";
|
||||
}
|
||||
else {
|
||||
echo "not logged in";
|
||||
}
|
||||
logoutUser();
|
||||
|
||||
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='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 += " <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 += " </div>";
|
||||
html += " <div class='form-control form-floating'>";
|
||||
|
|
|
@ -69,7 +69,7 @@ function getHtmlHeaders($prepend = ""){
|
|||
\n";
|
||||
}
|
||||
|
||||
function loginUser($email, $pass) {
|
||||
function loginUser($email, $pass, $stayLoggedIn = false) {
|
||||
global $db;
|
||||
|
||||
|
||||
|
@ -89,23 +89,27 @@ function loginUser($email, $pass) {
|
|||
}
|
||||
|
||||
|
||||
|
||||
if(password_verify(PwdGen($pass), $dbPass)){
|
||||
if(!isset($_SESSION)){
|
||||
session_start();
|
||||
}
|
||||
else {
|
||||
// session_regenerate_id(true);
|
||||
session_regenerate_id();
|
||||
}
|
||||
session_regenerate_id();
|
||||
|
||||
$_SESSION['user_id'] = $dbUserId;
|
||||
$_SESSION['user_name'] = $dbUserName;
|
||||
$_SESSION['user_agent'] = md5($_SERVER['HTTP_USER_AGENT']);
|
||||
$md5agent = md5($_SERVER['HTTP_USER_AGENT']);
|
||||
$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)){
|
||||
$_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;
|
||||
}
|
||||
else {
|
||||
|
@ -119,9 +123,46 @@ function loginUser($email, $pass) {
|
|||
return $err;
|
||||
}
|
||||
|
||||
function logoutUser(){
|
||||
if(checkLogin()){
|
||||
function loginFromAuth($auth): bool {
|
||||
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
|
||||
|
@ -131,6 +172,8 @@ function logoutUser(){
|
|||
$params["secure"], $params["httponly"]
|
||||
);
|
||||
|
||||
setcookie('auth', '', time() - 42000, "/", $_SERVER['HTTP_HOST'], isset($_SERVER['HTTPS']), true );
|
||||
|
||||
// Finally, destroy the session.
|
||||
session_destroy();
|
||||
}
|
||||
|
@ -147,7 +190,7 @@ function PwdGen($pass, $returnHashed = false): string {
|
|||
return password_hash($pwd_peppered, PASSWORD_ARGON2ID, ['threads' => 2]);
|
||||
}
|
||||
|
||||
function GenKey($length = 7): string{
|
||||
function GenKey($length = 21): string{
|
||||
$password = "";
|
||||
$possible = "0123456789abcdefghijkmnopqrstuvwxyz";
|
||||
|
||||
|
@ -166,8 +209,8 @@ function GenKey($length = 7): string{
|
|||
return $password;
|
||||
}
|
||||
|
||||
function checkLogin(): bool{
|
||||
global $db, $_SESSION;
|
||||
function checkLogin(): bool {
|
||||
global $db, $_SESSION, $_COOKIE;
|
||||
|
||||
if($db == null){
|
||||
$db = database();
|
||||
|
@ -177,16 +220,25 @@ function checkLogin(): bool{
|
|||
session_start();
|
||||
}
|
||||
|
||||
if(!isset($_SESSION['user_id'])){
|
||||
return false;
|
||||
if(isset($_SESSION['user_id'])){
|
||||
$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']){
|
||||
$verifyLoginRes = $db->query("SELECT ckey FROM user WHERE user_id = ".$_SESSION['user_id']);
|
||||
list($cKey) = $verifyLoginRes->fetch_row();
|
||||
if(sha1($cKey) == $_SESSION['user_key']){
|
||||
return true;
|
||||
}
|
||||
if(isset($_COOKIE['auth']) && loginFromAuth($_COOKIE['auth'])){
|
||||
return true;
|
||||
}
|
||||
|
||||
unset($_SESSION['user_id']);
|
||||
|
|
|
@ -5,7 +5,7 @@ $msg = array();
|
|||
|
||||
$missingConfig = false;
|
||||
|
||||
if($_SERVER['HTTP_HOST'] != "localhost"){
|
||||
if($_SERVER['REMOTE_ADDR'] != "127.0.0.1"){
|
||||
$err[] = "You need to use this page from localhost";
|
||||
$fatalErr = true;
|
||||
}
|
||||
|
@ -15,29 +15,50 @@ if($_SERVER['HTTP_HOST'] != "localhost"){
|
|||
|
||||
// CREATE TABLES
|
||||
$sql = "CREATE OR REPLACE TABLE `user` (
|
||||
`user_id` BIGINT(20) NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`md5_id` VARCHAR(200) UNIQUE,
|
||||
`full_name` TINYTEXT,
|
||||
`user_email` VARCHAR(220) NOT NULL UNIQUE,
|
||||
`user_level` TINYINT(4) NOT NULL DEFAULT 1,
|
||||
`pwd` VARCHAR(220),
|
||||
`date` DATE NOT NULL DEFAULT(CURRENT_DATE),
|
||||
`ckey` VARCHAR(220),
|
||||
`ctime` VARCHAR(220)
|
||||
`user_id` BIGINT(20) NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`md5_id` VARCHAR(200) UNIQUE,
|
||||
`full_name` TINYTEXT,
|
||||
`user_email` VARCHAR(220) NOT NULL UNIQUE,
|
||||
`user_level` TINYINT(4) NOT NULL DEFAULT 1,
|
||||
`pwd` VARCHAR(220),
|
||||
`date` DATE NOT NULL DEFAULT(CURRENT_DATE)
|
||||
) 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` (
|
||||
`space_id` INT auto_increment PRIMARY KEY,
|
||||
`space_name` tinytext,
|
||||
`owner_id` BIGINT(20),
|
||||
`space_id` INT auto_increment PRIMARY KEY,
|
||||
`space_name` tinytext,
|
||||
`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`)
|
||||
);
|
||||
|
||||
CREATE OR REPLACE TABLE `plan_space_member` (
|
||||
`space_id` INT auto_increment NOT NULL,
|
||||
`member_id` BIGINT(20) NOT NULL,
|
||||
`timestamp` DATETIME default current_timestamp() NOT NULL,
|
||||
`space_id` INT auto_increment NOT NULL,
|
||||
`member_id` BIGINT(20) NOT NULL,
|
||||
`timestamp` DATETIME default current_timestamp() NOT NULL,
|
||||
PRIMARY KEY (`space_id`, `member_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`)
|
||||
|
@ -45,22 +66,22 @@ CREATE OR REPLACE TABLE `plan_space_member` (
|
|||
|
||||
CREATE OR REPLACE TABLE `plan_store` (
|
||||
`plan_store_id` INT auto_increment,
|
||||
`space_id` INT NOT NULL,
|
||||
`name` varchar(100) NOT NULL,
|
||||
`created` DATETIME default current_timestamp() NOT NULL,
|
||||
`state` ENUM('planning', 'shopping', 'closed') default 'planning',
|
||||
`space_id` INT NOT NULL,
|
||||
`name` varchar(100) NOT NULL,
|
||||
`created` DATETIME default current_timestamp() NOT NULL,
|
||||
`state` ENUM('planning', 'shopping', 'closed') default 'planning',
|
||||
PRIMARY KEY (plan_store_id),
|
||||
CONSTRAINT plan_store_user_FK FOREIGN KEY (`space_id`) REFERENCES `plan_space`(`space_id`)
|
||||
) DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;
|
||||
|
||||
CREATE OR REPLACE TABLE `plan_store_item` (
|
||||
`plan_item_id` INT auto_increment NOT NULL,
|
||||
`plan_store_id` INT NOT NULL,
|
||||
`pos` tinyint(3) unsigned,
|
||||
`name` varchar(200) NOT NULL,
|
||||
`price` decimal(8,2) NOT NULL,
|
||||
`amount` tinyint(3) unsigned DEFAULT 1,
|
||||
`checked` BOOLEAN default 0,
|
||||
`plan_item_id` INT auto_increment NOT NULL,
|
||||
`plan_store_id` INT NOT NULL,
|
||||
`pos` tinyint(3) unsigned,
|
||||
`name` varchar(200) NOT NULL,
|
||||
`price` decimal(8,2) NOT NULL,
|
||||
`amount` tinyint(3) unsigned DEFAULT 1,
|
||||
`checked` BOOLEAN default 0,
|
||||
PRIMARY KEY (plan_item_id),
|
||||
CONSTRAINT plan_store_item_FK FOREIGN KEY (plan_store_id) REFERENCES `plan_store`(`plan_store_id`)
|
||||
) DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;
|
||||
|
|
Loading…
Reference in New Issue