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

博客讨论了如何在Node.js应用中创建用户会话并在需要时读取。作者遇到的问题是尝试在用户登录时设置会话值,并在Socket.IO连接上读取这些值。解决方案包括正确配置Express中间件,确保会话存储的顺序,并在Socket.IO连接上发送会话ID。还提到了由于Socket.IO的特性,直接在会话中设置和读取值可能会遇到问题,特别是跨域和不同传输方式时。
摘要由CSDN通过智能技术生成

Fttygg提出的问题

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

<span style="color:#444444"><span style="background-color:#ffffff"><code class="language-javascript">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);
</code></span></span>

解决方案

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

<span style="color:#333333"><span style="background-color:#ffffff"><code class="language-javascript">req.session.portal = false
Passport.authenticate('facebook', (req, res, next) => {
    next()
})(req, res, next)
</code></span></span>

在护照策略上,我没有在 Mozilla 请求中获得门户价值,但可以正常使用 chrome 和 opera

<span style="color:#333333"><span style="background-color:#ffffff"><code class="language-javascript">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));</code></span></span>

我做的步骤:

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

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

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

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

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

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

<span style="color:#333333"><span style="background-color:#ffffff"><code class="language-javascript">app.use(express.cookieParser());
app.use(express.session({ secret: sessionVal }));
app.use(app.route);</code></span></span>

 

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

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

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

<span style="color:#333333"><span style="background-color:#ffffff"><code class="language-javascript">req.session.email = req.param('email');
</code></span></span>

有了这个…


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

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

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

您可以获取 Connect 的会话数据;您只需要获取对会话存储的引用。最简单的方法是在调用之前自己创建商店express.session

<span style="color:#333333"><span style="background-color:#ffffff"><code class="language-javascript">// 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 }));
</code></span></span>

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

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

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

<span style="color:#333333"><span style="background-color:#ffffff"><code class="language-javascript">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);
</code></span></span>

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值