如何用express创建和读取会话

时间:2021-07-15 23:55:46

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

我想要创建一个用户sessison,当用户输入app时,并在需要时读取会话。这是我的尝试

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

4 个解决方案

#1


66  

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

我需要指出的是,您将中间件添加到应用程序中是错误的。use调用不应该在app.get请求处理程序中执行,而是在它之外执行。只需在createServer之后直接调用它们,或者查看文档中的其他示例。

The secret you pass to express.session should 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.

你想表达的秘密。会话应该是一个字符串常量,或者可能是从配置文件中获取的东西。不要给它提供客户可能知道的东西,那实际上是危险的。这是一个只有服务器才知道的秘密。

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请求并跟踪会话,然后打开一个套接字。还需要会话数据的IO连接。

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

这个问题的难点在于套接字。IO是在任何http上执行魔术的方法。服务器通过劫持请求事件。因此,永远不会在套接字上调用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.e之前自己创建商店。

// 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 sid parameter, 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 key option in your express.session call.)

每个会话存储都有一个get(sid, callback)方法。sid参数(即会话ID)存储在客户机的cookie中。该cookie的默认名称是connector .sid。(但是你可以通过在你的快递中指定一个键选项来给它起任何名字。会话的电话。)

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.

然后,您需要访问套接字上的cookie。输入输出连接。不幸的是,套接字。IO似乎不允许您访问http.ServerRequest。一个简单的解决方法是在浏览器中获取cookie,然后通过套接字发送。输入输出连接。

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-Cookie header in (think WebSockets).

这假定您只想读取一个现有会话。您不能实际创建或删除会话,因为套接字。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-Cookie header, 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)方法,看看会发生什么。

#2


5  

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时忘记告诉错误。邮件= 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);

#3


4  

It is cumbersome to interoperate socket.io and connect sessions support. The problem is not because socket.io "hijacks" 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:

互操作插座很麻烦。io和连接会话支持。问题不在于插座。io“劫持”请求,但因为某些套接字。io传输(我认为是flashsockets)不支持cookie。我可能对饼干有误解,但我的方法是:

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

#4


3  

Steps I did:

我做的步骤:

  1. Include the angular-cookies.js file in the HTML!
  2. 包括angular-cookies。HTML中的js文件!
  3. Init cookies as being NOT http-only in server-side app.'s:

    Init cookie不是http-仅在服务器端应用程序中。

    var cookieSettings = {path: '/', httpOnly: false, maxAge: null}; app.configure(function(){ //a bunch of stuff app.use(express.cookieSession({secret: 'mySecret', store: store, cookie: cookieSettings}));

    var cookieSettings = {path: '/', httpOnly: false, maxAge: null};configure(function(){// //一堆东西app.use(express)cookieSession({secret:‘mySecret’,store: store, cookie: cookieSettings});

  4. Then in client-side services.jss I put ['ngCookies'] in like this:

    然后在客户端服务。我把['ngCookies']放在这里:

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

    角。模块(“swrp”,[' ngCookies '])。/ /等

  5. Then in controller.js, in my function UserLoginCtrl, I have $cookies in there with $scope at the top like so:

    然后在控制器。js,在我的函数UserLoginCtrl中,我有$cookies顶部有$scope,如下所示:

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

    函数UserLoginCtrl($scope, $cookies, socket)

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

    最后,为了得到控制器函数中cookie的值,我做了如下操作:

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

    var mySession = $饼干(“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.

现在您可以从客户端将其发送回服务器。太棒了。但愿他们能把这个角化。js文件。我通过阅读angular-cookies的实际代码就知道了。js直接。

#1


66  

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

我需要指出的是,您将中间件添加到应用程序中是错误的。use调用不应该在app.get请求处理程序中执行,而是在它之外执行。只需在createServer之后直接调用它们,或者查看文档中的其他示例。

The secret you pass to express.session should 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.

你想表达的秘密。会话应该是一个字符串常量,或者可能是从配置文件中获取的东西。不要给它提供客户可能知道的东西,那实际上是危险的。这是一个只有服务器才知道的秘密。

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请求并跟踪会话,然后打开一个套接字。还需要会话数据的IO连接。

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

这个问题的难点在于套接字。IO是在任何http上执行魔术的方法。服务器通过劫持请求事件。因此,永远不会在套接字上调用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.e之前自己创建商店。

// 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 sid parameter, 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 key option in your express.session call.)

每个会话存储都有一个get(sid, callback)方法。sid参数(即会话ID)存储在客户机的cookie中。该cookie的默认名称是connector .sid。(但是你可以通过在你的快递中指定一个键选项来给它起任何名字。会话的电话。)

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.

然后,您需要访问套接字上的cookie。输入输出连接。不幸的是,套接字。IO似乎不允许您访问http.ServerRequest。一个简单的解决方法是在浏览器中获取cookie,然后通过套接字发送。输入输出连接。

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-Cookie header in (think WebSockets).

这假定您只想读取一个现有会话。您不能实际创建或删除会话,因为套接字。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-Cookie header, 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)方法,看看会发生什么。

#2


5  

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时忘记告诉错误。邮件= 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);

#3


4  

It is cumbersome to interoperate socket.io and connect sessions support. The problem is not because socket.io "hijacks" 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:

互操作插座很麻烦。io和连接会话支持。问题不在于插座。io“劫持”请求,但因为某些套接字。io传输(我认为是flashsockets)不支持cookie。我可能对饼干有误解,但我的方法是:

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

#4


3  

Steps I did:

我做的步骤:

  1. Include the angular-cookies.js file in the HTML!
  2. 包括angular-cookies。HTML中的js文件!
  3. Init cookies as being NOT http-only in server-side app.'s:

    Init cookie不是http-仅在服务器端应用程序中。

    var cookieSettings = {path: '/', httpOnly: false, maxAge: null}; app.configure(function(){ //a bunch of stuff app.use(express.cookieSession({secret: 'mySecret', store: store, cookie: cookieSettings}));

    var cookieSettings = {path: '/', httpOnly: false, maxAge: null};configure(function(){// //一堆东西app.use(express)cookieSession({secret:‘mySecret’,store: store, cookie: cookieSettings});

  4. Then in client-side services.jss I put ['ngCookies'] in like this:

    然后在客户端服务。我把['ngCookies']放在这里:

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

    角。模块(“swrp”,[' ngCookies '])。/ /等

  5. Then in controller.js, in my function UserLoginCtrl, I have $cookies in there with $scope at the top like so:

    然后在控制器。js,在我的函数UserLoginCtrl中,我有$cookies顶部有$scope,如下所示:

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

    函数UserLoginCtrl($scope, $cookies, socket)

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

    最后,为了得到控制器函数中cookie的值,我做了如下操作:

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

    var mySession = $饼干(“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.

现在您可以从客户端将其发送回服务器。太棒了。但愿他们能把这个角化。js文件。我通过阅读angular-cookies的实际代码就知道了。js直接。