express+socket.io 共享session
express下socket.io使用session驗證用戶
express下使用socket.io來傳輸用戶間的即時消息,如何驗證卻是個問題,想了一下可以在傳輸數據中添加一個用于驗證的加密字段,不過好像這樣有點麻煩,另外一種在io.set('authorization',function{..})中通過handshakeData.headers.cookie獲取express下的session來驗證,不過socket.io 1.x已經不再使用這種方式,結果繞了很多彎路才找到正確方式,現在使用socket.request.headers.cookie,下面是用法,以此記下
導航目錄
導入相應模塊
使用express框架模塊,并引入cookie解析和session存儲模塊:
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);//設置sessionio.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獲取到服務器端對應的sessionstoreMemory.get(connect_sid, function(error, session){if (error) {// if we cannot grab a session, turn down the connectioncallback(error.message, false);}else {// save the session data and accept the connectionhandshakeData.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.cookiesparseCookie(socket.request, null, function(err) {if (err) {console.log("err parse");return next(new Error("cookie err"));}// cookie中獲取sessionIdvar connect_sid = socket.request.cookies['connect_sid'];if (connect_sid) {//通過cookie中保存的session的id獲取到服務器端對應的sessionstoreMemory.get(connect_sid, function(error, session){if (error) {return next(new Error('Authentication error'));}else {// save the session data and accept the connectionsocket.request.session = session;next();}});}});});現在可以在socket.request.session中看到我們的session數據了:
io.sockets.on('connection', function (socket){var session = socket.handshake.session;//sessionvar 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
總結
以上是生活随笔為你收集整理的express+socket.io 共享session的全部內容,希望文章能夠幫你解決所遇到的問題。