express下使用socket.io来传输用户间的即时消息,如何验证却是个问题,想了一下可以在传输数据中添加一个用于验证的加密字段,不过好像这样有点麻烦,另外一种在io.set('authorization',function{..})中通过handshakeData.headers.cookie获取express下的session来验证,不过socket.io 1.x已经不再使用这种方式,结果绕了很多弯路才找到正确方式,现在使用socket.request.headers.cookie,下面是用法,以此记下
导航目录
-
导入相应模块
使用express框架模块,并引入cookie解析和session存储模块:var express = require('express'),// 导入express框架模块 //cookieParser = require('cookie-parser'),//没有使用express可以使用分离的cookie-parser模块进行解析 parseCookie = express.cookieParser("secret"),//"secret"改为你的加密签名 //建立一个memory store的实例 storeMemory = new express.session.MemoryStore();
-
express使用session配置:
//中间件 app.use(express.bodyParser()); app.use(express.cookieParser()); //解析cookie //使用secret设置签名来加密,使用key自定义cookie键,store设置存储方式为内存存储方式 app.use(express.session({secret:'secret',key:'connect_sid',store:storeMemory}));
-
socket.io获取session验证
socket.io 0.9.x版本中使用io.set('authorization',function{..}):var io = sio.listen(app); //设置session io.set('authorization', function(handshakeData, callback){ // 解析客户端的cookie字符串 handshakeData.cookie = parseCookie(handshakeData.headers.cookie) var connect_sid = handshakeData.cookie['connect_sid']; //connect_sid即我们之前自定义的cookie键字段 if (connect_sid) { //通过cookie中保存的session的id获取到服务器端对应的session storeMemory.get(connect_sid, function(error, session){ if (error) { // if we cannot grab a session, turn down the connection callback(error.message, false); } else { // save the session data and accept the connection handshakeData.session = session; callback(null, true); } }); } else { callback('nosession'); } });
使用io.use(function (socket,next){..})代替io.set('authorization',function{..}),socket.request.headers.cookie代替handshakeData.headers.cookie:io = sio.listen(app); //设置socket的session验证 io.use(function (socket,next) { //parseCookie会解析socket.request.headers.cookie并赋值给执行socket.request.cookies parseCookie(socket.request, null, function(err) { if (err) { console.log("err parse"); return next(new Error("cookie err")); } // cookie中获取sessionId var connect_sid = socket.request.cookies['connect_sid']; if (connect_sid) { //通过cookie中保存的session的id获取到服务器端对应的session storeMemory.get(connect_sid, function(error, session){ if (error) { return next(new Error('Authentication error')); } else { // save the session data and accept the connection socket.request.session = session; next(); } }); } }); });
现在可以在socket.request.session中看到我们的session数据了:io.sockets.on('connection', function (socket){ var session = socket.handshake.session;//session var name = session.name; var password = session.password; console.log(name+' '+password); });
11.29更新
express 4.x可以直接把express-session中间件当成socket.io处理,所以可以简单像下面这样,就可以共享express的session了
sio.use(function(socket, next) { sessionMiddleware(socket.request, socket.request.res, next); });
example:
var Server = require("http").Server; var session = require("express-session"); var app = express(); var server = Server(app); var sio = require("socket.io")(server); var sessionMiddleware = session({ secret: "keyboard cat", resave: false, saveUninitialized: true }); sio.use(function(socket, next) { sessionMiddleware(socket.request, socket.request.res, next); }); app.use(sessionMiddleware); app.get("/", function(req, res){ req.session.username = 'jim'; }); sio.sockets.on("connection", function(socket) { console.log(socket.request.session.username); // 'jim' }); server.listen(80);
-
区别session和cookie
看了这么多,也对session和cookie的概念有些深入了解了。session保存在服务器,而cookie保存在浏览器上,当你浏览网页时,服务器会请求浏览器通过设置cookie来保存一些数据,cookie的内容主要包括:名字,值,过期时间,路径和域,其中如果过期时间不设置就表示浏览器关闭即删除该cookie。
而服务器程序创建session时,会检查浏览器cookie中是否保存有session id的字段,此字段映射到服务器一个对应的session存储区,服务器通过session id找到对应的session来保存数据,而当浏览器中没有session id的时候,服务器端会创建一个新的session并生成一个session id保存在浏览器cookie中。
所以session解决了cookie的一些不安全问题,但是同时session保存在服务器上会占用一些服务器性能,因此一些私密数据应当使用session保存,而其他信息保存为cookie。
另外还有一个之前有些困惑的地方现在也明白些了:express中使用cookieParser对session id进行签名加密,而parseCookie对应就是对cookie进行解签。附上一段cookie-parser模块中处理cookie的代码:
exports.signedCookies = function(obj, secret){ var cookies = Object.keys(obj); var dec; var key; var ret = Object.create(null); var val; for (var i = 0; i < cookies.length; i++) { key = cookies[i]; val = obj[key]; dec = exports.signedCookie(val, secret); if (val !== dec) { ret[key] = dec; delete obj[key]; } } return ret; }; exports.signedCookie = function(str, secret){ return str.substr(0, 2) === 's:' ? signature.unsign(str.slice(2), secret) : str; };
Demo下载:Session-Demo.zip