[SOLVED] session_set_save_handler not working

  • (2 Pages)
  • +
  • 1
  • 2

15 Replies - 2473 Views - Last Post: 16 July 2015 - 02:47 PM Rate Topic: -----

#1 huzi8t9   User is offline

  • D.I.C Regular
  • member icon

Reputation: 25
  • View blog
  • Posts: 369
  • Joined: 11-July 07

[SOLVED] session_set_save_handler not working

Posted 16 July 2015 - 09:58 AM

Solution
Take a look at line 23 where I am retrieving my session data. I told it to fetch the data but didn't assign it to a variable. Silly mistake - too busy looking for bigger problems and overlooked this one.

A massive thank you to ArtificialSoldier!

Original Post
Good afternoon.

I'm attempting to save my sessions in a MySQL database, using PDO. I've got the class down and set it all up through the session_set_save_handler. Once completed, I headed straight away to test it and I've hit a rather unusual result.

When I initiate each page, I run a little check:

if ( isset($_SESSION['HTTP_USER_AGENT']) ) {
    if ( $_SESSION['HTTP_USER_AGENT'] !== MD5($_SERVER['HTTP_USER_AGENT'] ) ) {
        session_regenerate_id(true);
        $_SESSION['HTTP_USER_AGENT'] = MD5($_SERVER['HTTP_USER_AGENT']);
    }
} else {
    $_SESSION['HTTP_USER_AGENT'] = MD5($_SERVER['HTTP_USER_AGENT']);
}



With my new class, this is saved in my database! Which, I thought was a good result. However, nothing more will save in the database and I don't understand why. It's a little frustrating.

Here's my class:

Class Session {
    private $db;
    private $type;
    
    public function __construct() {
        session_write_close();
        session_set_save_handler(
            Array($this, '_open'),
            Array($this, '_close'),
            Array($this, '_read'),
            Array($this, '_write'),
            Array($this, '_destroy'),
            Array($this, '_clean')
        );
    }
    
    public function _open($savePath, $session_id) {
        $this->db = new Database();
        return true;
    }
    
    public function _read($id) {
        $this->db->Prep("SELECT data FROM client_sessions WHERE id = :id")->Bind(":id", $id)->Execute(true);
        
        if ( count( $data ) ) {
            return $data[0]['data'];
        }
        
        return '';
    }
    
    public function _write($id, $data) {
        $rows = $this->db->Prep("SELECT * FROM client_sessions WHERE id = :id")->Bind(":id", $id)->Execute(true);
        if ( count($rows) ) {
            $this->db->Prep("UPDATE client_sessions SET data = :data, access = :access WHERE id = :id")->Bind(":data", $data)->Bind(":access", time())->Bind(":id", $id)->Execute();
        } else {
            $this->db->Prep("INSERT INTO client_sessions VALUES(:id, :access, :data);")
                ->Bind(":id", $id)->Bind(":access", time())->Bind(":data", $data)
                ->Execute();
        }
        
        return true;
    }
    
    public function _clean($max) {
        if ( headers_sent() ) {
            echo "<!--Session now secure.-->";
        }
        $age = time() - $max;
        $this->db->Prep("DELETE FROM client_sessions WHERE access < :age")->Bind(":age", $age)->Execute();
        
        return true;
    }
    
    public function _destroy($id) {
        if ( headers_sent() ) {
            echo "<!--Session now secure.-->";
        }
        $this->db->Prep("DELETE FROM client_sessions WHERE id = :id")->Bind(":id", $id)->Execute();
        
        return true;
    }
    
    public function _close() {
        $this->db->close();
        
        return true;
    }
}



Initially, I went straight to my FTP to check for an error log, but there was nothing. Then, I went to phpMyAdmin to check see what had saved, and there was just this:

Quote

HTTP_USER_AGENT|s:32:"8599d48e36625b92bf3f0b46a0ffbbd1";


When I use $_SESSION['key'] = 'value'; it's not stored in the database and thus, I can't retrieve said value.

Am I doing something wrong or would it be worth saving in a flat file?

Any guidance appreciated!

Thanks

~huzi

EDIT

