-
-
Save mscdex/9507b0d8df42e0aec825 to your computer and use it in GitHub Desktop.
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')) | |
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', | |
resave: false, | |
saveUninitialized: false | |
})); | |
app.use(function(req, res, next) { | |
req.session.nodejs = 'Hello from node.js!'; | |
res.send('<pre>' + JSON.stringify(req.session, null, ' ') + '</pre>'); | |
}); | |
app.listen(8080); |
<?php | |
// this must match the express-session `secret` in your Express app | |
define('EXPRESS_SECRET', 'node.js rules'); | |
// this id mutator function helps ensure we look up | |
// the session using the right id | |
define('REDIS_SESSION_ID_MUTATOR', 'express_mutator'); | |
function express_mutator($id) { | |
if (substr($id, 0, 2) === "s:") | |
$id = substr($id, 2); | |
$dot_pos = strpos($id, "."); | |
if ($dot_pos !== false) { | |
$hmac_in = substr($id, $dot_pos + 1); | |
$id = substr($id, 0, $dot_pos); | |
} | |
return $id; | |
} | |
// check for existing express-session cookie ... | |
$sess_name = session_name(); | |
if (isset($_COOKIE[$sess_name])) { | |
// here we have to manipulate the cookie data in order for | |
// the lookup in redis to work correctly | |
// since express-session forces signed cookies now, we have | |
// to deal with that here ... | |
if (substr($_COOKIE[$sess_name], 0, 2) === "s:") | |
$_COOKIE[$sess_name] = substr($_COOKIE[$sess_name], 2); | |
$dot_pos = strpos($_COOKIE[$sess_name], "."); | |
if ($dot_pos !== false) { | |
$hmac_in = substr($_COOKIE[$sess_name], $dot_pos + 1); | |
$_COOKIE[$sess_name] = substr($_COOKIE[$sess_name], 0, $dot_pos); | |
// https://github.com/tj/node-cookie-signature/blob/0aa4ec2fffa29753efe7661ef9fe7f8e5f0f4843/index.js#L20-L23 | |
$hmac_calc = str_replace("=", "", base64_encode(hash_hmac('sha256', $_COOKIE[$sess_name], EXPRESS_SECRET, true))); | |
if ($hmac_calc !== $hmac_in) { | |
// the cookie data has been tampered with, you can decide | |
// how you want to handle this. for this example we will | |
// just ignore the cookie and generate a new session ... | |
unset($_COOKIE[$sess_name]); | |
} | |
} | |
} else { | |
// let PHP generate us a new id | |
session_regenerate_id(); | |
$sess_id = session_id(); | |
$hmac = str_replace("=", "", base64_encode(hash_hmac('sha256', $sess_id, EXPRESS_SECRET, true))); | |
// format it according to the express-session signed cookie format | |
session_id("s:$sess_id.$hmac"); | |
} | |
require('redis-session-php/redis-session.php'); | |
RedisSession::start(); | |
$_SESSION["php"] = "Hello from PHP"; | |
if (!isset($_SESSION["cookie"])) | |
$_SESSION["cookie"] = array(); | |
echo "<pre>"; | |
echo json_encode($_COOKIE, JSON_PRETTY_PRINT); | |
echo json_encode($_SESSION, JSON_PRETTY_PRINT); | |
echo "</pre>"; | |
?> |
谢谢,现在我知道怎么弄了
Beautiful! Thank you.
hello brian , i have a problem when i try to set session id to be compatible with express session format i got this error in php :Warning: session_start() [function.session-start]: The session id is too long or contains illegal characters, valid characters are a-z, A-Z, 0-9 and '-,' it's understandable because the session id we set contains : and . and other caracters that are not alphanumeric, second question is how can i get the phpsessid from redis in node ,
i will really appreciate it if u help me ,thanks in advance
I have different problem. When first execute "php file" then execute "node js server page" - "node js server page" have not seen session creation from "php file". When vice versa (first execute "node js server page" then execute "php file") session variables have seen in both page
Just as @ramin-git mentioned, I also experienced the issue of express-session not accepting cookie by PHP but other way works.
The issue happens when a new session start, the calls for session_regenerate_id();
(line 45) to (re)generate a new ID for the new session (and cookie). But the next call for session_id()
returns empty since both these functions should be called after session_start()
.
Fix:
if you are 100% sure that regenerate_id() will not work before session_start() (I'm not completely sure :P), then just replace line 45 and 46 with the following, that way executing regenerate and asking for a session id is avoided. This method should work definitely but I have to do further testing.
$sessHandlerInst=new SessionHandler();
$sess_id=$sessHandlerInst->create_sid();
or append the following instead, between line 46 and line 47 (after $sess_id = session_id();
, before $hmac = str_replace....
- this will generate a new ID if $sess_id
turns out empty (which will be*).
if(!$sess_id){
$sessHandlerInst=new SessionHandler();
$sess_id=$sessHandlerInst->create_sid();
}
Explanation :
Since the expectation for calling
session_regenerate_id();
$sess_id = session_id();
is to generate a new ID which the script modify to match express-session format, calling SessionHandler::create_sid()
can be used. Yes the session_regenerate()
internally calls create_sid() but will only work if the session has been started (which is not* otherwise setting session ID is not possible).
what is the best approach for using this with multiple domains?
Example of the domains that need to be aware of the session:
- domain.com
- sub1.domain.com
- bla.domain.com
I have tried adding the domain
to the cookie (prefixed with and without a dot) but no success yet.
Same problem is in this thread: https://github.com/expressjs/session/issues/633
Hi Brian, thanks for sharing this with us 😄 I want to see this code in action, I'll be grateful if you could help me run this code and see for myself :)