nodeJS – 如何使用express创build和读取会话
我想在用户input应用程序时创build一个用户sessison。 并在需要时阅读会议。 这是我的尝试
var io = require('socket.io'), express = require('express'); querystring = require('querystring'); var app = express.createServer(); app.get('/', function(req, res){ var sessionVal = querystring.parse(req.url.substr(2));// sessionVal is an email for example: me@gmail.com app.use(express.cookieParser()); app.use(express.session({ secret: sessionVal })); }); var socket = io.listen(app); socket.on('connection', function(client) { client.on('message', function(message) { // message will be an object {text:'user text chat blah blah', email:'me@gmail.com'} // if the seesion stored, has the same value with message.email // then the message will be broadcasted socket.broadcast(message.text); // else will not broadcast }); }); app.listen(4000);
我需要在这里指出,你错误地将中间件添加到应用程序。 app.use
调用不应该在app.get
请求处理程序中完成,而是在其之外。 只需在createServer
之后直接调用它们,或者查看文档中的其他示例 。
你传递给express.session
的秘密应该是一个string常量,或者是从configuration文件中取得的东西。 不要喂它客户可能知道的东西,这实际上是危险的。 这只是服务器应该知道的一个秘密。
如果您想在会话中存储电子邮件地址,只需按照以下方式进行操作:
req.session.email = req.param('email');
随着那个…
如果我理解正确,你要做的是处理一个或多个HTTP请求并跟踪一个会话,然后再打开一个你需要会话数据的Socket.IO连接。
关于这个问题有些棘手的地方在于,Socket.IO在任何http.Server
上的魔法工作都是通过劫持request
事件来实现的。 因此,Express(或者说Connect的)会话中间件永远不会在Socket.IO连接上被调用。
我相信你可以做这个工作,但有一些欺骗。
你可以到Connect的会话数据; 你只需要获得对会话存储的引用。 最简单的方法是在调用express.session
之前自己创build商店:
// A MemoryStore is the default, but you probably want something // more robust for production use. var store = new express.session.MemoryStore; app.use(express.session({ secret: 'whatever', store: store }));
每个会话存储都有一个get(sid, callback)
方法。 sid
参数或会话ID存储在客户端的cookie中。 该cookie的默认名称是connect.sid
。 (但你可以通过在你的express.session
调用中指定一个key
选项给它任何名字。)
然后,您需要访问Socket.IO连接上的cookie。 不幸的是,Socket.IO似乎没有给你访问http.ServerRequest
。 一个简单的解决方法是在浏览器中获取cookie,并通过Socket.IO连接发送。
服务器上的代码将如下所示:
var io = require('socket.io'), express = require('express'); var app = express.createServer(), socket = io.listen(app), store = new express.session.MemoryStore; app.use(express.cookieParser()); app.use(express.session({ secret: 'something', store: store })); app.get('/', function(req, res) { var old = req.session.email; req.session.email = req.param('email'); res.header('Content-Type', 'text/plain'); res.send("Email was '" + old + "', now is '" + req.session.email + "'."); }); socket.on('connection', function(client) { // We declare that the first message contains the SID. // This is where we handle the first message. client.once('message', function(sid) { store.get(sid, function(err, session) { if (err || !session) { // Do some error handling, bail. return; } // Any messages following are your chat messages. client.on('message', function(message) { if (message.email === session.email) { socket.broadcast(message.text); } }); }); }); }); app.listen(4000);
这假设你只想读取一个现有的会话。 你实际上不能创build或者删除会话,因为Socket.IO连接可能没有HTTP响应来发送Set-Cookie
头(认为是WebSockets)。
如果您想编辑会话,可能会在某些会话存储中使用。 一个CookieStore不会工作,因为它也需要发送一个Set-Cookie
头,它不能。 但对于其他商店,你可以尝试调用set(sid, data, callback)
方法,看看会发生什么。
我忘了告诉一个错误,当我使用我使用req.session.email = req.param('电子邮件'),服务器错误说不能设置未定义的属性电子邮件。
这个错误的原因是app.use的错误顺序。 您必须按以下顺序configurationExpress:
app.use(express.cookieParser()); app.use(express.session({ secret: sessionVal })); app.use(app.route);
互操作socket.io和连接会话支持是很麻烦的。 问题不是因为socket.io“劫持”请求,而是因为某些socket.io传输(我认为flashsockets)不支持cookies。 我可能是错误的cookies,但我的做法是以下几点:
- 为socket.io实现一个单独的会话存储,它以与connect-redis相同的格式存储数据
- 使连接会话cookie不仅仅是http,所以它可以从客户端JS访问
- 在socket.io连接之后,通过socket.io将会话cookie从浏览器发送到服务器
- 将会话标识存储在一个socket.io连接中,并使用它来访问来自redis的会话数据。
我做的步骤:
- 在HTML中包含angular-cookies.js文件!
-
在服务器端应用程序中将Cookie初始化为非http-only:
var cookieSettings = {path:'/',httpOnly:false,maxAge:null}; app.configure(function(){//一堆东西app.use(express.cookieSession({secret:'mySecret',store:store,cookie:cookieSettings}));
-
然后在客户端的services.jss我把['ngCookies']在这样的:
angular.module('swrp',['ngCookies')).//等
-
然后在controller.js中,在我的函数UserLoginCtrl中,我有$ cookie在那里顶部$ scope,如下所示:
函数UserLoginCtrl($ scope,$ cookies,socket){
-
最后,为了得到控制器function中的cookie的价值,我做了:
var mySession = $ cookies ['connect.sess'];
现在,您可以将其从客户端发送回服务器。 真棒。 希望他们把这个放在Angular.js文档中。 我想通过直接读取angular-cookies.js的实际代码来解决这个问题。