10

I have recently gone into extending my site using node.js and have come to realisation I need a session handler for my PHP sessions. Now everything was cool and dandy and node.js reads the php sessions and can propogate it's own session with the php ones. I am using database sessions so the session data gets saved into a field in the database.

I have however found a slight problem. I am attempting to read the session data into node.js and it's really quite a strange string. I have been able to get the strucutre of each session variable down to:

'field_name'|'type':'length':'value';

Now on certain strings the value field can be missing on other strings the length can be missing (when a variable is Null). The type can also be more than b, s, i; it can also be N (NULL).

I had originally thought up of a huge translator for JS but this just somehow seems a very wrong way to do it.

Has anyone here tried to extract php session variables in JS before and is there any kind of script that could help? Maybe there is a formatting thing I can use on PHP side to make my life a lot easier in node.js?

Edit: the Schema looks like:

{ _id: { id: 'L:\u00c1\u009d\u008e\u00ad\u000e}<\u0002\u0000\u0000' }
, session_id: 'a2clfnjhopv1srs5k5elgbfjv5'
, user_id: 0
, session_data:     'logged|b:0;uid|i:0;server_key|N;AUTH_TIER2|b:0;email|s:0:"";cheese|s:6:"cheese";'
, active: 1
, expires: 1278920567
}

This is the mongo db record for a user session. The field needing to be translated is session_data. There is some kind of formatting error when pasting it in since stackoverflow wont format that as code when I try and make it for some reason.

I tried to JSONfy the field before but it lost it's types and didn't read Null entries etc so I stopped that

Thanks,

Yacoby
  • 54,544
  • 15
  • 116
  • 120
Sammaye
  • 43,242
  • 7
  • 104
  • 146
  • 1
    I haven't worked with node.js before. Would it be possible to [`json_encode`](http://uk2.php.net/manual/en/function.json-encode.php) the unserialized session data from PHP before passing it to node.js? – Gordon Jul 12 '10 at 08:11
  • can you show an example instead of the schema? how it looks when something is missing? – gblazex Jul 12 '10 at 08:37
  • I added the schema, though as I said there was some kind of error when pasting it and stackoverflow wont format the data to be code :(. galam, as I also state in the edit I did try JSON but it seemed to break the string making it impossible to retrieve session data :(. Maybe there is something in that though, if I make a node field and copy the session data in a json string to it...and make a dejsonifier for the field....hmmmm could work – Sammaye Jul 12 '10 at 09:10
  • fixed the code. For future reference, you need to separated the indented code from non-indented text by at least on blank line before it will be properly formatted. – Yacoby Jul 12 '10 at 09:21

4 Answers4

5

Here is a session_decode function based on the unserialize function of phpjs: https://github.com/vianneyb/phpjs/blob/master/functions/var/session_decode.js

works for me!

vianney
  • 380
  • 1
  • 4
  • 12
5

I'm relatively sure PHP uses the serialize and unserialize functions to handle session data.

There is a JavaScript implementation of unserialize in PHP.JS, you can find it here: http://phpjs.org/functions/unserialize

Jani Hartikainen
  • 42,745
  • 10
  • 68
  • 86
  • That is one sexy script Ima try it out. I saw they got serialize as well so I will try them out. Do I need php.js to use these scripts or just the dependancies they state? – Sammaye Jul 12 '10 at 09:22
  • I haven't used PHP.JS myself, but I think you can just pick the specific functions you want and their deps if any – Jani Hartikainen Jul 12 '10 at 10:55
  • @Jani I am not sure this is handled with serialize/unserialize but rather with session_encode/session_decode – Gordon Jul 12 '10 at 17:15
  • You may be right Gordon. Doesn't look like there is a JS implementation fo that yet - @Sammaye your best bet would probably be to see if you can get it functioning with unserialize, since the format is pretty similar but not exactly 1-to-1, and if you run into problems modify the function to behave more like session_decode (less work than coding from scratch) – Jani Hartikainen Jul 13 '10 at 03:35
  • Yea, it seems that if you add the 'fieldname'|'serialisedarray' like that it works 1to1 with JS. Need to do a little more testing before I can say it works and I need to store objects within a array so they can be ignored but not deleted by node.js but it does seem as though it could work :D – Sammaye Jul 13 '10 at 07:28
  • I just noticed I cna php in node.js...if it communicates directly to php I might be able to run a quick unserialize function – Sammaye Jul 13 '10 at 07:38
  • Yes this worked perfect I was able to make a node.js php session handler and it works like a beast thanks :) – Sammaye Jul 14 '10 at 10:32
3

Just to reply with the way I've found: force PHP to use JSON instead :

Use the class below, with session_set_save_handler to store data as JSON and let PHP still using his own system. Link this class using this function at the beginning of each script you use session : http://php.net/manual/ru/function.session-set-save-handler.php

PS : here the class use memcache to store JSON resulting object, on Node.JS, use a memcache object, and retrieve like this :

  • get the PHPSESSID from cookies
  • use that characters string to bring a key from memcached with "sessions/id" where id is the key and session just the string (see class below).

Now you should have only JSON in memcache, so it's becoming a simple game with Node.JS to work with.

PS : of course you can work with/improve this, you can also use this not only with memcache (a db for example)

<?php
/**
 * This class is used to store session data with memcache, it store in json the session to be used more easily in Node.JS
 */
class memcacheSessionHandler{
    private static $lifetime = 0;
    private static $memcache = null;

    public function __construct(){
            self::$memcache = new Memcache();
            self::$memcache->addServer('localhost', 11211);
}

    public function __destruct(){
            session_write_close();
            self::$memcache->close();
            self::$memcache = null;
    }

    public static function open(){
            self::$lifetime = ini_get('session.gc_maxlifetime');
            return true;
    }

    public static function read($id){
            $tmp = $_SESSION;
            $_SESSION = json_decode(self::$memcache->get("sessions/{$id}"), true);
            $new_data = session_encode();
            $_SESSION = $tmp;
            return $new_data;
    }

    public static function write($id, $data){
            $tmp = $_SESSION;
            session_decode($data);
            $new_data = $_SESSION;
            $_SESSION = $tmp;
            return self::$memcache->set("sessions/{$id}", json_encode($new_data), 0, self::$lifetime);
    }

    public static function destroy($id){
            return self::$memcache->delete("sessions/{$id}");
    }

    public static function gc(){
            return true;
    }

    public static function close(){
            return true;
    }
}
?>
kleopatra
  • 51,061
  • 28
  • 99
  • 211
Deisss
  • 31
  • 1
2

I had the same problem. I needed to integrate php with node.js. I used js-php-unserialize to do this. The use is pretty straightforward.

var PHPUnserialize = require('php-unserialize');
console.log(PHPUnserialize.unserializeSession(yourData));

For example if you

var yourData = 'A|s:1:"B";userID|s:24:"53d620475e746b37648b4567";';

you will get this result:

{
  A: 'B',
  userID: '53d620475e746b37648b4567'
}
Salvador Dali
  • 214,103
  • 147
  • 703
  • 753