How to create and read session with express
I want to create a user sessison when user enter the app. And read the session whenever needed. Here is my try
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);
I need to point out here that you're incorrectly adding middleware to the application. The app.use
calls should not be done within the app.get
request handler, but outside of it. Simply call them directly after createServer
, or take a look at the other examples in the docs.
The secret you pass to express.session
should be a string constant, or perhaps something taken from a configuration file. Don't feed it something the client might know, that's actually dangerous. It's a secret only the server should know about.
If you want to store the email address in the session, simply do something along the lines of:
req.session.email = req.param('email');
With that out of the way...
If I understand correctly, what you're trying to do is handle one or more HTTP requests and keep track of a session, then later on open a Socket.IO connection from which you need the session data as well.
What's tricky about this problem is that Socket.IO's means of making the magic work on any http.Server
is by hijacking the request
event. Thus, Express' (or rather Connect's) session middleware is never called on the Socket.IO connection.
I believe you can make this work, though, with some trickery.
You can get to Connect's session data; you simply need to get a reference to the session store. The easiest way to do that is to create the store yourself before calling express.session
:
// 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 }));
Every session store has a get(sid, callback)
method. The sid
parameter, or session ID, is stored in a cookie on the client. The default name of that cookie is connect.sid
. (But you can give it any name by specifying a key
option in your express.session
call.)
Then, you need to access that cookie on the Socket.IO connection. Unfortunately, Socket.IO doesn't seem to give you access to the http.ServerRequest
. A simple work around would be to fetch the cookie in the browser, and send it over the Socket.IO connection.
Code on the server would then look something like the following:
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);
This assumes you only want to read an existing session. You cannot actually create or delete sessions, because Socket.IO connections may not have a HTTP response to send the Set-Cookie
header in (think WebSockets).
If you want to edit sessions, that may work with some session stores. A CookieStore wouldn't work for example, because it also needs to send a Set-Cookie
header, which it can't. But for other stores, you could try calling the set(sid, data, callback)
method and see what happens.
I forgot to tell a bug when i use I use req.session.email = req.param('email'), the server error says cannot sett property email of undefined.
The reason of this error is a wrong order of app.use. You must configure express in this order:
app.use(express.cookieParser());
app.use(express.session({ secret: sessionVal }));
app.use(app.route);
It is cumbersome to interoperate socket.io and connect sessions support. The problem is not because socket.io "hijacks" request somehow, but because certain socket.io transports (I think flashsockets) don't support cookies. I could be wrong with cookies, but my approach is the following:
下一篇: 如何使用快递创建和阅读会话