I have a very basic php session login script. I want to force logout of a certain user or force logout of all users.
How can I read all sessions made to my website, and destroy some or all sessions?
You could try to force PHP to delete all the sessions by doing
ini_set('session.gc_max_lifetime', 0);
ini_set('session.gc_probability', 1);
ini_set('session.gc_divisor', 1);
That forces PHP to treat all sessions as having a 0-second lifetime, and a 100% probability of getting cleaned up.
The drawback is that whichever unlucky user runs this first will get a long pause while PHP does cleanup, especially if there's a lot of session files to go through.
For one particular user, you'd have to add some code to your session handler:
if ($_SESSION['username'] == 'user to delete') {
session_destroy();
}
PHP's garbage collector isn't controllable, so you can't give it parameters such as "delete all sessions except for user X's". It looks strictly at the last-modified/last-accessed timestamps on the session files and compares that to the max_lifetime setting. It doesn't actually process the session data.
You can use session_save_path() to find the path where PHP saves the session files, and then delete them using unlink().
Updated - Aug 2012
This code is based from the official PHP site, and another well written snippet on SO.
<?php
// Finds all server sessions
session_start();
// Stores in Array
$_SESSION = array();
// Swipe via memory
if (ini_get("session.use_cookies")) {
// Prepare and swipe cookies
$params = session_get_cookie_params();
// clear cookies and sessions
setcookie(session_name(), '', time() - 42000,
$params["path"], $params["domain"],
$params["secure"], $params["httponly"]
);
}
// Just in case.. swipe these values too
ini_set('session.gc_max_lifetime', 0);
ini_set('session.gc_probability', 1);
ini_set('session.gc_divisor', 1);
// Completely destroy our server sessions..
session_destroy();
?>
Works well. Servers like NGinx you can turn off, clean cache, swipe memory reset, clear logs etc and generally remove temp usage. Even drop the limits of memory.
Clearling all sessions at once would require first knowing which session.save_handler is being used to store sessions and locating the session.save_path in order to delete all sessions. For deleting the current session only, refer to the documentation for session_destroy().
Here are some common examples for deleting all sessions using standard file and memcached save handlers:
Using file save handler
foreach(glob(ini_get("session.save_path") . "/*") as $sessionFile) {
unlink($sessionFile);
}
Using memcached save handler
$memcached = new Memcached;
$memcached->addServers($listOfYourMemcachedSesssionServers);
// Memcached session keys are prefixed with "memc.sess.key." by default
$sessionKeys = preg_grep("#^memc\.sess\.key\.#", $memcached->getAllKeys());
$memcached->deleteMulti($sessionKeys);
Of course, you might want to consider only doing this out of band from your normal HTTP client requests, since cleaning up large session storage may take some time and have inadvertent side effects in a normal request life cycle.
I found this code very helpful and it really worked for me
<?php
$path = session_save_path();
$files = glob($path.'/*'); // get all file names
foreach($files as $file){ // iterate files
if(is_file($file))
unlink($file); // delete file
}
?>
It depends on your session storage.
If you're using PHP session storage, then they may be in the temporary directory of your server. Deleting the selected files will "kill" the session. However if your server is in running state, that session file may be occupied by HTTP process and you won't be able to delete it. Just look at the image below. File named as starting with "+~" are all session files.
A nicer solution is to use a database session storage and delete the selected sessions from there. You can check out HTTP_Session2 which has multiple containers.
I will create a txt file containing the token which has the same value as the generated login session as a comparison every time the user is logged in:
if($_SERVER['REQUEST_METHOD'] == 'POST') {
$token = sha1(uniqid(mt_rand(), true));
if($everything_is_valid) {
// Set login session
$_SESSION[$_POST['username']] = $token;
// Create token file
file_put_contents('log/token.' . $_POST['username'] . '.txt', $token);
// Just to be safe
chmod('log/token.' . $_POST['username'] . '.txt', 0600);
}
}
Checks for logged in user(s):
if(isset($_SESSION['charlie']) && file_exists('log/token.charlie.txt') && $_SESSION['charlie'] == file_get_contents('log/token.charlie.txt')) {
echo 'You are logged in.';
}
So, if you want to force this charlie user to be logged out, simply remove the token file:
// Force logout the `charlie` user
unlink('log/token.charlie.txt');
Taufik's answer is the best i could find.
However, you can further modify it
After authenticating the user and creating the session variables, add these lines:
$token = "/sess_" . session_id();
file_put_contents('log/' . $_SESSION['id'] . '.txt', $token);
If you need to force the user to log out during a cronjob or by an admin request:
$path = session_save_path();
$file = file_get_contents('log/xxx.txt'); // xxx is user's id
$url = $path.$file;
unlink($url);
remove all session variables
session_unset();
destroy the session
session_destroy();
Related
I'm trying to improve the session management for web applications. My major issue is the session expiration and how to deal with it. For that I'd like to find out if the session is still available or not. I'm using the default file based sessions (PHP 7.1, Apache 2.4, Fedora/RHEL) and it is cookie based.
What I've found out is that the session GC gets executed when session_start() is called. It is not with the begin or end of the script execution, it happens with this function. What seems odd to me is that if session_start() and the GC consider the session as expired and want to delete the corresponding session file, $_SESSION gets populated regularly first, then the file will be deleted. That's surprising.
With that behaviour only the next following request leads to an empty $_SESSION. I would expect this with the call before - the one that deletes the file. So if I'd like to know whether the session has expired in the current request I would have to check if the session file still exists after the session_start() call. That seems strange to me.
Are there any other or better ways to check that a session has expired than looking into the file system?
I thought I could just check if $_SESSION is empty to determine that the session was renewed - but that is obviously not possible.
Update: I've found the following bug reports dealing with the issue: this and that. There's also a SO entry about the expiration problem. Current PHP source: php_session_start calls php_session_initialize calls php_session_gc.
You may want to play with this script (unreal settings are just for testing purposes):
ini_set('session.gc_maxlifetime', 2); // Session gets expired after 2 seconds
ini_set('session.gc_divisor', 1); // Delete expired session files immediately
ini_set('session.save_path', '/some/safe/path/for/testing'); // Must be accessible for the server
//ini_set('session.use_strict_mode', true); // Uncomment if the id should be renewed, what makes no difference here
echo "Session files before session_start call<br>";
listSessionFiles();
session_start();
echo "Session files after session_start call<br>";
listSessionFiles();
echo "<hr>";
echo "Session id: " . session_id() . "<br>";
echo "Session content: " . print_r($_SESSION, true);
$_SESSION['x'] = time(); // Populate the session with something
function listSessionFiles() {
echo "<ul>";
$none = true;
$dir = dir(ini_get('session.save_path'));
while ($entry = $dir->read()) {
if (preg_match('/^sess_/', $entry)) {
echo "<li>" . $entry . "</li>";
$none = false;
}
}
$dir->close();
if ($none) echo "<li>None</li>";
echo "</ul>";
}
Just reload the page some times. Wait at least more than two seconds. Otherwise the session does not expire.
One way to circumvent the problem is to use cookies with a certain lifetime (below the session lifetime). If the cookie expires it won't be sent to the server. PHP will then create a new session when session_start() is called, so $_SESSION will be empty.
This might be enough to find out that the session is not available. Although one cannot distinguish in PHP if the session has expired or anything went wrong. You can just tell that no session data is available and do appropiate things then (amongst other also destroy the newly created empty session).
I am doing a small project in that i have user data in session. In the middle the user will do payment, after payment success, the session is destroying automatically.
Now am not able to get user data from session. (How can i achieve this with out using COOKIES).
Note: I have tried using:
header('Access-Control-Allow-Origin: *');
But no use.
Hello this is an example from PHP manual i hope it might help. Firstly start your session by session_start(); and once all your transactions are completed destroy is by session_destroy();
<?php
// Initialize the session.
// If you are using session_name("something"), don't forget it now!
session_start();
// Unset all of the session variables.
$_SESSION = array();
// If it's desired to kill the session, also delete the session cookie.
// Note: This will destroy the session, and not just the session data!
if (ini_get("session.use_cookies")) {
$params = session_get_cookie_params();
setcookie(session_name(), '', time() - 42000,
$params["path"], $params["domain"],
$params["secure"], $params["httponly"]
);
}
// Finally, destroy the session.
session_destroy();
?>
$_SESSION is a special array used to store information across the page requests a user makes during his visit to your website or web application.
While there may be many users accessing the site at the same time, each with his own session, it’s thanks to unique IDs assigned and managed by PHP for each session that allows each user’s session to be available only to himself. Session information is stored on the server rather than the user’s computer (as cookie data is stored), which makes sessions more secure than traditional cookies for passing information between page requests.
Using Sessions
Before you can to store information in a session, you have to start PHP’s session handling. This is done at the beginning of your PHP code, and must be done before any text, HTML, or JavaScript is sent to the browser. To start the session, you call the session_start() function in your first file:
<?php
// start the session
session_start();
// store session data
$_SESSION["username"] = "Qateel";
session_start() starts the session between the user and the server, and allows values stored in $_SESSION to be accessible in other scripts later on.
In your second file, you call session_start() again which this time continues the session, and you can then retrieve values from $_SESSION.
<?php
// continue the session
session_start();
// retrieve session data
echo "Username = " . $_SESSION["username"];
Ending a Session
As important as it is to begin a session, so it is to end one. Even though a session is only a temporary way to store data, it is very important to clean up after yourself to ensure maximum security when dealing with potentially sensitive information. It is also good practice and will avoid having a huge amount of stale session data sitting on the server.
To delete a single session value, you use the unset() function:
<?php
session_start();
// delete the username value
unset($_SESSION["username"]);
To unset all of the session’s values, you can use the session_unset() function:
<?php
session_start();
// delete all session values
session_unset();
Both examples only affect data stored in the session, not the session itself. You can still store other values to $_SESSION after calling them if you so choose. If you wish to completely stop using the session, for example a user logs out, you use the session_destroy() function.
<?php
session_start();
// terminate the session
session_destroy();
Few Tips
Despite there simplicity, there are still ways using sessions can go wrong.
Timing-out sessions is a very important action if you are dealing with users logged in to your website or application.
if (isset($_SESSION["timeout"])) {
// calculate the session's "time to live"
$sessionTTL = time() - $_SESSION["timeout"];
if ($sessionTTL > $inactive) {
session_destroy();
header("Location: /logout.php");
}
}
Use a database to store data at the earliest moment you know the data will be persistent; don’t let it stay as part of the session for too long as this opens it up to possible attack.
Use session_destory() once you don’t need to use the session any more.
You may want to go through:
php sessions at #SO
php sessions security at #SO
Though this question has multiple duplicates i could not find proper solution for me.
Need Some help.
I have used ini_set('session.cookie_lifetime', 0); in my configuration file.
But it is not helping me to destroy session on browser close.
Application current flow:
1) In authentication page if user is valid, generate new session identifier using session_regenerate_id(true);
2) Control goes to welcome.php where i start new session using session_start();
3) in logout page code is
$_SESSION = array();
if (ini_get("session.use_cookies")) {
$params = session_get_cookie_params();
setcookie(session_name(), '', time() - 42000,
$params["path"], $params["domain"],
$params["secure"], $params["httponly"]
);
}
// Finally, destroy the session.
session_destroy();
This might help you,
session_set_cookie_params(0);
session_start();
Your session cookie will be destroyed... so your session will be good until the browser is open. please view http://www.php.net//manual/en/function.session-set-cookie-params.php this may help you.
Use a keep alive.
On login:
session_start();
$_SESSION['last_action'] = time();
An ajax call every few (eg 20) seconds:
windows.setInterval(keepAliveCall, 20000);
Server side keepalive.php:
session_start();
$_SESSION['last_action'] = time();
On every other action:
session_start();
if ($_SESSION['last_action'] < time() - 30 /* be a little tolerant here */) {
// destroy the session and quit
}
The best way is to close the session is: if there is no response for that session after particular interval of time. then close. Please see this post and I hope it will resolve the issue. "How to change the session timeout in PHP?"
There are different ways to do this, but the server can't detect when de browser gets closed so destroying it then is hard.
timeout session.
Either create a new session with the current time or add a time variable to the current session. and then check it when you start up or perform an action to see if the session has to be removed.
session_start();
$_SESSION["timeout"] = time();
//if 100 seconds have passed since creating session delete it.
if(time() - $_SESSION["timeout"] > 100){
unset($_SESSION["timeout"];
}
ajax
Make javascript perform an ajax call that will delete the session, with onbeforeunload() a javascript function that calls a final action when the user leaves the page. For some reason this doesnt always work though.
delete it on startup.
If you always want the user to see the login page on startup after the page has been closed you can just delete the session on startup.
<? php
session_start();
unset($_SESSION["session"]);
and there probably are some more.
There's one more "hack" by using HTTP Referer (we asume that browser window was closed current referer's domain name and curent page's domain name do not match):
session_start();
$_SESSION['somevariable'] = 'somevalue';
if(parse_url($_SERVER["HTTP_REFERER"], PHP_URL_HOST) != $_SERVER["SERVER_NAME"]){
session_destroy();
}
This also has some drawbacks, but it helped me few times.
You can do it using JavaScript by triggering an ajax request to server to destroy the session on onbeforeunload event fired when we closes the browse tab or window or browser.
Use the following code to destroy the session:
<?php
session_start();
unset($_SESSION['sessionvariable']);
header("Location:index.php");
?>
If you want to change the session id on each log in, make sure to use session_regenerate_id(true) during the log in process.
<?php
session_start();
session_regenerate_id(true);
?>
If you close your browser your session is lost.
session.cookie_lifetime specifies the lifetime of the cookie in seconds which is sent to the browser.
session.gc_maxlifetime specifies the number of seconds after which data will be seen as 'garbage' and potentially cleaned up.
ini_set('session.cookie_lifetime', 176400); // for 48 hours
ini_set('session.gc_maxlifetime', 176400); // for 48 hours
session_start();
If you are confused what to do, just refer to the manual of session_destroy() function:
http://php.net/manual/en/function.session-destroy.php
There you can find some more features of session_destroy().
This is my code to control authentication on a website. I'm not sure if my logic is correct. If the username and password are correct the following happen:
if(session_start())
{
session_regenerate_id(true);//without this the session ID will always be the same
$_SESSION['loggedInUser'] = $uName;
echo 'You are now logged in';
}
else echo 'Right password/username but session failed to start';
Subsequent pages check to see if the user is logged in by
session_start();
if(isset($_SESSION['loggedInUser'])
{
//rest of page
}
else echo 'you must log in';
When logging out I have
session_start();//if I don't have this the next line produces an error
session_unset();//destroys session variables
session_destroy();//ends session
I red not to call session_start() on logout but if I don't have it there I get the message Trying to destroy uninitialized session. How can I fix this?
Is it recommend or not to create a finger print based on the IP address and user agent? I red it's bad because multiple computers can share the same IP address if they are in, for example a computer lab, and all the traffic goes through a proxy and the same computer could change it's IP address if it's dynamic. On the other hand, how often does this happen? It may be worth the few blocked valid uses to prevent all session hijacking.
Even if you could recommend reputable articles I should read to learn about this topic that would be great, thanks.
5/6 answers have votes less than 0 :( Could down voters comment so I know what to look out for?
First of all you should read the Mozilla WebAppSec Security Coding Guideline - Session Management and OWASP A3-Broken Authentication and Session Management. You can configure PHP's session handler to meet these requirements.
The first flaw you should prevent is A9-Insufficient Transport Layer Protection. In short you do not want someone to hijack a session using a tool like Firesheep. This attack can be prevented by forcing the browser to only send the session id over https:
session.cookie_secure=1
You can prevent an attacker from obtaining the session id using XSS by setting the httponly flag:
session.cookie_httponly=1
You always want to use a cookie to store your session id. If the session id can be passed using a GET or POST variable then an attacker could use Session Fixation attack to hijack a session. Another way of thinking about this attack is that you don't want an attacker to create a session for another user:
session.use_cookies=1
session.use_only_cookies=1
Next you want to make sure you have atleast 128 bits of entropy from a CSPRNG. Under *nix systems you can use /dev/urandom:
session.entropy_file="/dev/urandom"
session.entropy_length=16
The session handler isn't everything. You still need to worry about Cross-Site Request Forgery attacks (aka CSRF or "Session Riding"), and Cross-Site Scripting (XSS). XSS can be used to defeat CSRF protection (even with http_only cookies!). Clickjacking can also be used by an attacker to perform unauthorized actions.
After you set these configuration options, just call session_start(). As for destroying the session call session_destroy() when the user logs out, its that simple!
To securely destroy a session I would use the following code:
session_start();
// Unset all session values
$_SESSION = array();
// get session parameters
$params = session_get_cookie_params();
// Delete the actual cookie.
setcookie(session_name(), '', time() - 42000, $params["path"], $params["domain"], $params["secure"], $params["httponly"]);
// Destroy session
session_destroy();
In order to destroy a session you need to start it first, as you have found out it doesn't work if you don't include session_start();
The session_regenerate_id(); Function generates a new session id for the user. If used with true (session_regenerate_id(true);) then the old session id is deleted from the server when it generates a new one. The reason behind generating a new session id on every page is that it makes session hijacking much harder (Nearly Impossible?) to perform because of the users constantly changing session id.
(View PHP.net manual on session_regenerate_id();)
When authenticating a user you should always check something like the IP address or Browser, these are constant things sent in the request to the server that do not change in the life time of your session, and if they do then you know something dodgy it happening. I always create two session variable one that stores the user ID so I can query a database for data, and another that stores the users password, IP address and Browser String all in one hash (sha512).
$user_id = $_SESSION['user_id'];
$login_string = $_SESSION['login_string'];
// Query Database and get hashed password
$login_check = hash('sha512', $password.$ip_address.$user_browser);
if($login_check == $login_string) {
// Logged In!!!!
return true;
} else {
// Not logged in
return false;
}
The password is secure even though it is being stored in the session. This is because the password is hashed (Twice in this case) and because the session data is not stored on the users computer (Like cookies), it is stored in a session file.
I wrote an article on wikihow.com about secure login and authentication, is can be found here.
You can just write:
session_start(); // session should be started before it can be used.
You can assign userid of logged in member. For this you can take username and password from user input and check it in your db and return userid. For more security you can have strings for eg. "demo" and "test" just md5 both and mix it with userid in following manner.
$userid=md5("demo").$userid.md5("test");// you can set any string instead of demo and test.
$_SESSION['userid']=$userid;
While using it in other page,
session_start(); // If you are have not started it or included above code file in it.
As you know the strings while using just match it and find the exact userid from it and use it in your code.
For destroying it just use:
session_unset($_SESSION['userid']); // It will only unset the session userid completely.
Make sure that before use of any session you need to start it. In better way you can start the session in one file say init.php and include it every where where you want to use the session
You can first use session_id() to determine whether the user already got a session, if not, then use session_start().
example codes from Lithium framewrok:
/**
* Starts the session.
*
* #return boolean True if session successfully started (or has already been started),
* false otherwise.
*/
protected static function _start() {
if (session_id()) {
return true;
}
...
return session_start();
}
After call _start(), you can safely call session_destroy()
To destroy a session without using "start_session()", first verify whether there is an active session of not like below
$existingSessionId = session_id();
if ($existingSessionId != "")
{
// Initialize the session.
session_start();
// Unset all of the session variables.
$_SESSION = array();
// If it's desired to kill the session, also delete the session cookie.
// Note: This will destroy the session, and not just the session data!
if (ini_get("session.use_cookies")) {
$params = session_get_cookie_params();
setcookie(session_name(), '', time() - 42000,
$params["path"], $params["domain"],
$params["secure"], $params["httponly"]
);
}
// Finally, destroy the session.
session_destroy();
}
else
{
// No Active sessions
}
session_regenerate_id(true), just replace the old session id with the new one but it does not unset the old session id. This needs to be taken care by session_destroy and deleting session cookie.
Browser will send session cookie to server ever session is destroyed. PHP will get this session ID and when you do start_session(), it will use session id sent by browser. If you delete the session cookie, session_start will generate a new session id and you do not need to call session_regenerate_id()
Is it possible to unset a specific user session (one who is banned from the site)?
Each session contains the user's username.
Or is the only way to writing sessions in the database and checks whether the user is deleted from that record?
Thanks for any suggestion.
PHP doesn't keep track of what session IDs have been issued - when a session cookie comes in on a request and session_start() is called, it'll look in the session save directory for a file named with that session's ID (sess_XXXX) and load it up.
Unless your login system records the user's current session ID, you'll have to scan that save directory for the file that contains the user's session, and delete the file. Fortunately, it could be done with something as simple as:
$session_dir = session_save_path();
$out = exec("rm -f `grep -l $username $session_dir/*`");
You'd probably want something a bit more secure/safe, but that's the basics of it.
Just remove the user from your database.
I assume that you are checking login credentials.
You can add a timeout to your sessions like so:
define('SESSION_EXPIRE', 3600 * 5); //5 hours
if (!isset($_SESSION['CREATED'])) {
$_SESSION['CREATED'] = time();
} else if (time() - $_SESSION['CREATED'] > SESSION_EXPIRE) {
session_regenerate_id(true); // change session ID for the current session an invalidate old session ID
session_destroy();
session_start();
$_SESSION['CREATED'] = time(); // update creation time
}
I think the best method would be before allowing the user to comment, have PHP read your database and check if the individual has publish permissions. If not return an error.
Another thing you could do, which Facebook does, is have an AJAX call checking a PHP file every few minutes. The PHP file simply returns whether the user is logged on or off and if they are logged off, Javascript redirects them off the page.