I have looked through a few previously answered questions, but the solutions don't seem to work for me.
So I have a simple login script that looks like the following:
login.php
// If page requires SSL, and we're not in SSL mode,
// redirect to the SSL version of the page
if($_SERVER['SERVER_PORT'] != 443) {
header("HTTP/1.1 301 Moved Permanently");
header("Location: https://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']);
exit();
}
// put sha1() encrypted password here
$password = 'sha1passwordgoeshere';
session_start();
if (!isset($_SESSION['loggedIn'])) {
$_SESSION['loggedIn'] = false;
}
if (isset($_POST['password'])) {
if (sha1($_POST['password']) == $password) {
$_SESSION['loggedIn'] = true;
} else {
$logFailure = true;
}
}
if (!$_SESSION['loggedIn']):
// Load Login Page
exit();
endif;
logout.php
// If page requires SSL, and we're not in SSL mode,
// redirect to the SSL version of the page
if($_SERVER['SERVER_PORT'] != 443) {
header("HTTP/1.1 301 Moved Permanently");
header("Location: https://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']);
exit();
}
// 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();
The rest of my pages include login.php at the top of the file.
All seems to work fine, most of the time. However, I have been noticing since I have moved over to a new server, and using php 5.6.14 that I have been getting timed out from time to time.
For example, right now I can login with Internet Explorer, but I can't with Firefox or Chrome. If I clear cookies, I can then login with Firefox and Internet Explorer, but not Chrome.
UPDATE
I can cause a timeout immediately by logging in successfully, logging out immediately, then logging in again. On the second login, it times out.
It is really been frustrating me, and I am not a session guru, so I don't understand why it is acting in this way, or how to fix it so that it isn't so delicate.
I am only using sessions to record the login, and not for anything else. I do use AJAX on certain pages within the site, but not often.
Basically, I never want this to time out. How would I prevent these time outs from happening?
I have fixed the issue. First, I had used a form button on the log out page to allow a user to log back in. I replaced that with a standard link.
Second, after login, the landing page had a section of code that would create error warnings on the log file with a foreach expecting an array (even though it was an array and outputted properly). Removing that section of code seems to have fixed the issue. I am not sure how this would cause problems.
Related
I just finished creating a website that includes a login page. When the user attempts to log in, I check the username and password against the database. If they both match, I start a session and set the session variables 'id' and 'uid', like so:
$sql = "SELECT * FROM users WHERE uidUsers = ? OR emailUsers = ?";
$stmt = mysqli_stmt_init($conn);
if (!mysqli_stmt_prepare($stmt, $sql)) {
header("Location: ../login.php?error=sqlerror");
exit();
}
else {
mysqli_stmt_bind_param($stmt, "ss", $mailuid, $mailuid);
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
if ($row = mysqli_fetch_assoc($result)) {
$pwdCheck = password_verify($password, $row['pwdUsers']);
if ($pwdCheck == false) {
header("Location: ../login.php?error=wrongpwd&mail=".$mailuid);
exit();
}
elseif($pwdCheck == true) {
session_start();
$_SESSION['id'] = $row['idUsers'];
$_SESSION['uid'] = $row['uidUsers'];
header("Location: ../login.php?login=success");
exit();
}
else {
header("Location: ../login.php?error=wrongpwd");
exit();
}
}
else {
header("Location: ../login.php?error=nouser&mail=".$mailuid);
exit();
}
}
In my header.php file, which is linked within every php page using include 'header.php';, I have php code that displays either log in/sign up buttons (if $_SESSION['id'] is not set) or a log out button (if $_SESSION['id'] is set). I also started a session in the header.php page. This is what the code of header.php looks like:
session_start();
if (isset($_SESSION['id'])) {
echo
"<div id='logout-form'>
<form action='includes/logout.inc.php' method='post'>
<button type='submit' name='logout-submit'>Log Out</button>
</form>
</div>";
}
else {
echo
"<div id='header-form'>
<form action='includes/login.inc.php' method='post'>
<button type='submit' name='login-button-header'>Log In</button>
</form>
<button id='signup-button'><a href='signup.php' class='header-signup'>Sign Up</a></button>
</div>";
}
if (isset($_SESSION['id'])) {
echo '<p class="greeting">Hello, <span class="greetingName">' . $_SESSION['uid'] . '</span></p>';
}
date_default_timezone_set("America/Los_Angeles");
Using xampp, I am connected to an apache server offline. When clicking through my site, the sessions work for every page; if I log in, it registers that I've logged in on every page I go to, as it should. However, when I posted my website a few days ago, it had trouble knowing if I was logged in or out. My website URL is writingboxco.com if you would like to see what I'm about to talk about. When I log in, it seems to know that I am logged in on every web page; I know this because it provides the message "Hello, [username]" on every page, which only happens when $_SESSION['id'] is set. However, when I click "Log Out" and go back to the home page, it still thinks that I'm logged on (because I probably am, but I don't know why). When the "Log Out" button is clicked, the script "logout.inc.php" runs. In this file, I unset and destroy the session variables, like so:
session_start();
session_unset();
session_destroy();
$_SESSION = [];
header("Location: ../login.php");
Additionally, I only stay logged in on some pages of the website. Some of them register that I've logged out, while other don't.
I'm not sure why I stay logged in after clicking the "Log Out" button, which should destroy the session variables. When my site is used offline, it works perfectly fine; when I log out, every page realizes it. However, when online, it doesn't work for every page. It only works for some (some pages stay logged in and some pages correctly log out). Additionally, when I try to log in with an alternate account, it signs me in, but on certain pages, the message "Hello [username]" still displays the username of the account I just logged out of instead of the account I just logged into. Any ideas on what the problem could be? Is it a problem with the failure to destroy the session variables? Could it be other code I should be looking at? Thanks.
UPDATE:
I found that there is an error message stating [28-Jan-2020 00:02:56 UTC] PHP Warning: session_start(): Cannot send session cache limiter - headers already sent (output started at /home1/writipe3/public_html/searchUsers.php:1) in /home1/writipe3/public_html/header.php on line 5
on the error_log file. Any ideas why this would be happening?
When you're destroying a session in PHP you're not actually deleting it. You're merely marking it for garbage collection. The physical deletion happens later. So in order to ensure the session is actually destroyed you must also delete the session cookie, which propagate the session id.
If you look at Example #1 of the session_destory() documentation you'd see some sample code of how to go about doing this:
<?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();
Why is this behavior variable across platforms?
The reason you may see differences in how this atually works out in practice is because different platforms can use different methods of garbage collection for cleaning up session data. For example, on most Windows systems this might actually happen instantly. Some Debian-based (Ubuntu) systems are known to use an asynchronous GC method that happens outside of PHP.
PHP, by default, implements this via a probablistic algorithm wherein each request made to PHP will, within a given probability (usually about 1% of the time) will trigger the GC cycle. So the clean up is non-deterministic in almost all cases.
I have a page, login.php, that processes a username and password and if successful it sets session variables and then redirects the user to home.php. The relevant part of login.php is here:
if ($pwdHash == $storedpass) {
$success = true;
$sessionStatus = session_status();
if ($sessionStatus !== PHP_SESSION_ACTIVE) {
session_start();
}
$_SESSION['user_id'] = $user;
$_SESSION['logged_in'] = true;
session_write_close();
header('Location: http://www.examplesite.com/home.php');
header("HTTP/1.1 303 See Other");
die("redirecting");
}
Then home.php tries to collect the session variable
$sessionStatus = session_status();
if ($sessionStatus !== PHP_SESSION_ACTIVE) {
session_start();
}
$loggedIn = $_SESSION['logged_in'];
The problem is that on the first login attempt, $_SESSION['logged_in'] is undefined and generates an error, even though login.php was successful.
Notice: Undefined index: logged_in
A var_dump of $_SESSION returns an empty array, but sessionStatus reports that the session was already started, it did not have to execute session_start.
This forces the user to log in a second time, then everything is fine. So is the redirect just happening too fast for the session variable to get set? Should I put a delay in the redirect? (and how would I do that?) Or is this something else that I'm doing wrong?
EDIT: I've checked with my host based on an answer to a similar question and confirmed that a session would never be served by more than one server and there is no need to enable sticky sessions or anything like that. I've also updated the code above based an answer offered below and some other research but the error persists.
The session is probably automatically saved when the script ends. You redirect before the script ends.
How long your script takes to really end depends very much on what other code needs to wind down. It is better to explicitly save the session.
How to do this depends on what kind of sessions you use. One type can be closed like this:
http://php.net/manual/en/function.session-write-close.php
If that's the one you're using do this:
if ($pwdHash == $storedpass) {
$success = true;
$_SESSION['user_id'] = $user;
$_SESSION['logged_in'] = true;
session_write_close();
header('Location: http://www.examplesite.com/home.php');
header("HTTP/1.1 303 See Other");
die("redirecting");
}
And the session should be available to the next page when you redirect.
If your sessions work differently, you have to adapt the code, of course. The point I'm trying to make is: Never put a delay in your code. It's unreliable, and pointless. Simply save the session before you redirect.
I have experienced the same issue while writing the session content to the database.
To make it work I have added the sleep() function before setting the session variable, just like below.
sleep(2);
$_SESSION['GUID'] = uniqid(time().rand());
It resolves the issue for me.
We have observed this issue when the page hits are frequent but if one or two users are accessing the page it works as expected.
I have encountered this same issue with a login page but none of the suggestions work for me. The only thing I've found that does work is redirecting the page to itself after 1 second and then checking the session variables to see if the login was successful...
startSession(); // assigns all the login session variables, etc.
header('Refresh: 1; URL=/[THIS_PAGE].php'); // [THIS_PAGE] = the current login page
However, this is a very inelegant solution and I don't like using it. But it "works".
This problem persists. In my case, the user login goes without a problem to the protected homepage, but clicking on a menu link causes the user to be dumped back to the login page to login again. A check on certain Session values (required for both pages) shows these are not set on going to the specific menu link (while other menu links cause no problem). The code requiring a session value is the same in all cases. Not all users experience the problem. Seems that those with less robust connections to the internet always experience this problem. Others, never.
Went to work at a customer's place today and really messed things up. Here is a brief history of what happened.
I created a simple cms for a customer and usually, before I went to the customer, I tested everything by myself, localhost without any problems.
As soon as I transferred the site to a real host and started testing at the customer's place, 2 weird things happened (I have to say that we were both hooked up by cable to the same router so both our external IP addresses must have been the same):
First, when I logged into the cms with chrome, all of a sudden at some point Firefox was also logged in as well without me ever login in via Firefox.
The weirdest thing is that the customer at some point was also logged in it seems without ever loggin in from her computer...
What happened is that some toolbars that onlyh show up in "admin mode" all of a sudden were "added" to the real page content via a save I probably done.
I think we both somehow used the same session ID or something similar and it messed up my code / cms.
Here is the code I currently use for loggins:
I first have this at the top of my page:
if(!isset($_SESSION)){
session_name("sitesession");
session_set_cookie_params(0);
session_start();
}
// make sure user login attempts are no more than 3 times
if (!isset($_SESSION['ip'])){
$_SESSION['ip'] = $_SERVER['REMOTE_ADDR'];
}
if (!isset($_SESSION['logintriesleft'])){
$_SESSION['logintriesleft'] = 3;
}
then later on in the page, i "require_once" the login script which has the following in it:
if (isset($theaction) and ($theaction=="adminlogin")){
$email = $_REQUEST['email'];
$magickey = $_REQUEST['magickey'];
$sth = $DB_con->prepare('SELECT magickey FROM admin_users WHERE email = :email LIMIT 1');
$sth->bindParam(':email', $email);
$sth->execute();
$user = $sth->fetch(PDO::FETCH_OBJ);
if (is_null($user->magickey) || hash_equals($user->magickey, crypt($magickey, $user->magickey))==false) {
$_SESSION['logintriesleft'] = --$_SESSION['logintriesleft'];
if ($_SESSION['logintriesleft'] > 0){
echo '<script>javascript:alert("Bad Login ('.$_SESSION['logintriesleft'].' more tries left before getting banned)...Please Try Again");</script>';
echo '<script>javascript:location.replace("'.$_SESSION['baseurl'].'");</script>';
}else{
echo '<script>javascript:alert("Too many bad login attempts. Contact the website administrator to reactivate your account");</script>';
echo '<script>javascript:location.replace("http://google.ca");</script>';
}
}
else {
$_SESSION["admin"] = "true";
$_SESSION["edit_content"] = "true";
echo '<script>javascript:alert("Successful login! Redirecting you back to the main page!");</script>';
echo '<script>javascript:location.replace("'.$_SESSION['baseurl'].$_SESSION['currentpage'].'");</script>';
break;
}
}
?>
and my logout code is like so:
case "logout":
$_SESSION = array(); // unset all of the session variables
// also delete the session cookie. This will destroy the session, 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();
echo '<script>javascript:alert("Your are now logged out. Goodbye!");</script>';
echo '<script>javascript:location.replace("//www.google.ca");</script>';
break;
I do think my first piece of code is at fault here probably when looking up the ip address of the user but I'm not sure. Like I said, I've never experienced any issues like this until we were two of us on the same router accessing my site on an external host.
Any ideas what might have gone wrong?
Thanks for all your help.
Really annoying problem I can't solve/can only partially solve. Nice juicy one for you pros.
I've got a basic login system set up. Like this:
Login.php:
line 1: session_start();
Check if($_SESSION['logged_in'] == true) header("Location: /controls.php);, incase they've already entered their details.
If they haven't entered them yet, user enters credentials, if valid: $_SESSION['logged_in'] = true;
After database credentials are checked and session is set to true, redirect using PHP header("Location: /controls.php);
Bear in mind, the session is now set.
Controls.php
line 1: session_start();
line 2: if($_SESSION['logged_in'] != true) {header("Location: /index.php");}
Instantly I get taken to index.php ONLY IN CHROME AND FIREFOX.
Also, I have accounttools.php, where the session is again required. Once I try to access accounttools.php, the session is destroyed/unset and any attempt to load accounttools.php results in the header redirect to my /index.php page, again ONLY IN FIREFOX AND CHROME.
I've also got to add in something. If I go back to login.php and re-login, everything works fine and the session gets set properly. Is this a browser-based bug? PHP is executed before any data gets sent to the browser, so how on earth can these browsers act differently if the PHP has already been executed by the time anything reaches the user?
Login file:
// Login.php
<?php session_start();
if($_SESSION['logged_in'] == true)
{
header("Location: /controls.php");
exit();
}
if($_POST['username_login'] && $_POST['password_login'])
{
// Do necessary database work to check credentials (edited out here).
// ...
// Check re-hashed pass against database hash (password checking)
if($make_password == $current_user[0]['password'])
{
// If this is OK login is a success.
$_SESSION['logged_in'] = true;
header("Location: /controls.php");
exit();
}
}
?>
Controls file:
// controls.php
// This page instantly redirects to index.php
<?php session_start();
// Go to homepage if logging out.
if($_POST['logging_out'])
{
unset($_SESSION['logged_in']);
header("Location: /index.php");
exit();
}
// No access unless logged in.
// This session seems to no longer exist at this point. Why??
if($_SESSION['logged_in'] != true)
{
header("Location: /index.php");
exit();
}
?>
Edit: I've discovered something else: If I login and manually enter the URL of the $_SESSION-restricted page, the $_SESSION is not destroyed.
There is some part of the header() redirect that is causing th $_SESSION to become unset/destroyed in Google and Mozilla.
I've also been Googling like crazy and apparently this is a common problem amongs PHP coders. Someone must have a clue what this is?
I see a problem with the way you are redirecting after a successful login: It is a javascript redirect so it will only happen after all the php has finished executing and the result has been sent to the browser. That means that codes after your redirect are executed as well.
I would recommend not outputting anything to the browser until the very end and use the:
header("Location: /...");
exit();
combination everywhere where you want to redirect so that you are sure that nothing happens to your session after the redirect code.
To avoid getting headers already sent problems, I would also recommend getting rid of stuff like:
?>
<?php
like on the first lines of login.php.
i have this file
secure.php
session_start();
if(empty($_SESSION['u_name'])) {
header("Location:emprego.php");
}
if(isset($_GET['logout'])) {
session_destroy();
header("Location:emprego.php");
}
$name = $_SESSION['u_name'];
?>
<li><?php echo "<a href='emprego.php?logout' id='D'>Logout</a>";?></li>
basically, if i do logout, i will be redirected to emprego.php. But if i click in back page button (arrow in browser), i can view the same page (secure.php).
my question is, why?
thanks
http://nl2.php.net/manual/en/function.session-destroy.php
Take a look at example 1 here. It clearly states that you have to clear $_SESSION as well.
if(isset($_GET['logout'])) {
unset($_SESSION['u_name']); //makes it non-existent (it does unset) that variable
session_destroy();
header("Location:emprego.php");
}
Your browser keeps a copy of the page in cache. When you click the back button, you are seeing the local cached copy, not the current page from the server. If your security is set up properly, you will not be able to do anything meaningful from that cached page.
It is for this reason that secure websites (bank sites, for example) tell you to log off and clear your cache (or close the browser) after you log out.
If you're using session cookies, also try expiring the session cookie explicitly, like this:
if (ini_get("session.use_cookies")) {
$params = session_get_cookie_params();
setcookie(session_name(), '', time() - 42000,
$params["path"], $params["domain"],
$params["secure"], $params["httponly"]
);
}
Also, going back in the browser only loads a cached copy of the page. If you tried interacting with the cached page to fetch a new page from the server, you shouldn't be able to proceed.
I recently found header_remove(); http://php.net/manual/en/function.header-remove.php
Caution: This function will remove all headers set by PHP, including cookies, session and the X-Powered-By headers.
Not sure whether this is the appropriate way to do it, but it's pretty effective for log out functionality.
All the other solutions didn't seem to work for me. However, this workaround did the trick. Basically, the code below keeps calling the logout until the logout finally succeeds:
if (isset($_GET["logout"])){
if (isset($_SESSION["username"])) {
unset($_SESSION["username"]);
session_destroy();
header("Location:/?logout=true");
exit;
}
header("Location:/");
exit;
}