如何在node.js中使用express-session加载特定会话?

时间:2015-10-06 00:02:36

标签: javascript node.js session express express-session

我需要创建一个websocket,我可以从另一个域连接到它(websocket在10.0.4.18:8020上运行,客户端将从10.0.4.160:443建立连接。)

每个用户必须具有唯一的会话才能在身份验证发生后重复使用他/她的用户数据。

由于客户端"又称用户的浏览器"在一个不同的主机上,我很难将会话与在页面重新加载事件上创建它的客户端联系起来!

我想到了解决这个问题的解决方法

  1. 使用客户端的XMLHttpRequest()函数创建会话,然后将sessionID返回给客户端
  2. 使用localStorage
  3. 将sessionId保存在用户的浏览器中
  4. 每次用户连接到websocket时,都将sessionId传递给socket.io。
  5. 然后Websocket接受sessionId并重新加载它以使其再次可用。
  6. 为了消除会话固定攻击,我将添加更多验证步骤,以确保使用客户端的IP和代理数据不会劫持sessionId。

    此外,我需要触发setInterval()方法,该方法将每秒进行外部API调用并更新会话变量。

    问题

    如何正确地重新加载会话数据,我可以自动保存变量,而无需直接使用store.get()加载会话数据并保存它们?

    以下是我的工作

    我使用文件系统创建了会话。在每个请求中,我必须使用store.get()方法加载会话存储,更新会话数据,然后保存它。但我遇到的问题是每次我想要更新会话,因为你可以看到我的下面的代码。

    这就是我所做的!

    var app = require('express')(),
        https = require('https'),
        fs = require('fs'),
        session = require('express-session'),
        fileStore = require('session-file-store')(session),
        base64url = require('base64url'),
        bodyParser = require("body-parser");
        cookieParser = require("cookie-parser"),
        env = require('./modules/config');
    
    var server = https.createServer(
        {
            key: fs.readFileSync('certs/key.pem'),
            cert: fs.readFileSync('certs/cert.pem')
        }, app).listen(env.socket.port, env.socket.host, function () {
        console.log('\033[2J');
        console.log('Websocket is running at https://%s:%s', server.address().address, server.address().port);
    });
    
    var io = require('socket.io')(server);
    
    var icwsReq = require('./modules/icws/request.js'),
        icwsConn = require('./modules/icws/connection.js'),
        icwsInter = require('./modules/icws/interactions.js'),
        sessionValidator = require('./modules/validator.js');
    
    var icwsRequest = new icwsReq();
    var sessionChecker = new sessionValidator();
    
    var sessionStoreFile = new fileStore({path: './tmp/sessions'});
    
    var sessionOptions = {
            store: sessionStoreFile,
            secret: env.session.secret,
            saveUninitialized: true,
            resave: false,
            cookie: {
                path: '/',
                httpOnly: true,
                maxAge: 60 * 60 * 1000,
                secure: true
            }
        };
    
    app.use(session(sessionOptions)); // session support for the app
    
    app.use(bodyParser.urlencoded({ extended: false }));  //allows to pupulate req.body in the REST/PUT post requests!
    
    
    // Set access control headers on every express route.
    app.use(function (req, res, next){
        res.setHeader('x-powered-by', 'Express');
        res.setHeader('Access-Control-Allow-Origin', '*');
        res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type');
        res.setHeader('Access-Control-Allow-Methods', 'GET, POST');
        next();
    });
    
    
    //Middleware for authorizing a user before establishing a connection
    io.use(function(req, next) {
    
        var sessionID = req.handshake.query.token || '';
        var token = req.handshake.query.auth || '';
    
        var origin = req.handshake.headers.origin;
        var ip = req.request.socket.remoteAddress; 
        var userAgent =  req.handshake.headers['user-agent'];
    
        if(!sessionID || !token){
            console.log('No Session found with this token! ' + sessionID);
            return next(new Error('No Session found with this token!'));
        }
    
        sessionStoreFile.get(sessionID, function(err, session){
    
            // session updated
            if(err){
                console.log(err);
                return next(new Error(err));
            }
    
            if(!session){
                console.log('Session Could not be loaded');
                return next(new Error('Session Could not be loaded'));
            }
    
            if(    session.token != token
                || session.ip != ip
                || session.agent != userAgent
                || session.origin != origin
            ){
    
                session.token = null;
                session.ip = null;
                session.agent = null;
                session.origin = null;
    
                sessionStoreFile.set(sessionID, session);
    
                console.log('This session is invalid! Please sign in');
                return next(new Error('This session is invalid! Please sign in'));
            }
    
            next();
    
        });
    });
    
    io.on('connection', function (socket) {
    
        var sessionID = socket.handshake.query.token;
    
        //load the session with the ID sessionID
        sessionStoreFile.get(sessionID, function(err, session){
    
            //add the socket.id to the queue
            session.clients.push(socket.id);
    
            //Save the session data after adding the connection to the queue
            sessionStoreFile.set(sessionID, session, function(){
    
                //Get the current session data "including current socket.id"
                sessionStoreFile.get(sessionID, function(err, session){
    
                    //get an instance of icws connector
                    icwsRequest.setConnection(session.icwsHost, session.icwsPort);
    
                    var interactions = new icwsInter(icwsRequest);
    
                    //Call the API everysecond, update the session then save the session
                    setInterval(function(){
                        sessionStoreFile.get(sessionID, function(err, session){
                            //call the API and return the new data
                            session.queue = interactions.updateQueue();
                            //save the new data every second
                            sessionStoreFile.set(sessionID, session);
                        }
    
                    }, 1000);
    
                    //handle ICWS interactions
                    socket.on('interaction', function(data){
    
                        var  task = data.task || '',
                             phone = data.phone || '',
                             interactionId = data.interactionId || '',
                             queueName = data.queueName || '';
    
                        //Place a phone call
                        if(task == 'call'){
                            interactions.call(phone);
                        }
    
                        //External transfer
                        if(task == 'eBlindTransfer'){
                            interactions.blindTransferCallExternal(interactionId, phone);
                        }           
    
                        //Internal Transfer
                        if(task == 'iBlindTransfer'){
                            interactions.blindTransferCallInternal(interactionId, queueName);
                        }                   
    
                    });
    
                    //send a chat message to all browser's tabs associated with the currect session
                    socket.on('chat', function(msg){
    
                        var clients = session.clients;
    
                        console.log(clients);
    
                        for (var i in clients) {
    
                            var socketId = clients[i];
                            console.log('Client Said: ' + msg + ' socket Id: ' + socketId);
                            io.to(socketId).emit('chat', {message: 'Server Said: ' + msg});
                        }
    
                    });
    
                    //handle disconnect
                    socket.on('disconnect', function(msg){
    
                        var index = session.clients.indexOf(socket.id);
    
                        if(index > -1){
                            session.clients.splice(index, 1);
    
                            //save session after removing a client
                            sessionStoreFile.set(sessionID, session, function(error){
    
                                if(!error){
                                    console.log('Closing tabs: ' + socket.id);
                                    console.log(session);
                                }
                            });
                        }
                    });
    
                    //handle errors
                    socket.on('error', function(msg){
                        console.log('Error Message: ' + msg);
                    }); 
    
                });
    
            });
    
        });
    
    });
    
    
    app.get('/', function (req, res) {
        res.send('welcome: ' + req.sessionID);
    });
    
    
    app.get('/handshake/:token', function (req, res) {
    
        var origin = req.headers.origin;
        var ip =  req.connection.remoteAddress;
        var userAgent =  req.headers['user-agent'];
    
        if(!req.params || !req.params.token || !ip || !origin || !userAgent){
            console.log('Missing Request!');
            return false;
        }
    
        if(!originIsAllowed(origin)){
            console.log('This is a cross-domain attack!');
            return false;
        }
    
        req.session.token = req.params.token;
        req.session.ip = ip;
        req.session.origin = origin; 
        req.session.agent = userAgent;
        req.session.clients = [];
    
        req.session.save(function(err){
    
            if (err) {
                connectionError(res, session);
            } else {
                res.json({
                    token: req.sessionID
                });
            }
    
        });
    });
    
    
    
    function originIsAllowed(origin) {
        // put logic here to detect whether the specified origin is allowed.
            var allowed = env.session.allowedOrigins || []
    
            if(allowed.indexOf(origin) >= 0){
                return true;
            }
    
        return false;
    };
    

0 个答案:

没有答案