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.
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 want display logged in online users on my site like Members Online: 102. I am not catching a perfect and simple way as how to do this. Whether there be a session counting method or any other method to achieve this result. I can do it by using a 0 and 1 column in database table while logging in and logging out but it will not help when the user directly closes the browser and exits the session. That's the real problem. Please help me how to do this. For any instance I am just sharing my login and logout script.
Logout Script
<?php
session_start();
if(isset($_SESSION["zoranelogin"])){
unset($_SESSION["zoranelogin"]);
header("Location: login.php");
}
?>
Login Script
<?php
session_start();
if(isset($_SESSION['zoranelogin'])){
header('Location: dashboard.php');
}
include'config/db.php';
$msg = null;
$date = date('Y-m-d H:i:s');
$uname = (!empty($_POST['uname']))?$_POST['uname']:null;
$pass = (!empty($_POST['pass']))?$_POST['pass']:null;
$mpass = (!empty($_POST['pass']))?md5($_POST['pass']):null;
if(isset($_POST['login'])){
$chklogin = "SELECT * FROM members WHERE mem_uname = :uname AND mem_pass = :pass";
$chklogiq = $pdo->prepare($chklogin);
$chklogiq->bindValue(':uname', $uname);
$chklogiq->bindValue(':pass', $mpass);
$chklogiq->execute();
$checklgn = $chklogiq->rowCount();
$fetch = $chklogiq->fetch();
if($checklgn > 0){
session_start();
$_SESSION['zoranelogin'] = $fetch['mem_id'];
header("Location: dashboard.php");
}else{
$msg = "<div class='message-error'>Username and Password are incorrect. Please try again!</div>";
}
}
?>
It's not possible to detect a closing browser. The best way to know how many users you have on the site is to do it all with sessions. When you use the sessions on file system it's pretty hard because you have to open all the files and read them. So....
The best way to do it is to save your sessions in the database. There you can do set a user id to an session on login and remove it on logout. Then you can count all sessions with an user is with a simple mysql count script.
Here a link with a nice tutorial how to do sessions on a database.
http://www.tonymarston.net/php-mysql/session-handler.html
You still have one more problem. When a user closes his browser you will not see that. This is because a client don't send a message. i'm gone now. That's why we have a session timeout. you can shorten the timeout to say 2min but then you have a problem that when someone is reading a page for more than 2min he will be kicked. You can compensate that with an ajax script every min to update the session but that will take a lot of server traffic/memory. That's why that is not recommended.
Advice: Set your sessions to the database with an timeout of 20min. When someone closes his browser you won't see that for max 20min.
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.
Found a major problem on my website. I found tha if I login with user A. it sometimes kinda does log in but actually doesn't. Then I login with user B -> enter the site. I log out and then go manually back to url where login is needed and it somehow goes in with user A. It seems that I have two (maybe could have more) session_id cookies on different tabs or there is a ghost session_id that comes active I don't know. Pulling my hairs here.
Also found that, lets say I have a user dashboard and test page. With a little going back and forth with different credentials. I get this result:
Dashboard echoes user A's id, test echoes user B's id or not id at all. What the heck I am doing wrong with my sessions?
Login is done with AJAX. Login validation is the same on every page.
COMMON FUNCTIONS:
function validateUser($userid) {
session_regenerate_id();
$_SESSION['valid'] = 1;
$_SESSION['usersid'] = $userid;
}
function isLoggedIn() {
if (isset($_SESSION['valid']) && $_SESSION['valid'] == 1) {
return true;
} else {
return false;
}
}
function logout() {
$_SESSION = array();
session_unset();
session_destroy();
}
LOGIN/DB:
Login page:
session_start();
include 'include_files.php';
if(isLoggedIn()){
header('Location:loginrequiredpage.php');
die();
}
Login page sends username/password with AJAX to an controller php file that uses db functions as included file. It executes usercheckfunc() which checks user from db and then echoes succes or fail back to ajax.
from db functions - part of user check function
//if user found from db and password hash match
validateUser(**ID FROM DATABASE**);
Back in login page if ajax gets success message back, JS send user to login required url.
Here's where mystery sometimes occur The browser acts like if i just logged in somewhere, but the login page is loaded again. Sometimes I can manually go to login required page via address bar. Sometimes if I logout/idle too long etc. and login with different username/password I get in as a wrong user. Entered as user A, See user B's data OR echo different userids on pages or echo id only on other page.
LOGIN REQUIRED PAGE:
<?php
session_start();
require_once 'include_files.php';
if (!isLoggedIn()) {
logout();
header('Location:login.php');
die();
}
echo $_SESSION['usersid'];
Test page:
<?php
session_start();
error_reporting(E_ALL);
ini_set('display_errors', 1);
require_once 'include_files.php';
if (!isLoggedIn()) {
logout();
header('Location:login.php');
die();
}
echo $_SESSION['usersid'];
Is there a "best" way to manage sessions? Help is much appreciated :)
Got rid of the problem by manually setting session cookie parameters everywhere before session_start is executed. Now the session cookie domain doesn't behave unexpectedly. Sorry, no idea why it did that mysterious changeing before.
This cookie parameters sets it to be valid on whole domain. I guess it's no good in situation where you need different sessions on the same domain (different applications etc.). But for me it was the healing patch I needed.
session_set_cookie_params(0, '/', '.example.com');
session_start();
I have just started learning PHP, and I wrote an account system with PHP and mySQL for my website. I know the sql stuff is working fine, the problem is my PHP session.
When I go to test it, I can try to login, and it fails. Then, I try to login again, and it will succeed. It always succeeds on the second attempt to login. It never succeeds on the first attempt in Firefox, but it does in Chrome. Also, a couple of times in Chrome, after I succeeded in logging in, going to a some different pages on my site seemed to erase the session. Or, at least, that session was not registering on those other pages. I didn't have that problem on Firefox. I have checked, double-checked, and triple-checked, and all of my pages call session_start() before anything else, so I know that can't be the problem.
I must not have a full enough understanding of PHP sessions, as it's just not working consistently.
After posting this, I tested in IE, and everything works fine there. I log in on the first attempt, and any page I visit maintains my session.
Here is the code for the php script that actually "logs in" the user:
<?php
session_start();
//pass info to mysql(servername, username, password)
$connect = mysql_connect ("localhost", "ggstudio", "mtgertai1");
if (!$connect)
{
die ('Failed to connect: ' . mysql_error());
}
mysql_select_db("ggstudio_accountDatabase", $connect);
//capture data sent to page through login
//usernameField and passwordField
$usernameSubmission = $_POST[usernameField];
$passwordSubmission = $_POST[passwordField];
$validAccount = mysql_query("SELECT * FROM userAccounts WHERE userID = '$usernameSubmission' AND userPassword = '$passwordSubmission'");
$row = mysql_fetch_array($validAccount);
if (($row['userID'] == $usernameSubmission)&&($row['userPassword'] == $passwordSubmission))
{
/*********************************
**********************************
assign global variables to session
after starting session and then***
redirect to user homepage*********
**********************************
**********************************
*/
//get account number from database
$_SESSION['accountNumber']= $row['accountNumber'];
//get first name from database
$_SESSION['firstName']= $row['firstName'];
//get last name from database
$_SESSION['lastName']= $row['lastName'];
//save username into session
$_SESSION['username']= $row['userID'];
//save password into session (only really useful if user wants to change password)
$_SESSION['userPassword']= $row['userPassword'];
//get user's email address from database
$_SESSION['userEmail']= $row['userEmail'];
//get GP from database
$_SESSION['gpoints']= $row['userGloryPoints'];
//get user join date from database
$_SESSION['userJoinDate']= $row['userJoinDate'];
//get user rank
$_SESSION['userRank']= $row['userRank'];
header('Location: http://www.glorygamer.com/account_home.php');
}
else
{
$loginFailed= TRUE;
setcookie("incorrectLogin", $loginFailed, time()+20);
header('Location: http://www.glorygamer.com/shibboleth.php');
}
?>
If the session is working intermittently then I'd say there's one of two things happening:
Your session isn't being set in the browser correctly
Your session isn't being saved on the server in time.
One thing that can happen (especially when you're testing on localhost) is that an authenticated session isn't written to disk in time for the next request, hence the next request appears to be un-authenticated (remember that apache is multi-process; your second request could be handled by another process which isn't aware of what the first is doing). Here's one possible solution:
$_SESSION['userRank']= $row['userRank'];
session_write_close();
header('Location: http://www.glorygamer.com/account_home.php');
The call to session_write_close() should mean that your authenticated session is ready in time for the next request.
HTH.
The first thing I see are the lack of single quotes. Also, you should definitely escape these so that nobody can do any SQL injection on you.
$usernameSubmission = $_POST[usernameField];
$passwordSubmission = $_POST[passwordField];
should be:
$usernameSubmission = mysql_real_escape_string($_POST['usernameField']);
$passwordSubmission = mysql_real_escape_string($_POST['passwordField']);