在节点js不可见php会话(redis)

我使用Redis服务器来共享Php和Node js之间的会话。 对于Node js客户端使用“connect-redis”,而对于php客户端,使用redis-session-php和Predis。 我从这里获取了大部分的代码(来自正确答案)的堆栈升级版本。

app.js

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); 

app.php

 <?php // this must match the express-session `secret` in your Express app define('EXPRESS_SECRET', 'node.js rules'); // ==== BEGIN express-session COMPATIBILITY ==== // 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"); } // ==== END express-session COMPATIBILITY ==== 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>"; ?> 

问题是:首先执行“php文件”,然后执行“节点js服务器页面” – “节点js服务器页面”没有看到从“php文件”创build会话。 当反之亦然(首先执行“节点js服务器页面”,然后执行“php文件”)会话variables已经在这两个页面中看到

结果app.php

 []{ "php": "Hello from PHP", "cookie": [] } 

结果节点js页面( http://127.0.0.1:8080 )

 { "cookie": { "originalMaxAge": null, "expires": null, "httpOnly": true, "path": "/" }, "nodejs": "Hello from node.js!" } 

您可能正面临跨域问题。 如果您在不同的地址或端口上运行PHP和Node(而且可能是PHP),那么HTML将不会在到另一个域的请求之间共享Cookie,而是将分隔的副本保留到每个域中。

如果您正在使用子域名(例如,您的PHP位于像app1.mydomain.com这样的URL和运行在app2.mydomain.com中的NodeJS中),那么您可以共享configuration它们的Cookie,以便使用主域名Cookiepath设置/读取(mydomain.com)。

在这里有关于这个主题的好信息:

使用Express和Node,如何在子域/主机头之间维护会话 。

如果您需要更多信息,或者您的问题不完全一样,请告诉我们。

我从这篇文章解决了这个问题: 使用Redis的PHP和Node.JS会话共享

app.js

 var app = require("http").createServer(handler), fs = require("fs"), redis = require("redis"), co = require("./cookie.js"); app.listen(443); //On client incomming, we send back index.html function handler(req, res) { //Using php session to retrieve important data from user var cookieManager = new co.cookie(req.headers.cookie); //Note : to specify host and port : new redis.createClient(HOST, PORT, options) //For default version, you don't need to specify host and port, it will use default one var clientSession = new redis.createClient(); console.log('cookieManager.get("PHPSESSID") = ' + cookieManager.get("PHPSESSID")); clientSession.get("sessions/" + cookieManager.get("PHPSESSID"), function(error, result) { console.log("error : " + result); if(error) { console.log("error : " + error); } if(result != null) { console.log("result exist"); console.log(result.toString()); } else { console.log("session does not exist"); } }); //clientSession.set("sessions/" + cookieManager.get("PHPSESSID"), '{"selfId":"salamlar22", "nodejs":"salamlar33"}'); } 

cookie.js

 //Directly send cookie to system, if it's node.js handler, send : //request.headers.cookie //If it's socket.io cookie, send : //client.request.headers.cookie module.exports.cookie = function(co){ this.cookies = {}; co && co.split(';').forEach(function(cookie){ var parts = cookie.split('='); this.cookies[parts[0].trim()] = (parts[1] || '').trim(); }.bind(this)); //Retrieve all cookies available this.list = function(){ return this.cookies; }; //Retrieve a key/value pair this.get = function(key){ if(this.cookies[key]){ return this.cookies[key]; }else{ return {}; } }; //Retrieve a list of key/value pair this.getList = function(map){ var cookieRet = {}; for(var i=0; i<map.length; i++){ if(this.cookies[map[i]]){ cookieRet[map[i]] = this.cookies[map[i]]; } } return cookieRet; }; }; 

app.php

 <?php include 'redis.php'; session_start(); echo '<pre>'; var_dump($_COOKIE); echo '</pre>'; echo '$_SESSION["nodejs"] = '.$_SESSION[selfId].'<br>'; $_SESSION[selfId] = 2; echo '$_SESSION["nodejs"] = '.$_SESSION[selfId].'<br>'; ?> 

redis.php

 <?php //First we load the Predis autoloader //echo dirname(__FILE__)."/predis-1.0/src/Autoloader.php"; require(dirname(__FILE__)."/redis-session-php/modules/predis/src/Autoloader.php"); //Registering Predis system Predis\Autoloader::register(); /** * redisSessionHandler class * @class redisSessionHandler * @file redisSessionHandler.class.php * @brief This class is used to store session data with redis, it store in json the session to be used more easily in Node.JS * @version 0.1 * @date 2012-04-11 * @author deisss * @licence LGPLv3 * * This class is used to store session data with redis, it store in json the session to be used more easily in Node.JS */ class redisSessionHandler{ private $host = "127.0.0.1"; private $port = 6379; private $lifetime = 0; private $redis = null; /** * Constructor */ public function __construct(){ $this->redis = new Predis\Client(array( "scheme" => "tcp", "host" => $this->host, "port" => $this->port )); session_set_save_handler( array(&$this, "open"), array(&$this, "close"), array(&$this, "read"), array(&$this, "write"), array(&$this, "destroy"), array(&$this, "gc") ); } /** * Destructor */ public function __destruct(){ session_write_close(); $this->redis->disconnect(); } /** * Open the session handler, set the lifetime ot session.gc_maxlifetime * @return boolean True if everything succeed */ public function open(){ $this->lifetime = ini_get('session.gc_maxlifetime'); return true; } /** * Read the id * @param string $id The SESSID to search for * @return string The session saved previously */ public function read($id){ $tmp = $_SESSION; $_SESSION = json_decode($this->redis->get("sessions/{$id}"), true); if(isset($_SESSION) && !empty($_SESSION) && $_SESSION != null){ $new_data = session_encode(); $_SESSION = $tmp; return $new_data; }else{ return ""; } } /** * Write the session data, convert to json before storing * @param string $id The SESSID to save * @param string $data The data to store, already serialized by PHP * @return boolean True if redis was able to write the session data */ public function write($id, $data){ $tmp = $_SESSION; session_decode($data); $new_data = $_SESSION; $_SESSION = $tmp; $this->redis->set("sessions/{$id}", json_encode($new_data)); $this->redis->expire("sessions/{$id}", $this->lifetime); return true; } /** * Delete object in session * @param string $id The SESSID to delete * @return boolean True if redis was able delete session data */ public function destroy($id){ return $this->redis->delete("sessions/{$id}"); } /** * Close gc * @return boolean Always true */ public function gc(){ return true; } /** * Close session * @return boolean Always true */ public function close(){ return true; } } new redisSessionHandler(); ?>