I am setting up a website that has 3 types of users:
-those who are registered and are subscribed for current month
-those that are registered, but are not subscribed for current month
-users that are not registered (you cant be subscribed if you are not regitered)
I've created code that identifies these 3 kinds of users and acts appropriately. My question is, is this the way to go? I've never done similar thing before. Or should I reprogram my approach?
//login.php
//connect to database and see if a user and password combination exists. Store $exists=0 if not, and $exists=1 if it exists.
session_start();
$conn = new mysqli($hn,$un,$pw,$db);
if ($conn->connect_error){
die($conn->connect_error);
}
$query = "SELECT COUNT(1) as 'exists',expiration_date FROM table WHERE email = ? AND password = ?;";
$stmt = $conn->prepare($query);
$stmt->bind_param("ss", $email, $password);
$email = $_POST["email"];
$password = hash("hashingalgorithm", "salt".$_POST["password"]."salthere");
$stmt->execute();
/* Get the result */
$result = $stmt->get_result();
$num_of_rows = $result->num_rows;
$row = $result->fetch_assoc();
$exists = $row["exists"];
$expiration_date = $row["expiration_date"];
/* free results */
$stmt->free_result();
/* close statement */
$stmt->close();
$conn->close();
date_default_timezone_set('Europe/Berlin');
if ($exists==0){
echo "Wrong email or password";
$_SESSION['loginerror'] = 2;
header('Location: https://www.homepage.com/login');
}else if ($exists){
if (strtotime($expiration_date) < (strtotime("now"))){//logged in, but not subscribed
session_destroy();
session_start();
$_SESSION["authenticated"] = true;
header('Location: https://www.homepage.com');
}else{//logged in and ready to go
$_SESSION["authenticated"] = true;
$_SESSION["email"] = $email;
header('Location: https://www.homepage.com');
}
}else{
echo "An error with has occured.";
}
Then on every single page on my website I use this code, to see what kind of user has visited me
session_start();
if(isset($_SESSION["authenticated"]) && isset($_SESSION["email"])){
$email = $_SESSION["email"];
//connect to database and fetch expiration_date for a user with $email. Store it in $expiration_date
$conn = new mysqli($hn,$un,$pw,$db);
if ($conn->connect_error){
die($conn->connect_error);
}
$query = "SELECT expiration_date FROM table WHERE email = ?;";
$stmt = $conn->prepare($query);
$stmt->bind_param("s", $email);
$email = $_SESSION["email"];
$stmt->execute();
/* Get the result */
$result = $stmt->get_result();
$num_of_rows = $result->num_rows;
$row = $result->fetch_assoc();
$expiration_date = $row["expiration_date"];
/* free results */
$stmt->free_result();
/* close statement */
$stmt->close();
$conn->close();
date_default_timezone_set('Europe/Berlin');
if (strtotime($expiration_date) < (strtotime("now"))){//logged in, but not subscribed
session_destroy();
session_start();
$_SESSION["authenticated"] = true;
header('Location: https://www.homepage.com');
}else{ //html for subsribed and registered user
echo <<<_END
//html here
_END;
}
}else if(isset($_SESSION["authenticated"]) && !isset($_SESSION["email"])){
// user is logged in, but not subscribed;
echo <<<_END
//htmlhere
_END;
}else{// user is not registered nor is subscribed
echo <<<_END
//htmlhere
_END;
}
The code works, but I am worried about accessing database on every single page once the user registers and is subscribed. I am in effect penalizing users for registering and subscribing. Is there a better, performance wise, way to handle this kind of problem?
One of the “issues” with sessions is scalability. The argument is that sessions are stored in memory and servers are duplicated to handle the application load, therefore, limiting the scalability of the application. JWT, on the other hand, has higher scalability due to its statelessness.
Session based authentication: Because the sessions are stored in the server's memory, scaling becomes an issue when there is a huge number of users using the system at once. Token based authentication: There is no issue with scaling because token is stored on the client side.
To secure session managementImplement a session timeout and force re-authentication when users are inactive to mitigate the risk of an attacker using a hijacked session for a long time.
The solution here is to check for subscribed users (only on the first page where they login to your website) i.e. inside login.php
you could use,
// ...your previous code
session_start();
// initialize session variables
$_SESSION['subscribe_date'] = $_SESSION['authenticated'] = false;
if ($exists == 0){
echo "Wrong email or password";
$_SESSION['loginerror'] = 2;
header('Location: https://www.homepage.com/login');
} else if ($exists){
$_SESSION["authenticated"] = true;
if (strtotime($expiration_date) > (strtotime("now"))){ //logged in,& subscribed
$_SESSION["email"] = $email;
$_SESSION['subscribe_date'] = $expiration_date;
} else { //logged in and not subscribed, do nothin!
}
header('Location: https://www.homepage.com');
} else {
echo "An error has occured.";
}
Then, on every other page, all you need to do is only check for $_SESSION['subscribe_date']
instead of firing a query each time
if(!empty($_SESSION["subscribe_date"]) && strtotime($_SESSION["subscribe_date"]) > (strtotime("now"))) {
// html for subscribed and registered user
} else if (!empty($_SESSION["authenticated"])) {
// html for registered user
} else {
// html for unregistered user
}
Also, note that I have removed session_destroy();
A very bad idea to call it on every page. You can unset session variables instead if needed. i.e. unset($_SESSION["email"]);
You should call session_destroy();
only at the end when the user logs out. Check out the warning-section for session_destroy()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With