Подтвердить что ты не робот

NodeJS - Как создать и прочитать сеанс с помощью express

Я хочу создать пользовательский сеанс при входе пользователя в приложение. И прочитайте сессию, когда это необходимо. Вот моя попытка

var io   = require('socket.io'),
    express = require('express');
    querystring = require('querystring');

var app = express.createServer();
app.get('/', function(req, res){
    var sessionVal = querystring.parse(req.url.substr(2));// sessionVal is an email for example: [email protected]
    app.use(express.cookieParser());
    app.use(express.session({ secret: sessionVal }));
});
var socket = io.listen(app);
socket.on('connection', function(client) {
    client.on('message', function(message) {
        // message will be an object {text:'user text chat blah blah', email:'[email protected]'}
        // if the seesion stored, has the same value with message.email
        // then the message will be broadcasted
            socket.broadcast(message.text);
        // else will not broadcast  
    });
});

app.listen(4000);
4b9b3361

Ответ 1

Мне нужно указать, что вы неправильно добавляете в приложение промежуточное ПО. Вызов app.use не должен выполняться в обработчике запроса app.get, но за его пределами. Просто позвоните им непосредственно после createServer или посмотрите другие примеры в документах.

Секрет, который вы передаете в express.session, должен быть строковой константой или, возможно, чем-то взятым из файла конфигурации. Не кормите его тем, что может знать клиент, что на самом деле опасно. Это секрет, о котором должен знать только сервер.

Если вы хотите сохранить адрес электронной почты в сеансе, просто выполните что-то по строкам:

req.session.email = req.param('email');

С этим в сторону...


Если я правильно понимаю, то, что вы пытаетесь сделать, это обработать один или несколько HTTP-запросов и отслеживать сеанс, а затем открыть соединение Socket.IO, из которого вам нужны данные сеанса.

Какая сложность в этой проблеме заключается в том, что средство Socket.IO для создания волшебной работы над любым http.Server заключается в захвате события request. Таким образом, Express '(или, скорее, Connect), промежуточное ПО сеанса никогда не вызывается в соединении Socket.IO.

Я считаю, что вы можете сделать эту работу, хотя, с некоторыми обманами.

Вы можете получить данные сеанса Connect; вам просто нужно получить ссылку на хранилище сеансов. Самый простой способ сделать это - создать магазин перед вызовом express.session:

// A MemoryStore is the default, but you probably want something
// more robust for production use.
var store = new express.session.MemoryStore;
app.use(express.session({ secret: 'whatever', store: store }));

Каждое хранилище сеансов имеет метод get(sid, callback). Параметр sid или идентификатор сеанса хранится в файле cookie на клиенте. По умолчанию для этого файла cookie указано connect.sid. (Но вы можете дать ему любое имя, указав опцию key в своем вызове express.session.)

Затем вам нужно получить доступ к этому файлу cookie в соединении Socket.IO. К сожалению, Socket.IO, похоже, не дает вам доступ к http.ServerRequest. Простая работа заключалась бы в том, чтобы получить cookie в браузере и отправить его через соединение Socket.IO.

Код на сервере будет выглядеть примерно так:

var io      = require('socket.io'),
    express = require('express');

var app    = express.createServer(),
    socket = io.listen(app),
    store  = new express.session.MemoryStore;
app.use(express.cookieParser());
app.use(express.session({ secret: 'something', store: store }));

app.get('/', function(req, res) {
  var old = req.session.email;
  req.session.email = req.param('email');

  res.header('Content-Type', 'text/plain');
  res.send("Email was '" + old + "', now is '" + req.session.email + "'.");
});

socket.on('connection', function(client) {
  // We declare that the first message contains the SID.
  // This is where we handle the first message.
  client.once('message', function(sid) {
    store.get(sid, function(err, session) {
      if (err || !session) {
        // Do some error handling, bail.
        return;
      }

      // Any messages following are your chat messages.
      client.on('message', function(message) {
        if (message.email === session.email) {
          socket.broadcast(message.text);
        }
      });
    });
  });
});

app.listen(4000);

Предполагается, что вы хотите читать только существующий сеанс. Вы не можете создавать или удалять сеансы, потому что соединения Socket.IO могут не иметь ответа HTTP для отправки заголовка Set-Cookie (думаю, WebSockets).

Если вы хотите редактировать сеансы, это может работать с некоторыми хранилищами сеансов. Например, CookieStore не работает, потому что ему также необходимо отправить заголовок Set-Cookie, который он не может. Но для других магазинов вы можете попробовать вызвать метод set(sid, data, callback) и посмотреть, что произойдет.

Ответ 2

Очень сложно взаимодействовать сокета socket.io и подключать сеансы. Проблема заключается не в том, что socket.io "захватывает" запрос каким-то образом, а потому, что некоторые сокеты (я думаю, flashsockets) не поддерживают файлы cookie. Я могу ошибаться в отношении файлов cookie, но мой подход следующий:

  • Реализовать отдельный хранилище сеансов для socket.io, который хранит данные в том же формате, что и connect-redis
  • Сделать сеанс cookie сеанса не http-only, чтобы он был доступен из клиента JS
  • После подключения socket.io отправьте cookie сеанса через socket.io из браузера на сервер.
  • Сохраните идентификатор сеанса в соединении socket.io и используйте его для доступа к данным сеанса из redis.

Ответ 3

Я забыл сообщить об ошибке, когда использую я использую req.session.email = req.param('email'), ошибка сервера говорит, что не может настроить электронную почту свойства undefined.

Причиной этой ошибки является неправильный порядок app.use. Вы должны настроить выражение в следующем порядке:

app.use(express.cookieParser());
app.use(express.session({ secret: sessionVal }));
app.use(app.route);

Ответ 4

Шаги, которые я сделал:

  1. Включите файл angular-cookies.js в HTML!
  2. Инициируйте куки как НЕ только http в приложении на стороне сервера.

    app.configure(function(){
       //a bunch of stuff
       app.use(express.cookieSession({secret: 'mySecret', store: store, cookie: cookieSettings}));'''
    
  3. Затем в services.jss на стороне клиента я помещаю ['ngCookies'] так:

    angular.module('swrp', ['ngCookies']).//etc

  4. Затем в controller.js в моей функции UserLoginCtrl меня есть $cookies а $scope вверху, вот так:

    function UserLoginCtrl($scope, $cookies, socket) {

  5. Наконец, чтобы получить значение cookie внутри функции контроллера, я сделал:

    var mySession = $cookies['connect.sess'];

Теперь вы можете отправить это обратно на сервер с клиента. Потрясающие. Хотелось бы, чтобы они поместили это в документацию Angular.js. Я понял это, просто прочитав фактический код angular-cookies.js напрямую.

Ответ 5

Здравствуйте, я пытаюсь добавить новые значения сеанса в узел JS, как

req.session.portal = false
Passport.authenticate('facebook', (req, res, next) => {
    next()
})(req, res, next)

По паспортным стратегиям я не получаю значение портала в запросе Mozilla, но работаю нормально с Chrome и Opera

FacebookStrategy: new PassportFacebook.Strategy({
    clientID: Configuration.SocialChannel.Facebook.AppId,
    clientSecret: Configuration.SocialChannel.Facebook.AppSecret,
    callbackURL: Configuration.SocialChannel.Facebook.CallbackURL,
    profileFields: Configuration.SocialChannel.Facebook.Fields,
    scope: Configuration.SocialChannel.Facebook.Scope,
    passReqToCallback: true
}, (req, accessToken, refreshToken, profile, done) => {
    console.log(JSON.stringify(req.session));