我需要创建一个websocket,我可以从另一个域连接到它(websocket在10.0.4.18:8020上运行,客户端将从10.0.4.160:443建立连接。)
每个用户必须具有唯一的会话才能在身份验证发生后重复使用他/她的用户数据。
由于客户端"又称用户的浏览器"在一个不同的主机上,我很难将会话与在页面重新加载事件上创建它的客户端联系起来!
我想到了解决这个问题的解决方法
XMLHttpRequest()
函数创建会话,然后将sessionID返回给客户端localStorage
为了消除会话固定攻击,我将添加更多验证步骤,以确保使用客户端的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;
};