#google-app-engine #session #socket.io #express-session
#google-app-engine #сеанс #socket.io #экспресс-сессия
Вопрос:
Я пытаюсь получить идентификатор сеанса пользователя из express-session, когда пользователь открывает соединение с WebSocket. Приведенный ниже код показывает, как это делается. Проблема в том, что когда я развертываю свой сервер в Google App Engine, я больше не вижу сеансовый файл cookie при авторизации подключения к сокету. Он отлично работает при локальном запуске, поэтому Google App Engine должен что-то делать для удаления файла cookie? Я не слишком хорошо знаком с Google App Engine, поэтому буду признателен за любую помощь.
Я перепробовал много разных решений, которые нашел в Интернете, таких как passport.socketio из npm, многие из которых, как я полагаю, реализуют то же решение, которое я в итоге написал сам.
Редактировать 1:
Чтобы быть более конкретным, data.headers.cookies
содержит io
, connect.sid
и express.sid
cookie при запуске с локального хоста. При запуске в Google App Engine он содержит только io
файл cookie. (Конец редактирования)
Редактировать 2:
Я подумал, что это может быть проблемой с наличием разных экземпляров моего сервера из-за автоматического масштабирования Google, поэтому я изменил свои настройки, app.yaml
чтобы убедиться, что этого не произойдет:
network:
session_affinity: true
manual_scaling:
instances: 1
(Конец редактирования)
Код:
var session = require('express-session');
var MemoryStore = require('memorystore')(session);
var store = new MemoryStore({
checkPeriod: 86400000
}); // Likely to switch to RedisStore
app.use(session({
store: store,
secret: 'jpcs-0001080900DRXPXL',
saveUninitialized: false,
resave: true,
key: 'express.sid'
}));
// ...
io.set('authorization', (data, accept) => {
if (data amp;amp; data.headers amp;amp; data.headers.cookie) {
console.log('COOKIES:');
console.log(data.headers.cookie);
cookies_str = data.headers.cookie;
cookies_arr = cookies_str.split(';');
cookies = {};
for (index in cookies_arr) {
cookie = cookies_arr[index].split('=');
if (cookie.length != 2) continue;
key = cookie[0].replace(/ /g,'');
val = cookie[1];
cookies[key] = val;
}
if (!cookies['express.sid']) accept('User not signed in', null);
// HERE IS MY PROBLEM:
// When running from google app engine cookies['express.sid'] is null
sessionId = cookies['express.sid'].split('.')[0].substring(4);
data.sessionId = sessionId;
store.get(sessionId, (err, session) => {
if (!err amp;amp; session) {
data.session = session;
accept(null, true);
}
else if (err) accept('Could not get session', false);
else if (!session) accept('Could not get session', false)
});
}
accept('Could not get session', false);
});
Поэтому я ожидаю, что cookies [‘express.sid’] будут содержать в нем идентификатор сеанса, но в Google app Engine он равен нулю.
App.yaml
runtime: nodejs10 # For Node.js 8, use runtime: nodejs8
#instance_class: F2
#env_variables:
#BUCKET_NAME: "example-gcs-bucket"
handlers:
- url: .*
secure: always
redirect_http_response_code: 301
script: auto
network:
session_affinity: true
manual_scaling:
instances: 1
Ответ №1:
Более вероятно, что ваше приложение не может получить пользователя из хранилища сеансов при запуске в GAE из-за конфигурации сети или приложения. Дополнительная информация о том, какое хранилище сеансов вы используете, его конфигурация в express и app.yaml были бы более полезны для решения этой проблемы. Маловероятно, что GAE удалит файл cookie из заголовков HTTP-ответа.
Я обнаружил, что для использования redis с express / express-session мне нужно было указать имя сети app.yaml
.
network:
name: default
К сожалению, похоже, что вы не можете использовать это для стандартных сред, поэтому мне также пришлось изменить:
runtime: nodejs
env: flex
А также необходимо указать механизм package.json
при переключении на гибкую среду.
"engines": {
"node": "10.x"
}
Комментарии:
1. Спасибо, я собираюсь поиграть с конфигурацией приложения и посмотреть, изменится ли что-нибудь. Я не думаю, что это проблема с возможностью доступа к хранилищу сеансов, хотя оно отлично работает за пределами websockets, но я еще не смог это проверить, поскольку я даже не могу получить идентификатор сеанса для извлечения пользователя. — Также добавляю хранилище сеансов (MemoryStore) и app.yaml на мой вопрос.
2. Обновление: использование среды flex также не сработало, интересно, возможно ли перехватить начальный сокет HTTP-запроса. ввод-вывод позволяет установить соединение с сокетами. Я бы подумал, что вы могли бы получить там идентификатор сеанса без каких-либо проблем, я не знаю, как это сделать, хотя даже после некоторых исследований