Socket.io и сеанс?
Я использую express framework. Я хочу получить данные сеанса из socket.io. Я попробовал выразить dynamicHelpers с данными client.listener.server.dynamicViewHelpers, но я не могу получить данные сеанса. Есть ли простой способ сделать это? См. Код
app.listen(3000);
var io = require('socket.io');
var io = io.listen(app);
io.on('connection', function(client){
// I want to use session data here
client.on('message', function(message){
// or here
});
client.on('disconnect', function(){
// or here
});
});
Ответы
Ответ 1
Это не сработает для сокетов, проходящих по транспорту flashsocket (он не отправляет серверу необходимые файлы cookie), но он надежно работает на все остальное. Я просто отключил перенос flashsocket в моем коде.
Чтобы он работал, на стороне express/connect я явно определяю хранилище сеансов, поэтому я могу использовать его внутри сокета:
MemoryStore = require('connect/middleware/session/memory'),
var session_store = new MemoryStore();
app.configure(function () {
app.use(express.session({ store: session_store }));
});
Затем внутри моего кода сокета я включаю фреймворк connect, поэтому я могу использовать его разбор cookie для извлечения файла connect.sid из файлов cookie. Затем я просматриваю сеанс в хранилище сеансов, у которого есть этот файл connect.sid:
var connect = require('connect');
io.on('connection', function(socket_client) {
var cookie_string = socket_client.request.headers.cookie;
var parsed_cookies = connect.utils.parseCookie(cookie_string);
var connect_sid = parsed_cookies['connect.sid'];
if (connect_sid) {
session_store.get(connect_sid, function (error, session) {
//HOORAY NOW YOU'VE GOT THE SESSION OBJECT!!!!
});
}
});
Затем вы можете использовать сеанс по мере необходимости.
Ответ 2
Решение Socket.IO-session предоставляет приложение для атак XSS, выставляя идентификатор сеанса на уровне клиента (скриптинга).
Проверьте это решение (для Socket.IO >= v0.7). См. Docs здесь.
Ответ 3
Я предлагаю не полностью изобретать колесо. Необходимые инструменты уже являются пакетом npm. Я думаю, что это то, что вам нужно: session.socket.io
Я использую его в эти дни, и это будет очень полезно, я думаю!! Связывание экспресс-сессии с слоем socket.io будет иметь так много преимуществ!
Ответ 4
Изменить:. Попробовав некоторые модули, которые не сработали, я действительно ушел и написал свою собственную библиотеку, чтобы сделать это. Бесстыдный плагин: перейдите в https://github.com/aviddiviner/Socket.IO-sessions. Я оставлю свой старый пост ниже в исторических целях:
Я получил эту работу довольно аккуратно, не обойдя транспорт флэш-памяти в соответствии с вышеприведенным решением pr0zac. Я также использую экспресс с Socket.IO. Вот как.
Сначала передайте идентификатор сеанса в представление:
app.get('/', function(req,res){
res.render('index.ejs', {
locals: {
connect_sid: req.sessionID
// ...
}
});
});
Затем в вашем представлении свяжите его с клиентской стороной Socket.IO:
<script>
var sid = '<%= connect_sid %>';
var socket = new io.Socket();
socket.connect();
</script>
<input type="button" value="Ping" onclick="socket.send({sid:sid, msg:'ping'});"/>
Затем в своем слушателе Socket.IO на стороне сервера заберите его и прочитайте/запишите данные сеанса:
var socket = io.listen(app);
socket.on('connection', function(client){
client.on('message', function(message){
session_store.get(message.sid, function(error, session){
session.pings = session.pings + 1 || 1;
client.send("You have made " + session.pings + " pings.");
session_store.set(message.sid, session); // Save the session
});
});
});
В моем случае my session_store
- это Redis, используя библиотеку redis-connect
.
var RedisStore = require('connect-redis');
var session_store = new RedisStore;
// ...
app.use(express.session({ store: session_store }));
Надеюсь, что это поможет кому-то, кто находит этот пост при поиске в Google (как и я;)
Ответ 5
Смотрите это: Аутентификация Socket.IO
Я бы предложил ничего не получать через client.request...
или client.listener...
, поскольку он напрямую не привязан к объекту client
и всегда указывает на последнего зарегистрированного пользователя!
Ответ 6
Проверьте Socket.IO-connect
Подключить WebSocket Middleware Wrapper вокруг Socket.IO- node
https://github.com/bnoguchi/Socket.IO-connect
Это позволит вам проталкивать запросы Socket.IO вниз по стеку промежуточного программного обеспечения Express/Connect, прежде чем обрабатывать его с помощью обработчиков событий Socket.IO, предоставляя вам доступ к сеансу, куки и многое другое. Хотя, я не уверен, что он работает со всеми транспортными средствами Socket.IO.
Ответ 7
Вы можете посмотреть на это: https://github.com/bmeck/session-web-sockets
или, альтернативно, вы можете использовать:
io.on('connection', function(client) {
var session = client.listener.server.viewHelpers;
// use session here
});
Надеюсь, что это поможет.
Ответ 8
Я не уверен, что делаю все правильно.
https://github.com/LearnBoost/socket.io/wiki/Authorizing
С помощью данных рукопожатия вы можете получить доступ к файлам cookie. И в файлах cookie вы можете захватить connect.sid, который является идентификатором сеанса для каждого клиента. И затем используйте connect.sid для получения данных сеанса из базы данных (я предполагаю, что вы используете RedisStore)
Ответ 9
Вы можете использовать express-socket.io-session.
Поделитесь промежуточным программным обеспечением экспресс-сессии на основе файлов cookie с socket.io. Работает с express > 4.0.0 и socket.io > 1.0.0 и не будет обратно совместимым.
Работал для меня!
Ответ 10
Этот код содержит промежуточное программное обеспечение сокетов, которое соединяется с Express. req.session
сеанса также и отправьте переменную req.session
обратно клиенту. В этом случае клиенту нужен слушатель, socket.on('auth', function(session) { })
чтобы получить последнюю информацию!
var express = require('express'),
app = express()
var expressSession = require('express-session'),
sessionMiddleware = {}
sessionMiddleware = expressSession({
genid: req => {
return (require('uuid/v4'))()
},
store: new redisStore(),
secret: '*******************************',
name: process.env.NODE_ENV ? 'live_session' : 'dev_session',
resave: false,
saveUninitialized: false,
proxy: true,
logErrors: true,
unset: 'keep',
rolling: false,
cookie: {
domain: process.env.NODE_ENV ? '.indospace.io' : '.indo.io',
secure: process.env.NODE_ENV ? true : false,
httpOnly: true,
expires: new Date(Date.now() + 3600000),
maxAge: 3600000,
sameSite: true
}
})
app.use(sessionMiddleware)
var http = require('http')
http.globalAgent.maxSockets = Infinity
app.server = http.Server(app)
// parseInt(app.nconf.get('app:port')) + (process.env.NODE_APP_INSTANCE ? parseInt(process.env.NODE_APP_INSTANCE) : 0)
app.server.listen(app.nconf.get('app:port'), '0.0.0.0', ret => {
app.sio = require('socket.io').listen(app.server, {
transports: ['websocket']
})
/*app.sio.adapter(require('socket.io-redis')({
host: 'localhost',
port: 6379
}))*/
app.sio.use((socket, next) => {
var socket_subdomain = socket.handshake.headers.host.split('.')[0]
console.log('socket subdomain: ' + socket_subdomain)
sessionMiddleware(socket.handshake, {}, err => {
socket.on('auth', sock => {
socket.handshake.session.reload(err => {
console.log(Object.keys(socket.handshake.session))
console.log('*'.repeat(100))
app.sio.sockets.in('room_' + socket.handshake.session.id).emit('auth', socket.handshake.session)
})
})
})
sessionMiddleware(socket.request, {}, next)
})
app.sio.sockets.on('connection', socket => {
socket.join('room_' + socket.request.session.id)
app.sio.sockets.in('room_' + socket.request.session.id).emit('auth', socket.request.session)
})
app.sio.sockets.on('disconnect', ret => {
console.log(app.colors.red('[socket disconnected]'))
// drop session ID from Redis somehow???
})
})