Here's a link to the webpage: http://carlton-fete....es.photography/ - you'll notice it asks for a password, this is 000 - once you put it in, it redirects to /?authorised=1. I put this in so, if you refresh, it doesn't ask for confirmation, but also, it works to prove that the password was right, it just won't save the session data.

EDIT 2
I've noticed that, if I set the session, I can use it further down my code. However, when the screen refreshes, it's gone. Essentially, it's working as a variable and not actually saving. See session info

This post has been edited by huzi8t9: 16 July 2015 - 03:13 PM


Is This A Good Question/Topic? 0
  • +

Replies To: [SOLVED] session_set_save_handler not working

#2 ArtificialSoldier   User is offline

  • D.I.C Lover
  • member icon

Reputation: 2163
  • View blog
  • Posts: 6,563
  • Joined: 15-January 14

Re: [SOLVED] session_set_save_handler not working

Posted 16 July 2015 - 10:13 AM

You'll probably need to show the code where you create and use the session. For example, the fact that you call session_write_close in your constructor makes me wonder what you're doing.
Was This Post Helpful? 0
  • +
  • -

#3 huzi8t9   User is offline

  • D.I.C Regular
  • member icon

Reputation: 25
  • View blog
  • Posts: 369
  • Joined: 11-July 07

Re: [SOLVED] session_set_save_handler not working

Posted 16 July 2015 - 10:18 AM

I read that someone had trouble with their class and that if session_start was already called, this line would eliminate that error.

However, here's how I'm calling it:
new Session();
if ( !headers_sent() && !session_id() ) {
    $some_name = session_name("some_name");
    session_set_cookie_params(0, '/', '.markhughes.photography');
    session_start();
}



View PostArtificialSoldier, on 16 July 2015 - 06:13 PM, said:

You'll probably need to show the code where you create and use the session. For example, the fact that you call session_write_close in your constructor makes me wonder what you're doing.

Was This Post Helpful? 0
  • +
  • -

#4 ArtificialSoldier   User is offline

  • D.I.C Lover
  • member icon

Reputation: 2163
  • View blog
  • Posts: 6,563
  • Joined: 15-January 14

Re: [SOLVED] session_set_save_handler not working

Posted 16 July 2015 - 10:54 AM

Quote

I read that someone had trouble with their class and that if session_start was already called, this line would eliminate that error.

Well, the session_write_close function will save all session data and then end the session.

Personally, I would move the other function calls into the constructor, if all of this is your code then just don't call session_start before using your class, assume that your class is the only way to start and control the session. e.g.:

    public function __construct($name = null, $lifetime = null, $path = null, $domain = null) {
        session_set_save_handler(
            Array($this, '_open'),
            Array($this, '_close'),
            Array($this, '_read'),
            Array($this, '_write'),
            Array($this, '_destroy'),
            Array($this, '_clean')
        );

        if ($name != null) {
            session_name($name);
        }

        if ($lifetime != null || $path != null || $domain != null) {
            $params = session_get_cookie_params();
            session_set_cookie_params(
              $lifetime == null ? $params['lifetime'] : $lifetime,
              $path == null ? $params['path'] : $path,
              $domain == null ? $params['domain'] : $domain
            );
        }

        session_start();
    }


Then you can just do this:

new Session('some_name', 0, '/', '.markhughes.photography');


For your other question, check the manual for session_regenerate_id:

http://php.net/manua...generate-id.php

You're telling it to delete the session data when regenerating the ID.
Was This Post Helpful? 0
  • +
  • -

#5 huzi8t9   User is offline

  • D.I.C Regular
  • member icon

Reputation: 25
  • View blog
  • Posts: 369
  • Joined: 11-July 07

Re: [SOLVED] session_set_save_handler not working

Posted 16 July 2015 - 11:05 AM

Thanks, ArtificialSoldier, for the cleaner constructor; I've implemented that and also removed the session_regenerate_id(true) from my code. I've also ensure that the session_write_close has been removed.

Unfortunately, still not having any joy.

Thanks for your replies.

~huzi
Was This Post Helpful? 0
  • +
  • -

#6 ArtificialSoldier   User is offline

  • D.I.C Lover
  • member icon

