Cookies won't set, session works - php

I'm sorry for the small amount of information, but there is not much else I can give you. The problem is, when trying to extend my login function to add an option for staying logged in, the cookies won't set. The session itself works (so there are no blank characters or something). I get no error messages, the cookie just doesn't set (tested with opera/firefox). After being puzzled for over an hour, i decided to ask it here. Below is the login function. Further down you will find how it's called. Don't worry about the password in the cookie, it's hashed. I tested if the code is in fact executed (placed an echo 'abc' before setcookie) which is the case.
public function login($password,$stayloggedin) {
if ( is_null( $this->id ) ) trigger_error ( "user::login(): Attempt to login an user object that does not have its ID property set.", E_USER_ERROR );
if ($this->compare_password($password))
{
if ($stayloggedin)
{
setcookie("userid", $this->id, time()+3600);
setcookie("userid", $this->password, time()+3600);
}
session_start();
$_SESSION['user_id'] = $this->id;
$_SESSION['user_name'] = $this->name;
$_SESSION['user_nummer'] = $this->user_nummer;
return true;
}
else
{
return false; //wrong password
}
}
This is how the above function is called.
<?php
header('Content-type: text/html; charset=UTF-8');
require_once 'required_script.php';
if (isset($_GET['login']))
{
require_once CLASS_PATH.'user.class.php';
$user_logging_in=new user();
$user_logging_in->load_from_name($_POST['user_name']);
if (isset($user_logging_in->id))
{
if ($user_logging_in->login($_POST['user_pass'],$_POST['remember_me']=='true'))
{
echo '1';
}
else
{
echo '0';
}
}
else
{
echo '2';
}
die;
}
Thanks a lot.

Your cookie won't set because you're outputting HTML headers before the log in / cookie setting functionality happens.
You can't pass any headers to the browser prior to creating the cookie.

Related

PHP Auto Login after Registration

