session does not propagate after header("Location: page.php")

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • bilibytes
    New Member
    • Jun 2008
    • 128

    session does not propagate after header("Location: page.php")

    hi,

    i am making a website with php OOP.
    i have a class called session:
    it has the attribues
    -logged_in;
    -user_name;
    -user_ip;
    -user_level;

    and two methods
    -__construct
    -starter()
    -check_logged_in ()

    ok
    constructor calls:
    session_start()
    and sets:
    -logged_in = check_session;

    the starter, ... puts all the user information into $_SESSION array and then assigns that values to the user attributes: -user_name, -user_ip...

    so when i call the object instance, constructor will determine if the user is logged in by calling -check_session which checks if:
    $_SESSION[user_name] ... exist, if yes, it assigns its values to the attribues
    and returns true, else returns false.

    the point is that when i start the session by calling starter at one point of the script, and print_r($_SESSI ON) it will output all the user information which is normal.. this means the session has been correctly started.

    BUT, when from the same part of the script, i redirect the user with header("locatio n:page.php")
    page.php will call session->logged_in and it will return false....

    is there a reason for that?

    thnak you

    bilibytes
  • Atli
    Recognized Expert Expert
    • Nov 2006
    • 5062

    #2
    Hi.

    Could we see the actual code?

    Your explanation makes it sound like it should work, in theory, but we can't really know why it isn't working unless we can see the code.

    Comment

    • bilibytes
      New Member
      • Jun 2008
      • 128

      #3
      here is the session.php class:

      [PHP]class Session
      {
      const LEVEL_ADMIN = 1;
      const LEVEL_S_USER = 2;
      const LEVEL_G_USER = 8;
      const LEVEL_GUEST = 9;

      public $logged_in; //TRUE if user has given a good PHPSESSID and this SESSID comes from the same IP that athenticated
      public $user_name;
      public $user_IP;
      public $user_level;
      public $error;

      function __construct(){
      if(!isset($_SES SION))
      {
      session_start() ;
      }
      $this->logged_in = $this->check_session( );
      }

      function starter($userna me, $level){//this method is called from session_auth
      global $database, $calendar_auto_ updater;

      /**
      * Session Start - sets a session cookie
      *
      *
      * 1. First time user opens the page (there is no file in the server)
      *
      * -PHP generates a random value which is used to
      * -give value to PHPSESSID: cookie that he sends to Client'sBrowser
      * -Client's Browser keeps it for an undefined period of time
      * -give name to a File in the Server
      *
      *
      * 2. n>1 Time user opens the page (there is a file in the server)
      *
      * -Client's Browser Sends an HTTP Header with the PHPSESSID cookie
      * -PHP gets PHPSESSID cookie value with session_start()
      * -Looks for a file named like the value contained in the cookie (assumming he finds it)
      * -Reads its content and creates an array $_SESSION containing the pairs key values
      * -At the end of the script if there are $_SESSION[''] attributions:
      * -Write into the server file
      */


      session_regener ate_id();

      $this->user_name = $_SESSION['user_name'] = $username;
      $this->user_IP = $_SESSION['user_IP'] = $_SERVER['REMOTE_ADDR'];
      $this->user_level = $_SESSION['user_level'] = $level;
      if($calendar_au to_updater->auto() == true){
      if($database->DB_add_active_ user($this->user_name, $this->user_IP, $this->user_level, session_id()) == true){
      /**
      * we have to recall check session to set logged in = true because at object instace calling,
      * the constructor checks logged in before starting a new session
      * with $this->starter.
      * this is: firts logged_in == false and once starter called logged_in should be true, but check_session is not called again.
      * this is why logged_in has to be set to logged_in from starter method
      */
      $this->logged_in = true;
      return true;
      }
      else{
      $this->error = "could not insert active user into db";
      return false;
      }
      }
      else{
      print_r($calend ar_auto_updater->error);
      }

      }

      function check_session() {
      global $database;

      /**
      * if the user has been authenticated, the script has sotred his name on session file
      * so if the user gives a SESSID which refers to a file with no name on it, this mean
      * it is a malicious user.
      * if the user gives a SESSID which refers to a file with a name on it, check if the
      * SESSID comes from the same IP the first user authenticated from.
      */

      if(isset($_SESS ION['user_name']) && isset($_SESSION['user_IP'])){//there is a value in file with key user_name
      if($_SERVER['REMOTE_ADDR'] == $_SESSION['user_IP']){// if the client IP corresponds to the first (authenticated) client IP
      /* Check if the user is logged in, if yes, store session variables, else log him totally out */
      if($database->DB_check_activ e_user($this->user_name, $this->user_IP) == true){
      $this->user_name = $_SESSION['user_name'];
      $this->user_IP = $_SESSION['user_IP'];
      $this->user_level = $_SESSION['user_level'];
      return true;
      }
      else{
      $this->unset_session( );
      return false;
      }
      }
      else{//there is a fraud, report it to DB
      $database->DB_report_frau d($_SESSION['user_name'], $_SERVER['REMOTE_ADDR']);
      return false;
      }
      }
      else{// the user is not authenticated
      return false;
      }
      }

      public function add_session_var s($obj ,$key, $value){
      $_SESSION[$obj][$key] = $value;
      if($_SESSION[$obj][$key] == true){
      return true;
      }
      else{
      return false;
      }
      }

      function unset_session() {
      global $database;

      // 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 (isset($_COOKIE['PHPSESSID'])) {
      setcookie('PHPS ESSID', '', time()-42000, '/');
      }

      // Finally, destroy the session.
      session_destroy ();

      if($database->DB_set_unactiv e_user($this->user_name, $this->user_IP)){
      return true;
      }
      else{
      print_r($databa se->error);
      }
      }

      }
      ?>[/PHP]

      then here is the session_auth.php class, it is used to check the posted user credentials consistency:

      [PHP]class Session_auth extends Session
      {
      const MAX_PASS_ERR = 3; //number of times a user is allowed to fail submiting password

      private $secured = "jo2lDly5ju_m66 FDperIs%";
      public $errors = false;
      private $DB_response; //stores the result of DB class query
      public $pre_user; //username with stripslashes for DB checking
      private $pre_pass; //password with stripslashes + md5 for DB checking
      public $pre_mail;

      /* Basic form submitted data checking */
      function login($sub_user , $sub_pass){
      global $database, $session, $account_manage r, $pre_session; //+$mail

      $this->pre_user = $sub_user;

      /* -USERNAME- */
      /* Check it the username is long enough getting rid of spaces */
      if(!$sub_user || strlen($sub_use r) < 8){
      $this->errors['sub_user']['char'] = "Need Username, minimum length is 8";
      }
      /* Check if username is not alphanumeric */
      else if(!eregi("^([0-9a-z])*$", $sub_user)){
      $this->errors['sub_user']['char'] = "Username not alphanumeric";
      }
      /* Store sub_user on a momentanious var $pre_user */
      else{
      $this->errors['sub_user'] == false; //no errors
      }
      /* -PASSWORD- */
      /* Check it the password is long enough getting rid of spaces */
      if(!$sub_pass || strlen($sub_pas s) < 8){
      $this->errors['sub_pass']['char'] = "Need Password, minimum length is 8";
      }
      /* Store sub_pass on a momentanious var $pre_pass with md5 */
      else{
      $this->pre_pass = md5($sub_pass);
      $this->errors['sub_pass'] == false; //no errors
      }

      /* CHECK AGAINST DB and do... */
      if($this->errors['sub_user']['char'] == false && $this->errors['sub_pass']['char'] == false){//if no character errors

      $this->DB_response = $database->DB_login_crede ntials($this->pre_user, $this->pre_pass);

      /* User and Pass match in DB */
      if($this->DB_response == true){
      unset($this->errors); // delete error content for next try
      if($database->DB_check_unact ive_user($this->pre_user, "all") == true){//check if the user is not logged in from elswhere

      if($database->DB_isnot_quara ntine_user($thi s->pre_user) == true){//check if the user is in quarantine
      /* The user seems has the rights to log in */
      if($session->starter($thi s->pre_user, $database->response_level ) == true){
      return true;
      }
      else{
      $this->errors['general']['auth'] = "Sorry, the system was unable to log you in, there was a Server error";
      return false;
      }
      }
      else{
      $session->starter($thi s->pre_user, 8); //start a session with reduced powers, to make availible user_name to quarantine to resend a mail
      $this->errors['general']['auth'] = "You were put in quarantine at last login attempt, please check your mail box, an e-mail should have been sent. Click here to be sent another one. <a href=quarantine .php?mail=resen d>Resend em@il</a>";
      return false;
      //$database->error['log']['user'] is the real error
      }
      }
      else{ //the user has logged in from a different ip
      //as the user has given the right credentials, but he has to logout before relogging in...
      //so create a pre session that will only allow him to loggin after having done what we asked him
      $pre_session->pre_starter($t his->pre_user, $database->response_level );
      $this->errors['session_auth'] = $database->error['log']['user'];
      $database->DB_report_frau d($this->pre_user, $_SERVER['REMOTE_ADDR']);
      return false;
      }
      }
      /* DB returns Error */
      else{
      if($database->error['log']['user'] == true){//user does not exist in db
      $this->errors['sub_user']['DB'] = $database->error['log']['user'] ;
      return false;
      }
      else if($database->error['log']['pass'] == true){//the client has submited wrong password
      if($database->DB_isnot_quara ntine_user($thi s->pre_user)){//the user is not in quarantine, so lets see how many tries he has left and put him in quarantine if necessary
      if($database->DB_report_wron g_pass($this->pre_user, $this->pre_pass.$sub_ pass, $_SERVER['REMOTE_ADDR']) == true){
      //calculate the number of tries left
      $max_tries = Session_auth::M AX_PASS_ERR;
      $actual_tries = $database->response;
      $left_tries = $max_tries - $actual_tries;
      if($left_tries < 1){//the user has reached his maximum attempts Put him in quarantine with a brand new generated md5 password to validate via url in mail
      //first get user e-mail
      $database->DB_get_mail($t his->pre_user);//stores mail into a variable of database class
      if($account_man ager->credentials_re factor($this->pre_user, $database->mail, $this->secured) == true){ //create a new password for the account
      /**
      * $account_manage r will create a new password, and will insert the user_name user_ip and user_new_pass into table quarantine
      * and will send the user a url with the password
      * when quarantine.php recives the right password, it calls again account manager to
      * delete the user from quarantine table and asks him for a new password
      * when POST new password is true, it calls again account manager to update the data into users table
      */
      $this->errors['general']['auth'] = "You reached the maximum wrong password submitting attempts, an e-mail has been sent to your box with a link and all the instructions to follow up.";//store error, auth will send this to client_side
      return false;
      }
      else{
      $this->errors['internal']['account_manage r'] = "Problem while creating new credentials for account, ".$account_mana ger->error;
      return false;
      }
      }
      else{
      $this->errors['sub_pass']['auth'] = "You entered a wrong password, ".$left_tri es." tries left.";// make a system where
      return false;
      }
      }
      else{
      $this->errors['internal']['mysql'] = $database->error['req']['mysql'];
      return false;
      }
      }
      else{//the user is already in quarantine and has submited wrong credentials, take his ip and bann him
      $this->errors['general']['auth'] = "You were put in quarantine at last login attempt, please check your mail box, an e-mail should have been sent.";
      return false;
      }
      }
      else{
      $this->errors['internal']['mysql'] = $database->error['req']['mysql'];
      return false;
      }
      }
      }
      else{//if character errors
      return false;
      }
      }
      }
      ?>
      [/PHP]

      then, here is the lowest page auth.php, which receives all data and transmits it to session_auth :

      [PHP]<?php
      include_once("i ncludings/inc.php");

      /**
      * User wants to login: submitted SUPERGLOBALS
      */
      if(isset($_POST['user_name']) || isset($_POST['user_pass'])){

      if($session->logged_in != true){
      /*Store values*/
      $posted_u_n = substr(trim(htm lentities($_POS T['user_name'])), 0, 20);
      $posted_u_n = preg_replace('/[^\w\.\-\& ]/', '', $posted_u_n);
      $posted_u_p = substr(trim(htm lentities($_POS T['user_pass'])), 0, 20);
      $posted_u_p = preg_replace('/[^\w\.\-\&]/', '', $posted_u_p);

      /*Check login succeed*/
      if ($session_auth->login($posted_ u_n, $posted_u_p) == true){
      //redirect to logged in section
      header("Locatio n: calendar.php");
      }
      else{//login failed or the user logged in but is still in quarantine
      $client_side->HTML_login_for m($session->user_name, $session_auth->errors);
      }
      }
      else{
      $error['logout']['can'] = 'log yourself out';
      $client_side->HTML_login_for m($session->user_name, $error);//can logout
      }
      }
      /**
      * User wants to logout: submited SUBERGLOBALS
      */
      else if($_GET['logout'] == 'true'){
      /*Check if logged in*/
      if($session->logged_in == true){
      /*Log him out*/
      if($session->unset_session( ) == true){
      //logout succeed
      $error['logout'] = 'logged out';
      $client_side->HTML_login_for m("Guest", $error);//message: you have logout + login form
      }
      else{
      //unable to log you out
      $error['logout'] = 'could not logout';
      $client_side->HTML_login_for m($session->user_name, $error); //message: unable to logout
      }
      }
      else{
      if($pre_session->pre_logged_i n == true){ // the user was logged in from another ip, and wants to logout and relogin from this ip. Already gave good credentials
      /* Set all the records on whose is said: active = 1 to 0 */
      /* Now when the user, that had logged in from the other ip checks if he is active, he wond find a record with IP active = 1 */
      if($database->DB_set_unactiv e_user($pre_ses sion->pre_user_nam e, "all") == true){
      /* Start a normal session which gives him his normal powers */
      if($session->starter($pre_s ession->pre_user_nam e, $pre_session->pre_user_level ) == true){
      if($session->logged_in == true){//------------------AT THIS POINT SESSION IS STARTED OK
      header("Locatio n: page.php");//---------------------HERE IS THE PROBLEM

      }
      else{
      print "not logged in";
      }
      }
      else{
      //unable to log you out
      $error['login'] = 'could not login';
      $client_side->HTML_login_for m($session->user_name, $error);
      }
      }
      else{
      //unable to log you out
      $error['logout'] = 'could not logout';
      $client_side->HTML_login_for m($session->user_name, $error); //message: unable to logout
      }
      }
      else{
      //you are not logged in
      $error['logout']['can'] = 'not logged in';
      $client_side->HTML_login_for m("Guest", $error); //message: not logged in cant logout...
      }
      }
      }
      /**
      * User can login: requested Blank page
      */
      else{//user requests this page from elsewhere than a form

      //show the first login fosrm
      if($session->logged_in == false){
      $error['first'] = '1';
      $client_side->HTML_login_for m('Guest',$erro r);//can login_form + register_link
      }
      else{
      $error['logout']['can'] = 'log yourself out';
      $client_side->HTML_login_for m($session->user_name, $error);//can logout
      }

      }
      ?>[/PHP]

      when the parser goes to where i wrote ----------HERE IS THE PROBLEM (above), the session is started ok, but when it redirects to the script: page.php, it calls $session->logged_in and it returns false, the user is no longer logged in
      here is the code of page.php:

      [PHP]
      class page_class
      {

      private $data_array = array();
      private $formatted_arra y = array();
      public $error = false;

      public function __construct(){
      global $session, $client_side, $database;


      /* Check Session - Only make calendar actions if user logged in */
      if($session->logged_in == true){
      print "you are logged in";
      }
      }
      [/PHP]

      all these files are correctly included in inc.php which is itself included in auth.php

      from the client side, it looks as if the script regenerated a new PHPSESSID when going to the other script and that should be the reason why $session->logged_in returns false...
      but i don't know where i tell PHP to create a new session id at each time a new page is sent...
      with firefox i can see that the request header sends PHPSESSID: XXX and the response header returns another PHPSESSID: YYY
      i cant understand why the session is lost.

      from the server side, i can see in /temp that all the sessions are still there and that they were not removed by session.max_lif time

      do you see a reason why php would generate a new session id at each time?

      Firstly i thought that this might be because of the session_regener ate_id() when i start the session, but this is done only once... when $session->starter() is called. but when $session::__con struct calls $session->check_session( ) to determine whether logged_in is true or not it never regenerates_id.

      Please if you have any suggestion let me know

      Thankyou very much for your time

      bilibytes

      Comment

      • urfriend202
        New Member
        • Nov 2008
        • 9

        #4
        Hi,
        Even I am having similar problem.

        In login page i had set session variables. But after page is redirected throgh header() to another page, sessions doesnt work any more.
        isset($_SESSION['username']) is returning false.

        Please help me.

        Thankyou.

        Comment

        • urfriend202
          New Member
          • Nov 2008
          • 9

          #5
          This is the first website I am developing on my machine. Do I have make any changes to php.ini file?

          Comment

          • Markus
            Recognized Expert Expert
            • Jun 2007
            • 6092

            #6
            Originally posted by urfriend202
            This is the first website I am developing on my machine. Do I have make any changes to php.ini file?
            Don't post your question multiple times. Start your own thread for your own questions.

            Moderator.

            Comment

            Working...