Reputation: 2163
  • View blog
  • Posts: 6,563
  • Joined: 15-January 14

Re: [SOLVED] session_set_save_handler not working

Posted 16 July 2015 - 11:18 AM

What are you doing to test? What exactly is happening?
Was This Post Helpful? 0
  • +
  • -

#7 huzi8t9   User is offline

  • D.I.C Regular
  • member icon

Reputation: 25
  • View blog
  • Posts: 369
  • Joined: 11-July 07

Re: [SOLVED] session_set_save_handler not working

Posted 16 July 2015 - 11:24 AM

View PostArtificialSoldier, on 16 July 2015 - 07:18 PM, said:

What are you doing to test? What exactly is happening?


As you can see in my original post, I'm testing here. When you enter the correct password (000), it sets the session variable to say you're "logged in," basically. One successful login, you'll be redirected to /?authorised=1. However, it's not saving that session variable, it's only saving the user agent.

Thank you for your continued support

~huzi

Edit

I put in the ?showinfo=1 so it prints the session variable - simply for debugging.

Edit
Added screenshots.

Attached Image

Attached Image

This post has been edited by huzi8t9: 16 July 2015 - 11:28 AM

Was This Post Helpful? 0
  • +
  • -

#8 ArtificialSoldier   User is offline

  • D.I.C Lover
  • member icon

Reputation: 2163
  • View blog
  • Posts: 6,563
  • Joined: 15-January 14

Re: [SOLVED] session_set_save_handler not working

Posted 16 July 2015 - 11:38 AM

What code runs on login after the code you've already showed? I'm trying to figure out what is supposed to happen versus what is actually happening, along with the code you're using for it.
Was This Post Helpful? 0
  • +
  • -

#9 huzi8t9   User is offline

  • D.I.C Regular
  • member icon

Reputation: 25
  • View blog
  • Posts: 369
  • Joined: 11-July 07

Re: [SOLVED] session_set_save_handler not working

Posted 16 July 2015 - 11:44 AM

View PostArtificialSoldier, on 16 July 2015 - 07:38 PM, said:

What code runs on login after the code you've already showed? I'm trying to figure out what is supposed to happen versus what is actually happening, along with the code you're using for it.


OK, the sub-domains are wildcard and are passed to an index.php which deciphers and checks to see if it exists, etcetera. Once it's been found, it does checks to see if it requires a password and such, if so, include the login page, if not, include the main album view page. Here's the login script:

            if ( isset($_POST['ga_password']) ) {
                if ( $_POST['ga_password'] === $cat['cat_password'] ) {
                    $authorised = true;
                    $_SESSION[MD5($cat['cat_name'].$cat['cat_password'])] = "1";
                    if ( isset($_POST['nojs']) ) {
                        $_SESSION['nojs'] = "1";
                    }
                    header("Location: /?authorised=1&showinfo=1");
                } else {
                    $authorisation_error = true;
                }
            }



And here's the code as a whole:

