I can't seem to find a straightforward answer to this question. Is there a way in which I can force a logged in user to logout? My login system essentially just relies on a session containing the user's unique ID (which is stored in a mysql database). So essentially just...
if (isset($_SESSION['user_id'])) {
echo "You're logged in!";
} else {
echo "You need to login!";
}
But let's say I want to ban this user, well I can change their status to banned in my database but this won't do anything until the user logs out and attempts to log back in... So, how do I force this user to logout? Preferably without checking every single time they view a page whether or not their status has been switched to "banned" because that seems like unnecessary stress on my server. Any help is appreciated, thank you.
Either you need to check every time they load a page, or possibly look at an Ajax call at set intervals to check their status from the DB.
Then you can use session_destroy(); to end their session. This will destroy their entire session.
Otherwise you can use unset($_SESSION['user_id']); to unset a single session variable
Preferably without checking every single time they view a page whether or not their status has been switched to "banned" because that seems like unnecessary stress on my server.
Loading the user from the database on every page load, rather than storing a copy of the user in the session, is a perfectly reasonable solution. It also prevents the user from getting out of sync with the copy in the database (so that, for instance, you can change a user's properties or permissions without them having to log out and back in).
Try to put this on every page...
if (isset($_SESSION['user_id'])) {
$sql = "SELECT from tbl where status='banned' and user_id=$_SESSION['user_id'] ";
$query = mysql_query($sql);
if(!empty(mysql_num_rows($query))){ // found the banned user
//redirect to logout or
//session_destroy();
}
} else {
echo "You need to login!";
}
if the user is still logged in... check if his/her status is banned or not... if banned.. then logout
You can unset it.
unset($_SESSION['user_id'])
You could use Custom Session Handlers this way you have full control where and how the session data is stored on the server.
So you could store the session data for a particular user in a file called <user_id>.session for example. Then, to logout the user, just delete that file.
Ajax calls in an interval will put extra load on server. If you want real-time response to your actions(e.g. the user will be signed out right when you ban them from your system backend), then you should look into something like Server Push.
The idea is to keep a tunnel open from Server to Browser whenever a user is browsing your website, so that you can communicate with them from server-side too. If you want them to be banned, push a logout request and the process that in your page(i.e. force logout by unsetting session).
This worked for me am using pHP 5.4
include 'connect.php';
session_start();
if(session_destroy())
{
header("Location: login.php");
}
You can use session_save_path() to find the path where PHP saves the session files, and then delete them using unlink().
Once you delete the session file stored in the sever, the client side PHPSESSID cookie will no longer be valid for authentication and the user will be automatically be logger out of your application.
Please be very careful while using this approach, if the path in question turns out to be the global /tmp directory! There's bound to be other processes other than PHP storing temporary data there. If PHP has its own directory set aside for session data it should be fairly safe though.
There is a few ways to do this the best in my opinion based on security is:
NOTE: THIS IS REALLY ROUGH.... I know the syntax is wrong, its just for you to get an idea.
$con = mysql_connect("localhost","sampleuser","samplepass");
if (!$con)
{
$error = "Could not connect to server";
}
mysql_select_db("sampledb", $con);
$result = mysql_query("SELECT * FROM `sampletable` WHERE `username`='".$_SESSION['user_id']."'");
$userdeets = mysql_fetch_array($result);
if($_SESSION['sessionvalue'] != $userdeets['sessionvalue'])
{
session_destroy();
Header('Location: logout.php');
}
else
{
$result2 = mysql_query("UPDATE `sessionvalue` WHERE `username`='".$_SESSION['user_id']."' SET `sessionvalue` = RANDOMVALUE''");
$sesval = mysql_fetch_array($result2);
$_SESSION['sessionvalue'] = $seshval
}
Now I know thats not the very code but in essence what you need to do to be secure and have this ability is:
Everytime a page load check a Session value matches a value in the DB.
Every time a page loads set a new session value based on a random generated DB value. you will need to store the username in a session as well.
if the Session ID's do not match then you destroy the session and redirect them.
if it does match you make the new session ID.
if you want to ban a user you can set their sessionvalue in the DB to a value like "BANNED". this value will not allow them to log in either. this way you can control user through a simple web form and you can also generate list of banned users very easily etc etc. I wish I had more time to explain it I hope this helps.
Related
I have this in my $_SESSION setting script:
<?php
//----------------------// Start session----------------------
if(!isset($_SESSION))
{
session_start();
}
//------------------------------------------------------------
//------------------// Check if Username $_SESSION is set------------------------------------------
if (!$_SESSION['Username']) { // If not current User
header("Location: ./logout.php"); // Session destroy file that leads to session logout landing page
exit();
}
//------------------------------------------------------------
?>
Now, what I basically do is just check if Username SESSION is set. But, I have come to notice something strange while putting another user through:
If we click the same link at the same time and arrive on the landing page same time, I noticed I can see my Username displayed as his Username and his personal data like email and phone replaced mine in my very own PC! This is really strange to me as we do not even live in the same country or even share same PC.
So, it is obvious I have not secured my SESSION and I have used a lame approach without thinking about security and this can be abused with SESSIONS hijacked.
How do I resolve this conflict? How do I restrict each logged in user to a particular session without conflicts if two or more users access the same resource at the very same time? I need help. I can't sleep since I found this.
After reading your responses, I will now show a snippet of the functions.php file which outputs Use data from DB.
First, I get the UserName value from session using:
$UserName = $_SESSION['Username'];
With this value, I query DB to get more user details:
//------------Get User Info -- All user column
$Get_User_Info = mysqli_query($conn,"SELECT * FROM customers WHERE User='$UserName'");
/************************************************************/
/************************************************************/
$Get_User_Info_row = mysqli_fetch_array($Get_User_Info,MYSQLI_ASSOC);
/************************************************************/
//---- Now list all user rows
$GLOBALS['Skype'] = $Get_User_Info_row['Skype'];
$GLOBALS['Jabber'] = $Get_User_Info_row['Jabber'];
$GLOBALS['ICQ'] = $Get_User_Info_row['ICQ'];
$GLOBALS['Join_Date'] = $Get_User_Info_row['Join_Date'];
$GLOBALS['Join_Date_Time'] = $Get_User_Info_row['Join_Date_Time'];
$GLOBALS['Balance'] = number_format($Get_User_Info_row['Balance'],2);
The above is what is contained in the functions.php which I require with each page I need protected.
As you can see, I barely see where I have done too much wrong there.
I googled to solve my question but any site explains my problem in a different way so I feel very confused!
I realized a php site in this way.
index.php:
In this page I get username and passw from login form and after checked if the user really exist I'll save them first in a variable and after in session.
$_SESSION['user']=$user;
$_SESSION['psw']=$psw;
Now I would show this page ONLY if the user is logged, so I would make some like this:
first_page.php:
<?
if(isset($_SESSION['user']) && isset($_SESSION['user'])!="" && isset($_SESSION['psw']) && isset($_SESSION['psw'])!=""{
// show page site
}
else
// go to index.php
?>
and insert this block if-else in any pages of the site.
It is correct this procedure?
I need to introduce session_start(); in any page or just in index.php?
How long time $_SESSION['user'] and $_SESSION['psw'] (expires)?
Since the site needs $_SESSION['user'] for many features, I need to be sure that when a user navigate the site those session variables are setted.
Thanks for your support, I feel very confused on it.
You must add session_start() in every single page where you use $_SESSION. It expires when you leave the site.
Don't store a password in a session, without changing the session handler data in a session is stored as plain text outside of the web root. This means anyone that has access to the system can read session data.
The method of knowing if a valid login occured is:
$sql = "select id where username = 'username' and password = 'hashedpassword'"
If an id is returned it means the user successfully logged in and store that ID in a session. Then validate if the session continues if the ID is set.
Keep in mind that after raising privileges it is recommend to change the session id as well, that can be done with session_regenerate_id() this to add protection for session fixation attacks.
At the beginning of each script when trying to read data from a session use session_start() and session_destroy() to remove all data stored in that session (usually a logout)
If I introduce at the top of any page the following script, could be a good solution? Or there's something wrong?
if ((isset($_SESSION['LAST_ACTIVITY']) && (time() - $_SESSION['LAST_ACTIVITY'] > 1800)) || $_SESSION['iduser']==NULL) {
// last request was more than 30 minutes ago
session_unset();
session_destroy(); // destroy session data in storage
echo "<script>location.href='index.php'</script>"; //redirect the user to index page
}
$_SESSION['LAST_ACTIVITY'] = time(); // update last activity time stamp
/* Code for the rest of my page HTML*/
(took from here: How do I expire a PHP session after 30 minutes?)
I have a login system that whenever the user logs succesfully creates some cookies with his username password and some other variables that are put in the url for configuration of the session:
setcookie("username", $myusername); //Sets a cookie storing the username
setcookie("password", $mypassword); //Sets a cookie storing the encrypted value of the password
setcookie("typeOfUser",$type); //example variable
and the variables are passed through the URL:
header("location:http://www.example.com/logged.php?type=".$type);
inside the logged.php page I have a file called protect.php which checks whether the cookies exist and what kind of user is it.
if(isset($_COOKIE["username"])&&isset($_COOKIE["password"])){
//check if this user's cookies exist on the DB
$user = $_COOKIE["username"];
$pass = $_COOKIE["password"];
$sql="SELECT * FROM USERS WHERE Usr='".$user."' and Pass='".$pass."';";
$result=mysql_query($sql);
// Mysql_num_row is counting table row
$count=mysql_num_rows($result);
if($count==1){
$type = $_COOKIE["type"];
header("location:logged.php?type=".$type);
exit();
}
else{
header("location:http://www.example.com/login.php");
}
}
so if the user just types www.example.com/logged.php he/she will get the variables associated with his user, but whenever I do this I get a redirect loop on the site. (It seems to me a little bit obvious that it redirects cause each time it goes to the header("location... it restarts and at the top it checks the protect.php... but I can't figure out a way to solve this).
Note logged.php just has at the top an:
include("protect.php");
Thanks in advance!
The reason that this script loops infinitely is based in the logic:
if($count==1){
header("location:logged.php?type=".$type);
}
else{
header("location:http://www.example.com/login.php");
}
Regardless of the value of $count at this point, your script will send a location header. In other words, the browser is receiving a redirect either way, whether $count is equal to 1 or not.
if(isset($_COOKIE["username"])&&isset($_COOKIE["password"])){
In combination with this line, your loop is defined. This evaluates to true if the user has these cookies defined, which happens when they are logging in for the first time, or have already logged in. If they are logged in, their username and password must be valid, and $count will end up as 1, because they are in the database.
In short, every time the user goes to logged.php after they are logged in, this script is run because they have the appropriate cookies and they are directed, again, to "logged.php?type=."$type" (over and over again) because they are a valid user and present in the database.
To fix this, you'll want to stop header("location:logged.php?type=".$type); from running every time protect.php is run. This is the essence of your problem. You can fix this however you like, but I would do it with sessions.
Check out this tutorial to learn how to implement sessions in your logins script.
You already have three cookies: username, password, and typeOfUser. The system you have works fine, but most authentication scripts use sessions, accessible like cookies ($_COOKIE['foo']), but with the $_SESSION variable instead. The advantage to using session is that the values you store in them are not available to anyone but scripts on your server/site, to view, or to edit. In general, the less information you expose to the user, the better. If you need clarification, check out this StackOverflow post or the basic examples on the PHP website.
One more thing to point out is in your script, if(isset($_COOKIE["username"])&&isset($_COOKIE["password"])){ has no else statement. If one or both of these cookies are not defined, no code will be executed, and what I am assuming is a protected page will be displayed publicly. You may want to add an else statement, something along the lines of:
else{
header("location:http://www.example.com/login.php");
}
Hope you're able to make this functional and awesome!
For a website, I need to route users to their own page. I have a login form, which sends data to a PHP file to check if the user's information is correct, and if so, forwarding the user to their page. The only problem is that I need to validate the user on arrival, to check if they logged in or just typed out the URL. I plan to use this with a POST, but how can I auto-send the constant (i.e. "logged-in")? Is there a way to do that through an HTML form (outputted from an echo) and sending it when the page loads? Thanks in advance!
EDIT 1: I understand that I must use Sessions, but whenever the page redirects it clears the session. The whole reason I was asking this was because I needed a way to keep the session active. How do I redirect in a way that doesn't clear the session?
In the PHP file that validates their credentials, start a "session". You can then apply session variables that can be called at any time while the session is valid. You can do this with POST, which is sounds like you're using, or by querying a database upon validation.
For example, upon validation:
session_start();
$_SESSION['username'] = $_POST['username'];
$security_check = mysql_query("SELECT * FROM userList WHERE username = '$username'");
$row = mysql_fetch_assoc($security_check);
$_SESSION['userId'] = $row['userId'];
$_SESSION['userFullName'] = $row['userFullName'];
On subsequent pages, you can put the following code at the top to check if the user logged in. If not, it will kick them back to the index page; otherwise the $_SESSION variables will be maintained.
<?php
session_start();
if (!isset($_SESSION['userId'])) {
echo "<script> window.location.replace('index.php?login=no') </script>";
}
?>
As suggested in the comments, I would recommend doing some further research on sessions to get a full understanding of how they work.
I'm new to web programing and im trying to find a few good examples / tutorials on how to do a decent job of creating a website that requires users to log on to view any pages beyond the main log in page.
so far i've found 1 or 2 that ive tried but i keep running into the same problem. If i just enter the url of the page i want to see manually i can get in like there was nothing there.
Okay, I'll explain how the basic concept goes and a very simple implementation to get things going.
PHP (and most web applications) rely on RESTful services -- which, to our concern at the moment, means every request is not remotely bound to any other request being made - either that being by the same user or others.
So what does that mean?
This means that for every single request, you need to do your checks. You need to make sure if the user has permissions to execute that page, or less severely even see its contents.
How is this achieved?
By many ways, actually. There are lots of techniques used to enforce authorization on web applications but they would essentially both break down to one of two -- either centralized, or decentralized.
-- Centralized
This means all your actions (and controllers) are being handled through a single file. Say index.php. This file would then include or delegate its tasks to other files (that are not runnable on their own via normal requests) based on request parameters. This is a very popular approach, but not exactly straight forward for new developers. Examples of applications that use this approach would have URLS of the type: index.php?do=register, index.php?do=login, index.php?do=showtopic&topic_id=2, and so forth.
A simple implementation of this technique would go like:
<?php
// index.php
define('RUNNING_APP', true);
// 1. place your auth code here, or...
switch ($_REQUEST['do']) {
case 'register':
// 2. or here
include 'inc/register.php';
break;
case 'do_register':
// 2. and here, and before every include.. and so forth.
include 'inc/do_register.php';
break;
}
?>
<?php
// inc/register.php
defined('RUNNING_APP') or die('Cannot access this script directly'); // make sure to break direct access
?>
<form action="index.php?do=do_register">
<!-- form elements -->
</form>
and so forth.
I've documented where the usual auth code should go.
-- Decentralized
Using this approach, however, your auth code should go at the beginning of every single file. URLS of applications of this sort usually look something like: register.php, login.php, and so forth. The main problem here is that you need to perform all auth logic per file, as stated above, and that may be a hectic job if your files increase in amount. A convenient solution is to have that logic in a single file, and include that file (which would kill the request for unauth personel) before any of your logic. A simple example would be:
<?php
// index.php
include('inc/auth.php');
// index logic
?>
<?php
// register.php
include 'inc/auth.php';
// register logic
?>
<?php
// inc/auth.php
$logged_in = false;
if (!$logged_in) {
die ('You do not have permission to access this page. Please login');
}
?>
When logging in using a form, you should check the username and password in the database. The password should be scrambled (usually done using the MD5 hash algorithm), and stored in the database in the same way. You capture the variables, using something like (use some validation to check if the POST variables are valid):
$username = $_POST['username'];
$passwordHash = md5( $_POST['password'] );
The username and hashed password should be stored in your database. You can then check for a match in the database using:
$res = mysql_query("SELECT * FROM users WHERE username='".$username."' && password='".$password."'");
When a user is found, you use sessions to store the user values, which will allow you to get access to a users information across pages. NOTE: session_start() is usually placed at the top of the page, but I'll place it here for readability.
if ( mysql_num_rows($res) ) {
session_start();
session_regenerate_id(); // regenerate session_id to help prevent session hijacking
$row = mysql_fetch_assoc($res);
$_SESSION['logged_on'] = true;
$_SESSION['username'] = $row['username'];
// add more session variables about the user as needed
}
On every page you want to protect, you add the following to the top of those pages:
session_start();
if ( !isset($_SESSION['logged_on']) ) {
header("Location: login.php"); // user is not logged in, redirect to login page
exit;
}
// page content here
There's HTTP Auth:
http://php.net/manual/en/features.http-auth.php
Or you can roll your own with a login form and session tracking:
http://www.php.net/manual/en/book.session.php.
Http auth means the user gets a pop-up dialog window asking for a username and password, it's less usual than the self-rolled version.
Enjoy!
The sites you mentioned are likely bypassable because the pages past the security check don't save and then check for login status on each page. You need to check that a visitor is logged in before access to a page is granted.
I think most users would expect form input for a login. If you want the user to come back and log in with the same account later after their session expires, you'd need a database to store user information.
When storing user information in a database, you should probably not actually store their password, either. For an example:
name password ...
-----------------------------------------------
Johnny '3858f62230ac3c915f300c664312c63f'
Alice '80338e79d2ca9b9c090ebaaa2ef293c7'
.
.
.
Johnny's password is actually "foobar", but the database stores md5('foobar'). When Johnny tries to log in, he enters his username ('Johnny') and his password ('foobar'). In PHP, you hash the password he entered, and call up his password value from the database, resulting in:
if (md5('foobar') == '3858f62230ac3c915f300c664312c63f')
This conditional is true. You can confirm if he logged in correctly, but you're never storing his actual password.
Alice's password is 'foobaz'. She tries to log in, but accidentally types 'foobar', Johnny's password. this results in:
if(md5('foobar') == '80338e79d2ca9b9c090ebaaa2ef293c7')
Which is false. Again, you don't know what Alice's password is, just that she entered the wrong one.
The downside to this strategy, of course, is that you can't tell the user what their password is when they forget it -- you don't know! You can resolve this by letting a user reset their password (to some semi-random string) instead of strait telling them what their password is.