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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5765777/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 14:04:42  来源:igfitidea点击:

nodeJS - How to create and read session with express

node.js

提问by angry kiwi

I want to create a user sessison when user enter the app. And read the session whenever needed. Here is my try

我想在用户进入应用程序时创建一个用户会话。并在需要时阅读会话。这是我的尝试

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);

回答by Stéphan Kochen

I need to point out here that you're incorrectly adding middleware to the application. The app.usecalls should not be done within the app.getrequest handler, but outside of it. Simply call them directly after createServer, or take a look at the other examples in the docs.

我需要在这里指出,您错误地向应用程序添加了中间件。该app.use电话不应该内完成app.get的请求处理程序,但它的外面。之后直接调用它们createServer,或者查看文档的其他示例

The secret you pass to express.sessionshould be a string constant, or perhaps something taken from a configuration file. Don't feed it something the client might know, that's actually dangerous. It's a secret only the server should know about.

您传递给的秘密express.session应该是一个字符串常量,或者可能是从配置文件中获取的内容。不要给它提供客户可能知道的东西,这实际上很危险。这是只有服务器应该知道的秘密。

If you want to store the email address in the session, simply do something along the lines of:

如果您想在会话中存储电子邮件地址,只需执行以下操作:

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

With that out of the way...

有了这个...



If I understand correctly, what you're trying to do is handle one or more HTTP requests and keep track of a session, then later on open a Socket.IO connection from which you need the session data as well.

如果我理解正确的话,您要做的是处理一个或多个 HTTP 请求并跟踪会话,然后打开一个 Socket.IO 连接,您还需要从中获取会话数据。

What's tricky about this problem is that Socket.IO's means of making the magic work on any http.Serveris by hiHymaning the requestevent. Thus, Express' (or rather Connect's) session middleware is never called on the Socket.IO connection.

这个问题的棘手之处在于,Socket.IO 使魔法在 any 上发挥作用的方法http.Server是通过劫持request事件。因此,永远不会在 Socket.IO 连接上调用Express(或者更确切地说Connect的)会话中间件。

I believe you can make this work, though, with some trickery.

不过,我相信您可以通过一些技巧来完成这项工作。

You can get to Connect's session data; you simply need to get a reference to the session store. The easiest way to do that is to create the store yourself before calling express.session:

可以获取到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 }));

Every session store has a get(sid, callback)method. The sidparameter, or session ID, is stored in a cookie on the client. The default name of that cookie is connect.sid. (But you can give it any name by specifying a keyoption in your express.sessioncall.)

每个会话存储都有一个get(sid, callback)方法。的sid参数,或会话ID,被存储在客户端上的cookie。该 cookie 的默认名称是connect.sid. (但您可以通过keyexpress.session调用中指定一个选项来为其命名。)

Then, you need to access that cookie on the Socket.IO connection. Unfortunately, Socket.IO doesn't seem to give you access to the http.ServerRequest. A simple work around would be to fetch the cookie in the browser, and send it over the Socket.IO connection.

然后,您需要在 Socket.IO 连接上访问该 cookie。不幸的是,Socket.IO 似乎无法让您访问http.ServerRequest. 一个简单的解决方法是在浏览器中获取 cookie,然后通过 Socket.IO 连接发送它。

Code on the server would then look something like the following:

服务器上的代码如下所示:

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);

This assumes you only want to read an existing session. You cannot actually create or delete sessions, because Socket.IO connections may not have a HTTP response to send the Set-Cookieheader in (think WebSockets).

这假设您只想阅读现有会话。您实际上无法创建或删除会话,因为 Socket.IO 连接可能没有 HTTP 响应来发送Set-Cookie标头(想想 WebSockets)。

If you want to edit sessions, that may work with some session stores. A CookieStore wouldn't work for example, because it also needs to send a Set-Cookieheader, which it can't. But for other stores, you could try calling the set(sid, data, callback)method and see what happens.

如果您想编辑会话,这可能适用于某些会话存储。例如,CookieStore 不起作用,因为它还需要发送一个Set-Cookie标头,而它不能。但是对于其他商店,您可以尝试调用该set(sid, data, callback)方法,看看会发生什么。

回答by nponeccop

It is cumbersome to interoperate socket.io and connect sessions support. The problem is not because socket.io "hiHymans" request somehow, but because certain socket.io transports (I think flashsockets) don't support cookies. I could be wrong with cookies, but my approach is the following:

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

  1. Implement a separate session store for socket.io that stores data in the same format as connect-redis
  2. Make connect session cookie not http-only so it's accessible from client JS
  3. Upon a socket.io connection, send session cookie over socket.io from browser to server
  4. Store the session id in a socket.io connection, and use it to access session data from redis.
  1. 为 socket.io 实现一个单独的会话存储,以与 connect-redis 相同的格式存储数据
  2. 使连接会话 cookie 不是 http-only,以便它可以从客户端 JS 访问
  3. 在 socket.io 连接上,通过 socket.io 从浏览器向服务器发送会话 cookie
  4. 将会话 ID 存储在 socket.io 连接中,并使用它从 redis 访问会话数据。

回答by Donald Lian

I forgot to tell a bug when i use I use req.session.email = req.param('email'), the server error says cannot sett property email of undefined.

我在使用时忘记告诉错误我使用 req.session.email = req.param('email'),服务器错误说无法设置未定义的属性电子邮件。

The reason of this error is a wrong order of app.use. You must configure express in this order:

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

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

回答by CommaToast

Steps I did:

我做的步骤:

  1. Include the angular-cookies.js file in the HTML!
  2. Init cookies as being NOT http-only in server-side app.'s:

    app.configure(function(){
       //a bunch of stuff
       app.use(express.cookieSession({secret: 'mySecret', store: store, cookie: cookieSettings}));```
    
  3. Then in client-side services.jss I put ['ngCookies'] in like this:

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

  4. Then in controller.js, in my function UserLoginCtrl, I have $cookiesin there with $scopeat the top like so:

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

  5. Lastly, to get the value of a cookie inside the controller function I did:

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

  1. 在 HTML 中包含 angular-cookies.js 文件!
  2. 在服务器端应用程序中将 cookie 初始化为非 http-only:

    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'];

Now you can send that back to the server from the client. Awesome. Wish they would've put this in the Angular.js documentation. I figured it out by just reading the actual code for angular-cookies.js directly.

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

回答by Varun Sharma

Hello I am trying to add new session values in node js like

您好,我正在尝试在节点 js 中添加新的会话值,例如

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

On passport strategies I am not getting portal value in mozilla request but working fine with chrome and opera

关于护照策略,我没有在 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));