if ( isset($_GET['view']) && isset($_GET['album']) ) {
    $who = isset($_GET['album']) && !empty($_GET['album']) ? $_GET['album'] : false;
    if ( !$who ) {
        header("Location: http://clients.markhughes.photography/");
    }
    
    $db = new Database();
    $cat = $db->Prep("SELECT * FROM img_cats WHERE cat_subd = :cname")->Bind(":cname", $who)->Execute(true);
    if ( count($cat) ) {
        $cat = $cat[0];
        if ( $cat['cat_password'] == '' ) {
            $requires_auth = false;
            if ( isset($_GET['token']) ) {
                header("Location: http://".urlencode($cat['cat_subd']).".clients.markhughes.photography/");
            }
        } else {
            $requires_auth = true;
            
            if ( isset($_POST['ga_password']) ) {
                if ( $_POST['ga_password'] === $cat['cat_password'] ) {
                    $authorised = true;
                    $_SESSION[MD5($cat['cat_name'].$cat['cat_password'])] = "1";
                    echo "<!--Set session: ".MD5($cat['cat_name'].$cat['cat_password'])." = 1-->";
                    if ( isset($_POST['nojs']) ) {
                        $_SESSION['nojs'] = "1";
                        echo "<!--Set session: nojs = 1-->";
                    }
                    header("Location: /?authorised=1&showinfo=1");
                } else {
                    $authorisation_error = true;
                }
            }
            
            if ( isset($_GET['token']) && !empty($_POST['token']) ) {
                $token_set = true;
                $tkns = $db->Prep("SELECT * FROM client_access_tokens WHERE tkn_uses > 0 AND tkn_album = :aid AND tkn_data = :token")->Bind(":aid", $cat['cat_id'])->Bind(":token", $_GET['token'])->Execute(true);
            }
            
            $tokens_available = (count($tkns) ? true : false);
             
            if ( count($tokens) ) {
                $authorised = true;
                $db->Prep("UPDATE client_access_tokens SET tkn_uses = tkn_uses - 1 WHERE tkn_id = :tkn")->Bind(":tkn", $tkns[0]['tkn_id'])->Execute();
                $_SESSION[MD5($cat['cat_name'].$cat['catpassword'])] = "1";
                header("Location: /?authorised=1");
            } else {
                $authorised = false;
            }
            
            if ( isset($_SESSION[MD5($cat['cat_name'].$cat['cat_password'])]) ) {
                $authorised = true;
            }
        }
        
        include "catview.php";
    } else {
        include "catnotfound.php";
    }
    
    exit;
}



Thanks

~huzi
Was This Post Helpful? 0
  • +
  • -

#10 huzi8t9   User is offline

  • D.I.C Regular
  • member icon

Reputation: 25
  • View blog
  • Posts: 369
  • Joined: 11-July 07

Re: [SOLVED] session_set_save_handler not working

Posted 16 July 2015 - 01:22 PM

Update
OK, I've gone through, line-by-line debugging to try and get to the bottom of this error, and here's what I've discovered.

Like I said, I was line-by-line debugging by using $_SESSION['Line_'.__LINE__] = 'Saved'; and this proved invaluable to getting me this far.

<?php
include_once "classes/class.database.php";
include_once "SessionHandler.php";
include_once "header.inc.php";
$_SESSION['Line_'.__LINE__] = 'Saved';
$root = "http://clients.markhughes.photography/";
$_SESSION['Line_'.__LINE__] = 'Saved';
if ( isset($_POST['reuse']) ) {
    $_SESSION['Line_'.__LINE__] = 'Saved';
    $username = isset($_POST['username']) && !empty($_POST['username']) ? $_POST['username'] : false;
    $password = isset($_POST['password']) && !empty($_POST['password']) ? $_POST['password'] : false;
    $_SESSION['Line_'.__LINE__] = 'Saved';



Line 5 & 7 save, however, 9 and 12 do not. When I submit the form with duff credentials, it say's they're in my session - when I reload, they're gone (I've checked the database; line 5 & 7 are in there too).

So what is it that $_POST is doing to stop my sessions from working?

Hopefully, someone will have an answer!

Thanks in advanced

~huzi

This post has been edited by huzi8t9: 16 July 2015 - 01:23 PM

Was This Post Helpful? 0
  • +
  • -

#11 ArtificialSoldier   User is offline

  • D.I.C Lover
  • member icon

Reputation: 2163
  • View blog
  • Posts: 6,563
  • Joined: 15-January 14

Re: [SOLVED] session_set_save_handler not working

Posted 16 July 2015 - 02:17 PM

Quote

So what is it that $_POST is doing to stop my sessions from working?

Don't think like that, $_POST doesn't "do" anything at all, it's a data structure, and it doesn't affect $_SESSION. If you're asking those kinds of questions you're not going to find the answer you're looking for.

Since you've got all of the subdomains, the first thing to do is make sure that session cookies are working correctly. Use your browser's developer tools to check each request during this process, particularly the cookies. Make sure that the server is telling the browser to set a particular cookie (you should see the session name and ID), and that the browser sends the same cookie back on subsequent requests. Importantly, make sure that the session ID is not changing (that probably means that the browser did not send a session cookie and the server started a new empty session). The server will send a set-cookie header to tell the browser to set a cookie, and the browser sends back cookie headers. Most developer tools will have a tab that lists the cookies for each request.

