2

Is there an recent guide (or example code) to using node, express, and redis/predis to share PHPSESSID?

I've found several tutorials 1-2 years old and they are all either using old versions express or not using express.

Express cookie parser is also deprecated.

https://simplapi.wordpress.com/2012/04/13/php-and-node-js-session-share-redi/

NodeJS + ExpressJS + RedisStore Session is undefined

It would be great if someone could post some more recent code...

EDIT - extract of node server code so far:

var express = require('express'),
app = express(),
server = require('http').createServer(app),
io = require('socket.io').listen(server),
redis   = require('redis'),
client  = redis.createClient();    

var session = require('express-session'),
RedisStore = require('connect-redis')(session);

app.get('/', function(req, res) {
    res.sendfile('/');
});

app.use(
    session({
            name: 'PHPSESSID'
    store: new RedisStore({
        prefix: 'PHPSESSID',
        port: 6379
    })
})
);

io.sockets.on('connection', function (socket) {

    app.use(function(req, res, next) {
        console.log(req.session);
    });

    .......

Packages:

├─┬ connect@2.17.1
│ ├── basic-auth-connect@1.0.0
│ ├─┬ body-parser@1.2.0
│ │ └─┬ raw-body@1.1.4
│ │   └── bytes@0.3.0
│ ├── bytes@1.0.0
│ ├─┬ compression@1.0.2
│ │ ├── bytes@0.3.0
│ │ ├── compressible@1.0.1
│ │ └── negotiator@0.4.3
│ ├── connect-timeout@1.1.0
│ ├── cookie@0.1.2
│ ├── cookie-parser@1.1.0
│ ├── cookie-signature@1.0.3
│ ├─┬ csurf@1.2.0
│ │ ├── scmp@0.0.3
│ │ └── uid2@0.0.3
│ ├── debug@0.8.1
│ ├── errorhandler@1.0.1
│ ├─┬ express-session@1.2.0
│ │ ├── buffer-crc32@0.2.1
│ │ ├── uid2@0.0.3
│ │ └── utils-merge@1.0.0
│ ├── fresh@0.2.2
│ ├─┬ method-override@1.0.1
│ │ └── methods@1.0.0
│ ├── morgan@1.1.1
│ ├─┬ multiparty@2.2.0
│ │ ├─┬ readable-stream@1.1.13-1
│ │ │ ├── core-util-is@1.0.1
│ │ │ ├── inherits@2.0.1
│ │ │ ├── isarray@0.0.1
│ │ │ └── string_decoder@0.10.25-1
│ │ └── stream-counter@0.2.0
│ ├── on-headers@0.0.0
│ ├── parseurl@1.0.1
│ ├── pause@0.0.1
│ ├── qs@0.6.6
│ ├── response-time@1.0.0
│ ├── serve-favicon@2.0.0
│ ├─┬ serve-index@1.0.3
│ │ ├── batch@0.5.0
│ │ └── negotiator@0.4.3
│ ├─┬ serve-static@1.1.0
│ │ └─┬ send@0.3.0
│ │   ├── buffer-crc32@0.2.1
│ │   ├── debug@0.8.0
│ │   ├── mime@1.2.11
│ │   └── range-parser@1.0.0
│ ├─┬ type-is@1.2.0
│ │ └── mime@1.2.11
│ └── vhost@1.0.0
├─┬ connect-redis@2.0.0
│ └── debug@0.8.1
├─┬ express@4.1.1
│ ├─┬ accepts@1.0.1
│ │ ├── mime@1.2.11
│ │ └── negotiator@0.4.3
│ ├── buffer-crc32@0.2.1
│ ├── cookie@0.1.2
│ ├── cookie-signature@1.0.3
│ ├── debug@0.8.1
│ ├── escape-html@1.0.1
│ ├── fresh@0.2.2
│ ├── merge-descriptors@0.0.2
│ ├── methods@0.1.0
│ ├── parseurl@1.0.1
│ ├── path-to-regexp@0.1.2
│ ├── qs@0.6.6
│ ├── range-parser@1.0.0
│ ├─┬ send@0.3.0
│ │ ├── debug@0.8.0
│ │ └── mime@1.2.11
│ ├── serve-static@1.1.0
│ ├─┬ type-is@1.1.0
│ │ └── mime@1.2.11
│ └── utils-merge@1.0.0
├─┬ express-session@1.2.0
│ ├── buffer-crc32@0.2.1
│ ├── cookie@0.1.2
│ ├── cookie-signature@1.0.3
│ ├── debug@0.8.1
│ ├── on-headers@0.0.0
│ ├── uid2@0.0.3
│ └── utils-merge@1.0.0
├─┬ mysql@2.2.0
│ ├── bignumber.js@1.3.0
│ ├─┬ readable-stream@1.1.13-1
│ │ ├── core-util-is@1.0.1
│ │ ├── inherits@2.0.1
│ │ ├── isarray@0.0.1
│ │ └── string_decoder@0.10.25-1
│ └── require-all@0.0.8
├── redis@0.10.2
└─┬ socket.io@0.9.16
  ├── base64id@0.1.0
  ├── policyfile@0.0.4
  ├── redis@0.7.3
  └─┬ socket.io-client@0.9.16
    ├─┬ active-x-obfuscator@0.0.1
    │ └── zeparser@0.0.5
    ├── uglify-js@1.2.5
    ├─┬ ws@0.4.31
    │ ├── commander@0.6.1
    │ ├── nan@0.3.2
    │ ├── options@0.0.5
    │ └── tinycolor@0.0.1
    └── xmlhttprequest@1.4.2
Community
  • 1
  • 1
Asa Carter
  • 2,207
  • 5
  • 32
  • 62

2 Answers2

5

For node (and Express 4.x):

Start with the example from express-session, but use connect-redis as your session store instead.

Example code:

var express = require('express'),
    app = express(),
    cookieParser = require('cookie-parser'),
    session = require('express-session'),
    RedisStore = require('connect-redis')(session);

app.use(express.static(__dirname + '/public'));
app.use(function(req, res, next) {
  if (req.url.indexOf('favicon') > -1)
    return res.send(404);
  next();
});
app.use(cookieParser());
app.use(session({
  store: new RedisStore({
    // this is the default prefix used by redis-session-php
    prefix: 'session:php:'
  }),
  // use the default PHP session cookie name
  name: 'PHPSESSID',
  secret: 'node.js rules'
}));
app.use(function(req, res, next) {
  req.session.nodejs = 'Hello from node.js!';
  res.send(JSON.stringify(req.session, null, '  '));
});

app.listen(8080);

For PHP:

Use a redis session handler like redis-session-php.

Example code:

<?php

// from https://github.com/TheDeveloper/redis-session-php
require('redis-session-php/redis-session.php');
RedisSession::start();

$_SESSION["php"] = "Hello from PHP";

// `cookie` is needed by express-session to store information
// about the session cookie
if (!isset($_SESSION["cookie"]))
  $_SESSION["cookie"] = array();

var_dump($_SESSION);

?>

Note: Make sure you use the same prefix(connect-redis)/REDIS_SESSION_PREFIX(redis-session-php) (connect-redis uses 'sess:' and redis-session-php uses 'session:php:' by default) and ttl(connect-redis)/session.gc_maxlifetime(PHP) (and same database if you are using a redis database other than the default) for both redis-session-php and connect-redis.

mscdex
  • 104,356
  • 15
  • 192
  • 153
  • My php codebase is using `PHPSESSID` as the session key. So I've defined `REDIS_SESSION_PREFIX` as `PHPSESSID`. Is that correct? Also, I'm not sure how to how to access the session value in the node file. I'm adding my code to the original question above. – Asa Carter May 22 '14 at 02:20
  • No, the prefix is a redis-specific option. That is the prefix used for the keys. If you're using PHP's cookie name (PHPSESSID), then you need to set `name: 'PHPSESSID'` in your express-session options. – mscdex May 22 '14 at 03:11
  • I Still don't seem to be able to access the session. – Asa Carter May 22 '14 at 03:54
  • I guess I could install express 3 instead of 4 but that seems like a step backwards.. – Asa Carter May 22 '14 at 14:42
  • 1
    I've added example code that I've personally tested and have verified to be working. Just visit the PHP and node scripts in your browser and you should see the session data from both sides. – mscdex May 22 '14 at 17:12
  • where do I log the session (that was set in php) to the console to check that I can read it? – Asa Carter May 22 '14 at 21:42
  • `console.dir(req.session);` in any middleware/route after the session middleware – mscdex May 22 '14 at 22:38
  • I tried that but it was not logging anything. Ah, It only logs if I hit the browser with the :8080 port. http://***.dev:8080/messages/ This returns the cookie set by php: { "php": "e9msbo88gci5ne61t6s0fkve04", "cookie": { "expires": null, "httpOnly": true, "path": "/" }, "nodejs": "Hello from node.js!" } Why can't I access the cookie from the browser served by apache? I have server.listen(8080) in the server.js file. – Asa Carter May 23 '14 at 08:56
  • I removed all my other code and used only yours and it works. There are two issues however. There seems to be some issue using it with the facebook all.js file. I get the error on the client: `SyntaxError: missing ; before statement "php": "rbhdmbirbi9e7ghg5kilc52e66",` – Asa Carter May 23 '14 at 11:34
  • ..Ok so I changed `res.send(JSON.stringify(req.session, null, ' '));` to `res.send();`. It seems `res.send()` is required or it hangs the browser although I'm not sure why this is required? – Asa Carter May 23 '14 at 12:07
  • The other issue is getting it to work with the http server which is the reason I couldn't see the log for the sessions. Is it possible to have app and server both listening on 8080? – Asa Carter May 23 '14 at 12:25
  • Only if you use something like haproxy in front of both Apache and node and proxy the requests that way. – mscdex May 23 '14 at 18:07
  • or can I use both together on different ports in the same app? I've tried using different ports. There is no error but either one or the other seems to be ignored why I log to console. – Asa Carter May 23 '14 at 21:24
  • Dammit, I cant get it working again at all now, I've created a stripped down version of the full code here https://db.tt/HBi1ljuZ – Asa Carter May 27 '14 at 12:30
  • This only seems to work if I include the `` and also use app.listen on port 8081. Otherwise I get nothing. Any idea's????????? – Asa Carter May 27 '14 at 20:38
  • `app.use(session({ store: new RedisStore({ // this is the default prefix used by redis-session-php prefix: 'session:php:' }), // use the default PHP session cookie name name: 'PHPSESSID', secret: 'node.js rules', resave: true, saveUninitialized: true }));` – Fábio Zangirolami Aug 08 '16 at 15:16
1

I just wanted to offer an alternate solution here that doesn't require redis and I've been using for a couple years (cross-posting from another answer):

This requires the following:

npm install cookie

npm install php-unserialize

This solution uses the session files on the machine - you shouldn't have to change this line.

session.save_handler = files

^ Should be like this in your php.ini file (default).

Here is the super simple code to retrieve the session data:

var cookie = require('cookie');
var fs = require('fs');
var phpUnserialize = require('php-unserialize');

//This should point to your php session directory.
//My php.ini says session.save_path = "${US_ROOTF}/tmp"
var SESS_PATH = "C:/SomeDirectory/WhereYourPHPIs/tmp/";

io.on('connection', function(socket) {
    //I just check if cookies are a string - may be better method
    if(typeof socket.handshake.headers.cookie === "string") {
        var sid = cookie.parse(socket.handshake.headers.cookie);
        if(typeof sid.PHPSESSID === "undefined") {
          console.log("Undefined PHPSESSID");
        }
        else {
            console.log("PHP Session ID: " + sid.PHPSESSID);
            fs.readFile(SESS_PATH + "sess_" + sid.PHPSESSID, 'utf-8', function(err,data) {
                if(!err) {
                    console.log("Session Data:");
                    var sd = phpUnserialize.unserializeSession(data);
                    console.log(sd);
                }
                else {
                   console.log(err);
                }
            });
        }
    }
}

Results:

Results

Authenticate user for socket.io/nodejs

user1274820
  • 7,786
  • 3
  • 37
  • 74