I am starting the session as
session_start(); //So This session will get destroyed when user exit the browser
I set the cookie as
setcookie('cookie',$value,time()+3*60);
$_SESSION['cookie'] = true; //When user log in, I don't need to get the
salt again from db and do all the security
checks. Assume it as a cache
This suggesion is suggested in this question.
The problem is, cookie gets expired after 3 minutes. But session exists. So user tries to login after 3 minutes
if($_SESSION['cookie'])
{
//success
}
else
{
//Authenticate user
}
But this is wrong. Since cookie expired, else part should execute. But if part gets executed. I understand that session is still alive. How do I handle this situation?
I understand that it is due to that time()+3*60. But how do I implement that cache thing?
You need check cookie not in $_SESSION.
Check them in $_COOKIE.
As example:
if($_COOKIE['cookie'])
{
//success
}
else
{
//Authenticate user
}
Cookies and session variables are not related (except that PHP internally uses a cookie named PHPSESSID to connect the client to its session). Expiring the cookie doesn't have any effect on a session variable with the same name. If you want to test whether the cookie has expired, use:
if (isset($_COOKIE['cookie']))
Related
How can I check if a session was ever set or was set but expired?
I am using this code and I want to make an echo if the session has expired like this: Session has expired. Please login again
This is my code:
session_start();
if(!isset($_SESSION['sfmlogin'])){
?>
Login again
<?php
exit();
}
So for users who visit the page for the first time, they should not get an echo likesession expired because they did never login before.
The information you are looking for is in the session meta-data - but this is not exposed via the API. The default handler uses files - so if the file exists, then there was a session. but you should not attempt to bypass the handler to get session metadata! That would be a very bad idea. Really, it sounds like you should be writing your own session handler which also exposes the metadata.
Session has expired
This is a very complicated proposition: with the default handler (leaving aside the problem of bypassing the handler to get the meta-data) there is no session expiration - there is only garbage collection of session data which hasn't been touched for some time. On some systems this is handled by a batch process. On some it is a stochastic event. So in effect, and in this context, there is no difference between an expired session and no session from the server's point of view.
You could infer from the cookies if the browser thinks it should have a session:
session_start();
if ($_COOKIE(session_name() && !count($_SESSION)) {
print "session has expired";
exit;
} elsif (!$_COOKIE(session_name()) {
print "You need to login first";
exit;
} else {
print "welcome back....";
....
...but do make sure that you put something in the session when the user logs in.
How about doing a boolean check on session_status()? If it returns true, then the session is active, else, it would return a "Session Expired" notice. http://php.net/manual/en/function.session-status.php
Edit: You would only need to check session_status() after a user has logged in. If they have not, then the session has not been started, therefore $_SESSION would already be false and a session expiration notice wouldn't be possible.
I only store logged users id in SESSION.
When a user logs out, SESSION becomes useless for me. Do I have to destroy it?
These are the methods of Utils class which I am using to start and destroy SESSION.
static function sessionSecureStart()
{
if (session_status() == PHP_SESSION_NONE) {
session_start();
}
}
static function sessionSecureDestroy()
{
//Utils::sessionSecureStart(); This part is for testing only
if (session_status() == PHP_SESSION_ACTIVE) {
$_SESSION = [];
session_destroy();
}
}
Sometimes randomly I get errors/warnings like SESSION could not be destroyed.... Am I doing something wrong?
(I am using PHP/5.5.25)
You don't have to destroy the whole session, just unset the parts you don't need. Let's say that when a user logs in that you set $_SESSION['user_id'] and everything that says I am logged in is looking for that variable. A simple unset($_SESSION['user_id']); and suddenly the user is logged out. Remember, your user doesn't have control over what's in the session.
Another option is to set the session cookies to very low lifetimes. It's cruder but just as effective.
I highly advice you to destroy the session. For both security and performance.
Normally session data is saved in temporary files on the server and in a cookie on the browser, this one only contains the session id but no data.
When you call session destroy you delete this file but you also might tel the browser to delete the session cookie (sending a cookie with the same name which expires in the past). You can know the name calling the session_name() function (normally it's PHPSESSID).
When a user logs out, SESSION becomes useless for me. Do I have to destroy it?
Yes. Besides destroying it, it's also helpful to generate a new session-id
Sometimes randomly I get errors/warnings like SESSION could not be destroyed.... Am I doing something wrong?
You cannot destroy a session that haven't been started. Make sure you have successfully initiated your sessions with session_start(); before trying to destroy it
I know that with sessions in php, a cookie that stores the session ID is set on the client's side. The client can turn off these cookies, which I presumes makes sessions not work. How can I detect if the client has disabled the session cookies?
You can use javascript navigator.cookieEnabled. This returns true or false.
So
if(navigator.cookieEnabled)
//do something
else
//do something else
assuming you started a session on a previous page...
<?php
if(session_status() == PHP_SESSION_ACTIVE)
{
echo 'cookies & sessions enabled';
}
else
{
echo 'no cookies or sessions';
}
?>
or you're looking for a non-session cookies as well.
<?php
if(!empty($_COOKIE))
{
echo 'cookies are tasty';
}
else
{
echo 'no cookies to eat';
}
?>
with a pure php solution you can't check if sessions/cookies are enabled without setting a cookie on a previous page
If you know you MUST use a session, the usual approach is to redirect the user instantly at the start while trying to set a cookie, and then complain about the cookie not being set on the second page.
User goes to http://www.example.com
System sets a cookie (maybe only starts the session, maybe a dedicated test cookie).
System redirects to http://www.example.com/?cookietest=true
On that page, if the cookie is not sent back, complain to the user.
On the other hand, most of the time a session really is not needed if you do not have to log someone in. And IF you do, most users will understand they need to allow cookies, because otherwise the login will fail.
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()
For background, here's my scenario:
I'm building a self-hosted platform for a particular niche, and part of that platform is the login process, which if validated sets a session for the user. On every administration page load, the session is started and the variable $_SESSION['key'] checked to see if it's true.
If it's false, the user is re-directed to the login page with an error telling them to login again.
The problem is this is dependant on a session cookie being set or not set, in the sense that when the session cookie expires and the session is started with session_start() to check $_SESSION['key'], therefore creating a new session cookie with default values (I use session_set_cookie_params() to alter the path, timeout etc) making it impossible to re-login as session cookies do not overwrite from what I can see.
In order to fix this I've thought about using something like session_set_cookie_params(5, ..) before session_start() when checking $_SESSION['key'], which will create a 5 second session cookie, therefore allowing a new one to be created when re-logging in, but I'm not sure whether this would work - and I'm also sure there must be a more efficient way to set/unset a session variable?
Here's my code:
Start session if validated login
if($validated){
session_set_cookie_params(1800, "/inst", $server_name['home']);
session_name("_inst");
session_start();
$_SESSION['key'] = true;
}
Check if $_SESSION['key'] is still true
session_name("_inst");
session_start();
if(!$_SESSION['key']) {
header('Location: ' . $server['home'] . '/login/?error=1');
}
Any answers or advice would be great, and please do ask if you need clarification on anything!
Just issue a session_start() on all pages. This'll unconditionally create a session for you, then you can check for the presence/abscence of the key:
<?php
session_start();
if (!isset($_SESSSION['key'])) { // never logged in, or were logged in and got logged out
... redirect to login ...
exit();
}
if ($_SESSION['key'] != 'expected value') { // logged in, but no longer a valid login.
... redirect to login ...
exit();
}
You shouldn't have to mess with the session cookie settings at all. Leave them at default and simply check for the relevant key(s). if they're not there, then the user is not logged in and should be redirected.
If their session had expired and PHP cleaned up the session file, then they've been effectively logged out, even though they have a it-was-valid-at-one-point-in-time session key, and should get redirected to login again.