I'm having some issues with a request from my boss.
I'm using the http://www.html-form-guide.com/ Registration forms he has created for use (I've attached the link just in case anyone want to use or look at it)
So I'm pretty new to PHP, but I've been gaining a crazy amount of knowledge.
Here is my problem - I need to make this form Register the user than Login Automatically. (This form has a Email confirmation system)
So I've managed to bypass the Email Confirmation and get the user to register, but I can't seem to figure out how to get auto login.
Here is what I've traced in the code:
function RegisterUser()
{
if(!isset($_POST['submitted']))
{
return false;
}
$formvars = array();
if(!$this->ValidateRegistrationSubmission())
{
return false;
}
$this->CollectRegistrationSubmission($formvars);
if(!$this->SaveToDatabase($formvars))
{
return false;
}
/*if(!$this->SendUserConfirmationEmail($formvars))
{
return false;
}*/
$this->SendAdminIntimationEmail($formvars);
$this->AutoLogin($formvars);// My call
return true;
}
This will pull in the name, email and password - put them in an array then send it off for validation and sanitation. I've placed a call function here.
After which I'll need to manually login with:
function Login()
{
if(empty($_POST['email']))
{
$this->HandleError("Email is empty!");
return false;
}
if(empty($_POST['password']))
{
$this->HandleError("Password is empty!");
return false;
}
$email = trim($_POST['email']);
$password = trim($_POST['password']);
if(!isset($_SESSION)){ session_start(); }
if(!$this->CheckLoginInDB($email,$password))
{
return false;
}
$_SESSION[$this->GetLoginSessionVar()] = $email;
return true;
}
So I took the last portion of the login function and made:
function AutoLogin(&$formvars)
{
$email = trim($formvars['email']);
$password = trim($formvars['password']);
if(!isset($_SESSION)){ session_start(); }
if(!$this->CheckLoginInDB($email,$password))
{
return false;
}
$_SESSION[$this->GetLoginSessionVar()] = $email;
return true;
}
I did an echo $email; echo $password; exit; test and I can see that the email and password are appearing. But the "Session" (I think) is not starting or the Check Login is not getting the data.
function CheckLogin()
{
if(!isset($_SESSION)){ session_start(); }
$sessionvar = $this->GetLoginSessionVar();
if(empty($_SESSION[$sessionvar]))
{
return false;
}
return true;
}
Now I see the is a CheckLoginInDB which is:
function CheckLoginInDB($email,$password)
{
if(!$this->DBLogin())
{
$this->HandleError("Database login failed!");
return false;
}
$email = $this->SanitizeForSQL($email);
$pwdmd5 = md5($password);
$qry = "Select name, email, pagecode, welcome from $this->tablename where email='$email' and password='$pwdmd5' and confirmcode='y'";
$result = mysql_query($qry,$this->connection);
if(!$result || mysql_num_rows($result) <= 0)
{
$this->HandleError("Error logging in. The email or password does not match");
return false;
}
$row = mysql_fetch_assoc($result);
$_SESSION['name_of_user'] = $row['name'];
$_SESSION['email_of_user'] = $row['email'];
$_SESSION['pagecode_of_user'] = $row['pagecode'];
$_SESSION['welcome_user'] = $row['welcome'];
return true;
}
What I can gather from this, its just a standard checking the database to see if this user exists and returning the results.
I've searching through stackoverflow and can't seem to see an answer to my problem.
I looked into Cookies, but I don't think that is something I really need here.
My questions are:
How can I make this bad boy start the session on registration?
Is my thinking on calling the AutoLogin(&$formvars) the right idea?
Have I gone wrong with this AutoLogin function syntax?
Just in case here is the GetLoginSessionVar():
function GetLoginSessionVar()
{
$retvar = md5($this->rand_key);
$retvar = 'usr_'.substr($retvar,0,10);
return $retvar;
}
It's a pity I can't attached the file I'm working on, but if you need any further code snippets let me know and I'll be sure to Edit this straight away!
But the "Session" (I think) is not starting or the Check Login is not
getting the data.
Is my thinking on calling the AutoLogin(&$formvars) the right idea?
Have I gone wrong with this AutoLogin function syntax?
It's not something wrong with the syntax, otherwise the code wouldn't even be compiled. Nevertheless I believe it's not the right idea.
You need to understand what's the problem before trying to fix it.
Debug the code. Use xdebug. If it's installed and active, you can use IDEs (e.g.: Visual Studio Code) to easily debug the code. Add breakpoints where you suspect there's something wrong.
If you don't want to use xdebug, you can add temporarily echoes or var_dumps to check if some areas of the code are processed and check some relevant values.
Also enable all errors reports and use a logger.
If the session is started after any output, there should be some warning.
Handle the errors and throw exceptions.
http://php.net/manual/en/function.error-log.php
http://php.net/manual/en/function.syslog.php
https://jtreminio.com/2012/07/xdebug-and-you-why-you-should-be-using-a-real-debugger/
session_start() works after output being sent
http://php.net/manual/en/function.error-reporting.php
You don't need to use the & in AutoLogin(&$formvars) if you're not changing the argument $formvars (you're just reading it).
You don't need to set session variables with all the user data. Create some structure (a class, an array, ...) with the user data outside those function and change those. AutoLogin should update that structure, something like this:
<?php
if (!$_SESSION) {
session_start();
}
$currentUser = array();
function getUserFromID($userID)
{
//TODO implement function
return $user;
}
function AutoLogin()
{
global $currentUser;
if(!empty($_SESSION['userID'])) {
return false;
}
$user = getUserFromID($_SESSION['userID']);
if (empty($user)) {
return false;
}
$currentUser = $user;
return true;
}
Maybe the session is not initialised before CheckLoginInDB is invoked (make var_dump($_SESSION); to check it). Use the $_SESSION only to save the user ID (or email) and read it to retrieve the user data.

Having problems building my login-function, cant store sessions (php)

I am a Beginner. Right now I am trying to build a simple Login/Register-System to learn.
It worked once, but not anymore and I cant figure out where im going wrong. Slowly my Code becomes Spaghetti.
What I want:
LOGIN-System that starts a Session after logging in. But the session is not working! Please beware that all the echos are ugly but just for me to check right now!
My HTML CODE:
//Check if class responds
$user->classtest();
session_start();
//Login-Function
if($user->checkSession()) {
echo "Session is okay";
} else {
if(isset($_POST['uname']) && isset($_POST['upass'])) {
$name = $_POST['uname'];
$pass = $_POST['upass'];
if($user->checkPW($name,$pass)) {
$user->startSession($name,$pass);
} else {
echo "Your Login is wrong, please try again";
$user->loginForm();
}
} else {
echo "<br>You are not logged in. Please login!";
$user->loginForm();
}
}
Here are the function from the classes:
Starting the Session:
public function startSession($uname,$upass) {
$userData = $this->getUserData($uname);
session_start();
$_SESSION['username'] = $userData[0]["username"];
$_SESSION['password'] = $userData[0]["password"];
echo "<br>You are logged in and we started the session ";
echo "<br>Username: " . $_SESSION['username'] . "<br>";
echo "<br>Password: " . $_SESSION['password'] . "<br>";
return true;
}
and my function that should check if there is a Session:
public function checkSession() {
if(isset($_SESSION['username']) && isset($_SESSION['password'])) {
return true;
} else {
return false;
}
}
Now, although my startSession function gives me the $_SESSION['username'] correctly after submitting the login-form the checkSession() Function always gives me false.
Sorry for the not perfect code etc. Im a real beginner still figuring things out!
You call checkSession BEFORE you ever call session_start(), which means $_SESSION will be empty, and your isset() calls will fail.
Just init the session with session_start(); on the top of your file.
Or - if necessary - in the construct function of your class:
function __construct() { session_start(); }
Please be aware of having output before initialise Session (or setting cookies also).

PHP session_id regenerated on refresh

I am having problems with the session_id() that returns a new value every time on browser refresh/restart.
Read this post here but it doesn't solve the issue.I did all that was mentioned there - browser accepts cookies, permissions are set correctly, no param value is changed on sequential requests, etc.
Could this be refered to not using the session_name() or session_set_cookie_params() correctly? Or maybe it is the initial configuration that should be fine-tuned?
public static function init_session($name = FALSE, $lifetime = 10, $path = '/', $domain = FALSE, $secure = FALSE)
{
if (empty($name))
{
$name = APP_NAME;
}
if (empty($domain))
{
$domain = BASE_URL;
}
session_name($name);
session_set_cookie_params($lifetime, $path, $domain, $secure, TRUE);
session_start();
echo session_id();
}
First of all, you set your session lifetime to 10 seconds, which means that you get a new session after every 10 seconds.
Side note: It's normal behaviour for some browsers to discard session cookies when closing the browser.
If you need your session to expand over multiple browser sessions, you need to use persistent cookies.
Example:
function init_session(/* ... */)
{
if(!isset($_SESSION)) {
session_start();
}
//Is it a running session?
if(isset($_SESSION['somevalue'])) {
//Everything is fine, session is loaded, no need to reload from cookies
} else {
if(isset($_COOKIE['yourcookiename'])) {
//reload session from cookie
} else {
create_session();
}
}
}
function create_session()
{
$_SESSION['somevalue'] = 1;
//setcookie
}
Read http://www.allaboutcookies.org/cookies/cookies-the-same.html

PHP Session believes it's being hijacked unless an echo is performed

I'm writing a simple website which allows a user to login, fill out a form which is submitted to a database and then log out. In order to manage the session, I used the session manager which is described by TreeHouse on the following page: http://blog.teamtreehouse.com/how-to-create-bulletproof-sessions
In order to protect against hijacking, the client's IP address and user agent are stored in the session variable and compared to the server's values for these properties on each page. If they don't match, then it is assumed that the session has been hijacked and it is reset.
The implementation seems to work on my local machine without any issues, but when I uploaded it to the server, each page refresh causes the preventHijacking() function to return false (meaning it believes the session has been hijacked). However, if I echo any text within that function, the problem mysteriously disappears and the whole thing works as I expect it to (except for the bit of echoed text which is now displayed above my form :P).
I haven't a clue why this would be the case and I can't figure out how to fix it. The session manager code is below. At the start of each page, I use this to start the session and then each page simply uses or sets whatever variables it requires. If anyone could suggest why the function always returns false unless it echoes text and perhaps suggest what modification I need to make so that it will behave in the expected manner, I'd really appreciate it.
<?php
class SessionManager {
protected static $timeout = 600; // Time before automatic logout for the session
static function sessionStart($name, $limit=0, $path='/', $domain=null, $secure=null) {
// Set the cookie name before we start
session_name($name.'_Session');
// Set the domain to default to the current domain
$domain = isset($domain)? $domain : $_SERVER['SERVER_NAME'];
// Set the default secure value to whether the site is being accessed with SSL
$https = isset($secure)? $secure : isset($_SERVER['HTTPS']);
// Set the cookie settings and start the session
session_set_cookie_params($limit, $path, $domain, $secure, True);
session_start();
// Make sure the session hasn't expired and destroy it if it has
if(self::validateSession()) {
// Check to see if the session is new or a hijacking attempt
if(!self::preventHijacking()) {
// Reset session data and regenerate ID
$_SESSION=array();
$_SESSION['IPaddress'] = $_SERVER['REMOTE_ADDR'];
$_SESSION['userAgent'] = $_SERVER['HTTP_USER_AGENT'];
self::regenerateSession();
// Give a 5% chance of the session ID changing on any request
} else if (rand(1, 100) <= 5) {
self::regenerateSession();
}
$_SESSION['LAST_ACTIVITY'] = time();
} else {
$_SESSION = array();
session_destroy();
session_start();
}
}
static function preventHijacking() {
if(!isset($_SESSION['IPaddress']) || !isset($_SESSION['userAgent'])) {
return false;
}
if($_SESSION['IPaddress'] != $_SERVER['REMOTE_ADDR']) {
return false;
}
if($_SESSION['userAgent'] != $_SERVER['HTTP_USER_AGENT']) {
return false;
}
return true;
}
static function regenerateSession() {
// If this session is obsolete, it means that there already is a new id
if(isset($_SESSION['OBSOLETE']) && $_SESSION['OBSOLETE'] === True) {
return;
}
// Set current session to expire in 10 seconds
$_SESSION['OBSOLETE'] = True;
$_SESSION['EXPIRES'] = time() + 10;
// Create new session without destroying the old one
session_regenerate_id(false);
// Grab current session ID and close both sessions to allow other scripts to use them
$newSession = session_id();
session_write_close();
// Set session ID to the new one and start it back up again
session_id($newSession);
session_start();
// Now we unset the obsolete and expiration values for the session we want to keep
unset($_SESSION['OBSOLETE']);
unset($_SESSION['EXPIRES']);
}
static protected function validateSession() {
// Check if something went wrong
if(isset($_SESSION['OBSOLETE']) && !isset($_SESSION['EXPIRES'])) {
return false;
}
// Test if this is an old session which has expired
if(isset($_SESSION['EXPIRES']) && $_SESSION['EXPIRES'] < time()) {
return false;
}
// Check if the user's login has timed out
if(isset($_SESSION['LAST_ACTIVITY']) && (time() - $_SESSION['LAST_ACTIVITY']) > self::$timeout) {
return false;
}
return true;
}
}
?>
I could be way out here (it's been a while) but that sounds like the buffer containing the headers isn't being flushed for some reason. Providing body would force them to be flushed, so maybe not providing the body doesn't flush?
Try putting ob_end_flush(); in there before you return. That may fix it.

cookie won't set

This is a question regarding an old one of mine: cookie won't unset:
cookie wont unset
where I had problems unseting the cookie (but it was set 'properly'),
Now that the problem is solved; the cookie doesn't seem to SET
cookie 'set': (does not work)
setcookie("id",$data['id'], time()+3600*24*30,'/');
setcookie("alias",$data['nombre'], time()+3600*24*30,'/');
cookie check: (seems to work)
function sesion(){
if(isset($_COOKIE['id']) && isset($_COOKIE['alias'])){
$_SESSION['logueado'] = true;
$_SESSION['id'] = $_COOKIE['id'];
$_SESSION['alias'] = $_COOKIE['alias'];
return true; //THIS IS NEVER RETURNING TRUE
}
if(isset($_SESSION['id']) && isset($_SESSION['logueado']) && $_SESSION['logueado'] == true){
return true;
}
else{ return false;
}
}
cookie unset: (works)
function cerrar_sesion(){
session_start();
$_SESSION['logueado']= false;
$_SESSION['id']= NULL;
session_unset();
session_destroy();
setcookie("id",false,time()-3600,"/");
setcookie("alias",false,time()-3600,"/");
unset($_COOKIE['id']);
unset($_COOKIE['alias']);
}
What happens is that login is working only through $_SESSION so after 30 minutes of no activity the user is no longer logged in,
Any idea what I'm doing wrong? Thanks a lot!
As stated above you cannot read a cookie from the same page as it is set. I see you have tried tricking this using ajax but i do not believe that would be a valid trick as Ajax calls do not change the state of the page you are still on. so you can either do a full refresh or redirect OR at the same time you use setcookie you can also define the values you need in $_COOKIE so its available on the same page. like this:
setcookie("id",$data['id'], time()+3600*24*30,'/');
setcookie("alias",$data['nombre'], time()+3600*24*30,'/');
$_COOKIE['id'] = $data['id'];
$_COOKIE['alias'] = $data['nombre'];
set cookie lines work fine with me.
as for }else if(isset($_COOKIE['id']) && i
since you return if you remove the else here is still okay, if there was no return above you would have to keep the else here in order not to evaluate this block
generally speaking I am not sure that elseif is the same with else if in all cases
The way the function session is build will act like this:
On the first load it will show: no cookie, no session because you cannot see a cookie until reload (which I guess you already know).
-On second load you will see cookie alive session set.
-after the second load you always see session is set.
All I want to say that session works exactly as expected to work, so I don't really see any problem.
<?php
$data='Hello';
setcookie("id",$data['id'], time()+3600*24*30,'/');
setcookie("alias",$data['nombre'], time()+3600*24*30,'/');
session_start();
function sesion()
{
if(isset($_SESSION['id']) && isset($_SESSION['logueado'])
&& $_SESSION['logueado'] == true)
{
echo 'SESSION IS SET<br>';
return true;
}
if(isset($_COOKIE['id']) && isset($_COOKIE['alias']))
{
$_SESSION['logueado'] = true;
$_SESSION['id'] = $_COOKIE['id'];
$_SESSION['alias'] = $_COOKIE['alias'];
echo 'COOKIE is alive and session set'.$_SESSION['alias'].'<br>';
return true; //THIS IS NEVER RETURNING TRUE
}
else
{
echo 'NO SESSION, NO COOKIE YET, WAIT UNTIL REFRESH<br>';
return false;
}
}
sesion() ;
?>
Try removing the path parameter from your setcookie() calls, maybe that's the issue.
Also, did you check that $data actually contains any data?
Propably you have really known problem with setting cookies and you have disabled error reporting about warnings.
Just try:
error_reporting(E_ALL);
You will propably see at your page something like "Cannot modify headers. Headers already sent". That because you need to SET cookies before you display anything on your page. So solution to resolve your problem is to implement your code to SET cookies at the bottom of your page or use ob_start/ob_clean.
Let me know if it helps :)
According to the "setcookie()" implementation in PHP, the cookie value check will not work until you move the control from the page that you are creating the cookie. So, your "SET" will create the cookie in one page and "sesion()" should be called from other page to check the value of the cookie that you set. Try it and hope it helps!
Try the following approach (please refine this as per your need). What I am trying here to refresh the page itself after setting the cookie and the "sesion()" function is a dynamic function that may or may not have any arguments. So, when you pass any argument to it, the the cookie will be set, otherwise it will be checked for existence. An accompanying function with func_num_args() is func_get_args(). It will help you to sanitize the expected arguments in the function.
<?php
error_reporting(E_ALL);
ini_set("display_errors", 1);
ini_set("log_errors", 0);
session_start();
function sesion(){
// func_num_args() number of arguments passed to the function
if (func_num_args() == 0) { // if no arguments were passed, means the page is refreshed and cookie won't be set further
if(isset($_COOKIE['id']) && isset($_COOKIE['alias'])){
$_SESSION['logueado'] = true;
$_SESSION['id'] = $_COOKIE['id'];
$_SESSION['alias'] = $_COOKIE['alias'];
return true; //THIS IS NEVER RETURNING TRUE
}
if(isset($_SESSION['id']) && isset($_SESSION['logueado']) && $_SESSION['logueado'] == true){
return true;
}
else {
return false;
}
}
else { // if number of args > 0, means you need to cookie here and refresh the page itself
global $data; // set this to global as the $data will be available outside of this function
setcookie("id",$data['id'], time()+3600*24*30,'/');
setcookie("alias",$data['nombre'], time()+3600*24*30,'/');
/**
* refresh the page by javascript instead of header()
* as header already being sent by the session_start()
*/
echo '<script language="javascript">
<!--
window.location.replace("' . $_SERVER['PHP_SELF'] . '");
//-->
</script>';
die();
}
}
sesion(1); // passed an argument to set the cookie
?>
I think you will face issue with the JavaScript section, as it will change the page URL and I guess you are trying to include this script into the pages. So, I will take the help of call_user_func() and the final "else" part after the setcookie() lines will be changed with the following line:
call_user_func("sesion");
Hope this will make sense now.

Categories