【问题标题】:express-session won't set cookie connect.sidexpress-session 不会设置 cookie connect.sid
【发布时间】:2017-06-20 16:42:24
【问题描述】:

编辑 5

我在 LAMP 环境中运行后端和前端,可通过192.168.80.213/backend 地址访问。 我尝试使用 nodejs、socket.io 和 express 框架制作一个推送通知服务器来链接后端和前端。

我的 nodejs 服务器正在侦听端口 3000,而我的后端和前端都在使用 apache 侦听端口 80。

这是我的节点客户端:

<script type="text/javascript" src="socket.io-1.4.5.js"></script>
<script type="text/javascript">
    var socket = io('http://192.168.80.213:3000/');
</script>

这是我的节点服务器:

const   express          = require('express')
        , app            = express()
        , http           = require('http').Server(app)
        , socketIo       = require('socket.io')(http)
        , cookieParser   = require('cookie-parser')
        , cookie         = require('cookie')
        , connect        = require('connect')
        , expressSession = require('express-session')
        , port           = 3000
        , helmet         = require('helmet')
        , name           = 'connect.sid'
        , sessionStore   = new expressSession.MemoryStore({ reapInterval: 60000 * 10 })
        , sessionSecret  = 'VH6cJa7yZSmkRbmjZW#J3%CDn%dt'
        , environment    = process.env.NODE_ENV || 'development'
        ;

/** Configuration **/
app.enable('trust proxy');
app.disable('x-powered-by');
app.use(helmet());
app.use(cookieParser());
app.use(expressSession({
    'name'  : name,
    'secret': sessionSecret,
    'store' : sessionStore,
    'resave': true,
    'saveUninitialized': true
}));

app.get('/', function(req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello from node');
});

socketIo.use(function(socket, callback) {
    // Read cookies from handshake headers
    var cookies = cookie.parse(socket.handshake.headers.cookie);
    // We're now able to retrieve session ID
    var sessionID;
    if (cookies[name]) {
        console.log( "cookies['" + name + "'] = " + cookies[name] );
        sessionID = cookieParser.signedCookie( cookies[name], sessionSecret );
        console.log( "sessionID = " + sessionID );
    }else{
        console.log( "cookies['" + name + "'] = undefined" );
    }

    if (!sessionID) {
        console.log('ERROR NO SESSION CONNECTION REFUSED !!');
        callback('No session', false);
    } else {
        // Store session ID in handshake data, we'll use it later to associate
        // session with open sockets
        socket.handshake.sessionID = sessionID;
        callback(null, true);
    }

});


socketIo.on('connection', function (socket) { // New client
    console.log( 'new connection..' );
    console.log('user ' + socket.handshake.sessionID + ' authenticated and is now connected.');  

});

/** Start server */
http.listen(port);
console.log( "listening on :" + port );

转到192.168.80.213:3000 并查看'Hello from node' 并且cookie['connect.sid'] 根据下面的截图设置

和控制台输出:

现在正在清除缓存,我要去我的后端应用程序,我的 nodeClient 192.168.80.213/backend 在哪里。

connect.sid cookie 不存在

和控制台输出:

为什么 express-session 没有设置 cookie.sid ?我该如何解决?我是node和express的新手,我用谷歌搜索了很多次都没有成功,希望一些节点大师能帮助我!!

问候

【问题讨论】:

    标签: javascript node.js express socket.io


    【解决方案1】:

    我不知道您使用的是哪个版本的 socket.io,但在 1.0 版之后(&gt; 1.0):

    • 要注册中间件,您应该使用socketIo.use(参见documentation
    • 第一个参数是传入套接字,它可以通过socket.request 访问请求
    • 默认情况下快速会话保存带有connect.sid 名称的cookie,如果您想使用io 名称,您应该明确设置它(参见name option
    • 当你想解析一个签名的 cookie 时,你应该提供它 sessionSecret 而不是 sessionStore
    • 最后我认为握手支持已被弃用,你应该将任何你想要的东西直接附加到 socket(参见authentication-differences)。

    考虑到上述情况,您可以使用如下中间件来Authenticate 您的套接字:

    // every incoming socket should pass this middleware
    socketIo.use(function(socket, next) {
      var cookies = cookie.parse(socket.request.headers.cookie);
      var sessionID = cookieParser.signedCookie(cookies['connect.sid'], sessionSecret);
      sessionStore.get(sessionID, function(err, session) {
        if ( session && session.isAuthenticated ) {
          socket.userId = session.user.id;
          return next();
        } else {
          return next(new Error('Not Authenticated'));
        }
      });
    });
    // when connected ...
    socketIo.on('connection', function(socket) {
      console.log('user ' + socket.userId + ' authenticated and is now connected.')
    });
    

    在这里,我认为您在用户登录时在会话中设置了 isAuthenticated 布尔值和 user

    还要记住,内置sessionStore,MemoryStore 不适合生产环境:

    默认的服务器端会话存储 MemoryStore 故意不 专为生产环境而设计。它会在大多数情况下泄漏内存 条件,不会超过单个过程,并且适用于 调试和开发。

    因此您必须考虑使用另一个会话存储,例如:

    【讨论】:

    • console.log(cookies['connect.sid']);输出未定义,然后是 console.log(cookies['io']);返回为什么 cookies['connect.sid'] 是未定义的?
    • 只有这段代码,很难找出io cookie 的来源。有没有可以设置该cookie 的地方?
    • 你需要什么?我所有的服务器端代码都在上面,我确定我没有在任何地方设置任何 cookie
    • 删除你不需要的connect = require('connect')。还禁用helmet 可能会阻止设置cookie。并再次测试。
    • 完成!!不工作... :'( connect.sid 仍然未定义.. 客户端评论了除var socket = io('http://localhost:3000'); 之外的所有行
    【解决方案2】:

    我没有使用 cookie 或 cookie-parser 的经验,并且通常是 node 新手,但我有一个类似的系统来通过访问服务器端会话变量来验证套接字连接,如果这有帮助的话。

    将会话详细信息保存在变量中

    var sessionStorage = expressSession({
    'secret': sessionSecret,
    'store' : sessionStore,
    'resave': true,
    'saveUninitialized': true 
    });
    

    让socketIo和app使用存储

    socketIo.use(function (socket, next) {
        sessionStorage(socket.request, socket.request.res, next);
    });
    app.use(sessionStorage);
    

    然后在内部连接时,您可以使用以下方法访问这些会话变量:

    socket.request.res.session.[variable name]
    

    【讨论】:

    • 重点是 express 默认创建一个名为connect.sid的cookie。就我而言,它没有这样做
    • 检查调试器“socket.request.session”有一个“id”属性,注意它不是“sid”。这似乎与浏览器中设置的 cookie 匹配。
    • socket.request.session 中没有 id 属性,但 socket.request.sessionID 存在但与浏览器中设置的 cookie 不匹配
    • 检查整个字符串。我注意到从服务器访问变量时,前 5 个左右的字符被删除了
    猜你喜欢
    • 1970-01-01
    • 2021-01-11
    • 2021-11-18
    • 2019-11-05
    • 1970-01-01
    • 2021-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多