nodeJS - 如何使用express创建和读取会话

时间:2011-04-23 17:33:48

标签: node.js

我想在用户输入应用时创建用户会话。并在需要时阅读会话。这是我的尝试

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: me@gmail.com
    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:'me@gmail.com'}
        // 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);

5 个答案:

答案 0 :(得分:71)

我需要在此指出,您错误地将中间件添加到应用程序中。 app.use调用不应在app.get请求处理程序中完成,而应在其外部完成。只需在createServer之后直接致电,或者查看the other examples in the docs

传递给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参数或会话ID存储在客户端的cookie中。该cookie的默认名称为connect.sid。 (但您可以在key来电中指定express.session选项,为其命名。

然后,您需要在Socket.IO连接上访问该cookie。不幸的是,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)方法,看看会发生什么。

答案 1 :(得分:5)

互操作socket.io和连接会话支持很麻烦。问题不是因为socket.io以某种方式“劫持”请求,而是因为某些socket.io传输(我认为flashsockets)不支持cookie。我可能错了cookie,但我的方法如下:

  1. 为socket.io实现一个单独的会话存储,它以与connect-redis
  2. 相同的格式存储数据
  3. 使连接会话cookie不是仅限http,因此可以从客户端JS
  4. 访问
  5. 在socket.io连接时,通过socket.io将会话cookie从浏览器发送到服务器
  6. 将会话ID存储在socket.io连接中,并使用它来访问redis中的会话数据。

答案 2 :(得分:5)

  

当我使用req.session.email = req.param('email')时,我忘了告诉一个错误,服务器错误说无法解决未定义的属性电子邮件。

此错误的原因是app.use的顺序错误。您必须按此顺序配置express:

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

答案 3 :(得分:2)

我做的步骤:

  1. 在HTML中包含angular-cookies.js文件!
  2. 初始化cookie在服务器端应用程序中不是仅限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'];

  6. 现在您可以从客户端将其发送回服务器。真棒。希望他们将这个放在Angular.js文档中。我通过直接读取angular-cookies.js的实际代码来解决这个问题。

答案 4 :(得分:0)

你好,我想在节点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));