1

別のドメインから接続できる Websocket を作成する必要があります (Websocket は 10.0.4.18:8020 で実行され、クライアントは 10.0.4.160:443 から接続を確立します)。

認証後にユーザー データを再利用するには、各ユーザーに固有のセッションが必要です。

クライアント「別名ユーザーのブラウザー」は別のホスト上にあるため、ページのリロードイベントでセッションを作成するクライアントとセッションを結び付けるのに苦労しています!

この問題を解決するためにこの回避策を考えました

  1. クライアントからの関数を使用してセッションを作成し、セッションXMLHttpRequest()ID をクライアントに返します
  2. を使用してユーザーのブラウザーに sessionId を保存します。localStorage
  3. ユーザーが WebSocket に接続するたびに、sessionId を socket.io に渡します。
  4. 次に、Websocket は sessionId を受け取り、それをリロードして、もう一度使用できるようにします。

セッション固定攻撃を排除するために、さらにいくつかの検証手順を追加して、クライアントの 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;
};
4

0 に答える 0