Also, instead of sending location headers to redirect, you might want to use a redirect function which will first write and close the session, then send the redirect header, then exit, e.g.:

function redirect($url) {
  session_write_close();
  header('Location: ' . $url);
  exit;
}


If you can verify that session data is being written on one page but is not available on the next page then maybe the session isn't being closed correctly.
Was This Post Helpful? 0
  • +
  • -

#12 huzi8t9   User is offline

  • D.I.C Regular
  • member icon

Reputation: 25
  • View blog
  • Posts: 369
  • Joined: 11-July 07

Re: [SOLVED] session_set_save_handler not working

Posted 16 July 2015 - 02:30 PM

I can confirm that on different sub-domains, I keep the same session id.

I've written a redirect function:

function redirect($location) {
    session_write_close();
    if ( headers_sent() ) {
        echo "<script>top.location='{$location}';</script>";
    } else {
        header("Location: {$location}");
    }
    exit;
}



Still no joy. It's starting to hurt now - I think I should give up the ghost and stick to flat files!

Thanks again

~huzi
Was This Post Helpful? 0
  • +
  • -

#13 ArtificialSoldier   User is offline

  • D.I.C Lover
  • member icon

Reputation: 2163
  • View blog
  • Posts: 6,563
  • Joined: 15-January 14

Re: [SOLVED] session_set_save_handler not working

Posted 16 July 2015 - 02:34 PM

Actually have you tested that? If you remove the database handlers, does the problem go away? That would be another clue. Comment out the call to session_set_save_handler in the constructor and see if the behavior changes.
Was This Post Helpful? 0
  • +
  • -

#14 huzi8t9   User is offline

  • D.I.C Regular
  • member icon

Reputation: 25
  • View blog
  • Posts: 369
  • Joined: 11-July 07

Re: [SOLVED] session_set_save_handler not working

Posted 16 July 2015 - 02:36 PM

View PostArtificialSoldier, on 16 July 2015 - 10:34 PM, said:

Actually have you tested that? If you remove the database handlers, does the problem go away? That would be another clue. Comment out the call to session_set_save_handler in the constructor and see if the behavior changes.



Everything is golden without database interaction; does that mean it can only be my class?

Thanks

~huzi
Was This Post Helpful? 0
  • +
  • -

#15 ArtificialSoldier   User is offline

  • D.I.C Lover
  • member icon

Reputation: 2163
  • View blog
  • Posts: 6,563
  • Joined: 15-January 14

Re: [SOLVED] session_set_save_handler not working

Posted 16 July 2015 - 02:42 PM

Yeah, I would focus on the session class. I'll go back and find some code I wrote to do that years ago to compare with yours. In the meantime, you might want to set up the code to use an error log, and then add some error_log statements to record what's going on. You can do the settings like this (anywhere in the code):

error_reporting(E_ALL);
ini_set('log_errors', 1);
ini_set('error_log', __DIR__ . DIRECTORY_SEPARATOR . 'error.log');


Then you can use the error_log function to write whatever you want to that file. You could add a line in each method to make sure they're all getting called, e.g.:

    public function _write($id, $data) {

        error_log(__FILE__ . __LINE__ . ' session write, ID=' . $id . ', data=' . $data);

        $rows = $this->db->Prep("SELECT * FROM client_sessions WHERE id = :id")->Bind(":id", $id)->Execute(true);

        error_log(__FILE__ . __LINE__ . ' session record: ' . print_r($rows, true));

        if ( count($rows) ) {
            $this->db->Prep("UPDATE client_sessions SET data = :data, access = :access WHERE id = :id")->Bind(":data", $data)->Bind(":access", time())->Bind(":id", $id)->Execute();
        } else {
            $this->db->Prep("INSERT INTO client_sessions VALUES(:id, :access, :data);")
                ->Bind(":id", $id)->Bind(":access", time())->Bind(":data", $data)
                ->Execute();
        }
        
        return true;
    }

Was This Post Helpful? 1
  • +
  • -

  • (2 Pages)
  • +
  • 1
  • 2