使用node.js和session.socket.io进行安全authentication?

我正在使用最新版本的node.js和session.socket.io ,这是我设置会话的方式(请注意,我没有使用HTTPS连接,所以secure: true ):

 app.configure(function() { app.use(cookieParser); app.use(express.session({ signed: true, store: sessionStore, secret: 'SECRET', cookie: { maxAge: 24 * 60 * 60 * 1000, httpOnly: true } })); }); var sessionSockets = new SessionSockets(io, sessionStore, cookieParser); // Later sessionSockets.on('connection', function(error, socket, session) { // session could be used here to detect if user is logged in // eg login: session.name = 'x'; session.save(); // eg checkIfLoggedIn: if (session.name) return true; }); 

我的代码是安全的还是正确的?或者我可以如何validation用户是否真正login? 是否有可能/build议更改客户端上的cookie的sid (因为这里提到)?

我build议避免重新发明车轮,并使用PassportJS等库。 这里有一个专门用于使用PassportJS和Socket.io的模块(我从来没有使用过这个,尽pipe我目前正在开发一个项目,我将很快需要它)。 我使用PassportJS,它非常简单。 我会推荐这个。

我知道这已经有点老了,但是对于将来的读者,除了parsingcookie的@kentcdodds以及从存储检索会话(例如,我自己的passport.socketio模块)所描述的方法之外,您还可以考虑基于令牌的方法。

在这个例子中,我使用了非常标准的JSON Web Tokens。 您必须向客户端页面提供令牌,在本例中,设想一个返回JWT的authentication端点:

 var jwt = require('jsonwebtoken'); // other requires app.post('/login', function (req, res) { // TODO: validate the actual user user var profile = { first_name: 'John', last_name: 'Doe', email: 'john@doe.com', id: 123 }; // we are sending the profile in the token var token = jwt.sign(profile, jwtSecret, { expiresInMinutes: 60*5 }); res.json({token: token}); }); 

现在,您的socket.io服务器可以configuration如下:

 var socketioJwt = require('socketio-jwt'); var sio = socketIo.listen(server); sio.set('authorization', socketioJwt.authorize({ secret: jwtSecret, handshake: true })); sio.sockets .on('connection', function (socket) { console.log(socket.handshake.decoded_token.email, 'has joined'); //socket.on('event'); }); 

socket.io-jwt中间件期望查询string中的令牌,所以从客户端连接时只需要附加它:

 var socket = io.connect('', { query: 'token=' + token }); 

我在这里写了一个关于这个方法和cookie的更详细的解释。

用户身份validation和会话存储使用Passport

 var express = require('express'), routes = require('./routes'), api = require('./routes/api'), http = require('http'), path = require('path'), mysql = require('mysql'), passport = require('passport'), LocalStrategy = require('passport-local').Strategy; //MySQL var sqlInfo = { host: 'localhost', user: 'root', password: '', database: 'dbname' } global.client = mysql.createConnection(sqlInfo); client.connect(); var app = module.exports = express(); /** * Configuration */ // all environments app.set('port', process.env.PORT || 3000); app.set('views', __dirname + '/views'); app.set('view engine', 'jade'); app.use(express.logger('dev')); app.use(express.bodyParser()); app.use(express.methodOverride()); app.use(express.static(path.join(__dirname, 'public'))); app.use(express.cookieParser("secret")); app.use(express.session({ secret: 'keyboard cat' })); app.use(passport.initialize()); app.use(passport.session()); app.use(app.router); passport.use(new LocalStrategy( function(username, password, done) { return check_auth_user(username,password,done); } )); // development only if (app.get('env') === 'development') { app.use(express.errorHandler()); } // production only if (app.get('env') === 'production') { // TODO } /** * routes start--------------------------------------------------------------- */ // home page contain login form app.get('/home', function(reg, res){ //check user session value, is logged in if(req.user) res.render('dash',{ username: req.user['member_id']//req.user array contains serializeUser data }); else res.render('index'); }); app.get('/logout', function(req, res){ req.logout(); res.redirect('/home'); }); //login form submit as post app.post('/login', passport.authenticate('local', { successRedirect: '/dashboard', failureRedirect: '/home' }) ); //to project dashboard app.get('/dash',routes.dash); //to project dashboard app.get('/signup',routes.signup); //to project dashboard app.get('*', routes.index); /** * routes end--------------------------------------------------------------------- */ /** * Start Server */ http.createServer(app).listen(app.get('port'), function () { console.log('Express server listening on port ' + app.get('port')); }); 

点击查看更多细节 !