【问题标题】:Google app engine removes session cookies when authorizing socket.io connectionGoogle 应用引擎在授权 socket.io 连接时删除会话 cookie
【发布时间】:2019-04-15 03:03:25
【问题描述】:

当用户打开 WebSocket 连接时,我试图从 express-session 中获取用户的 sessionID。下面的代码显示了这是如何完成的。问题是当我将服务器部署到谷歌应用程序引擎时,在授权套接字连接时我再也看不到会话 cookie。在本地运行时它工作正常,所以谷歌应用引擎必须做一些事情来删除 cookie?我对谷歌应用引擎不太熟悉,所以任何帮助将不胜感激。

我尝试了许多我在网上找到的不同解决方案,例如来自 npm 的 passport.socketio,我相信其中许多解决方案与我最终自己编写的解决方案相同。

编辑 1:

更具体地说,data.headers.cookies 在从 localhost 运行时包含 ioconnect.sidexpress.sid cookie。在谷歌应用引擎上运行时,它只包含io cookie。 (编辑结束)

编辑 2:

我认为由于 google 的自动扩展,我的服务器的不同实例可能是个问题,所以我更改了app.yaml 中的设置以确保不会发生这种情况:

network:
  session_affinity: true

manual_scaling:
  instances: 1

(编辑结束)

代码:


var session = require('express-session');
var MemoryStore = require('memorystore')(session);

var store = new MemoryStore({
  checkPeriod: 86400000
}); // Likely to switch to RedisStore

app.use(session({
  store: store,
  secret: 'jpcs-0001080900DRXPXL',
  saveUninitialized: false,
  resave: true,
  key: 'express.sid'
}));

// ...

io.set('authorization', (data, accept) => {

  if (data && data.headers && data.headers.cookie) {

    console.log('COOKIES:');
    console.log(data.headers.cookie);

    cookies_str = data.headers.cookie;
    cookies_arr = cookies_str.split(';');
    cookies = {};

    for (index in cookies_arr) {
      cookie = cookies_arr[index].split('=');
      if (cookie.length != 2) continue;
      key = cookie[0].replace(/ /g,'');
      val = cookie[1];
      cookies[key] = val;
    }

    if (!cookies['express.sid']) accept('User not signed in', null);

    // HERE IS MY PROBLEM:
    // When running from google app engine cookies['express.sid'] is null

    sessionId = cookies['express.sid'].split('.')[0].substring(4);
    data.sessionId = sessionId;

    store.get(sessionId, (err, session) => {
      if (!err && session) {
        data.session = session;
        accept(null, true);
      }
      else if (err) accept('Could not get session', false);
      else if (!session) accept('Could not get session', false)
    });

  }

  accept('Could not get session', false);

});

所以我希望 cookies['express.sid'] 在其中包含 sessionID,但在谷歌应用引擎上它是空的。

App.yaml

runtime: nodejs10 # For Node.js 8, use runtime: nodejs8

#instance_class: F2

#env_variables:
  #BUCKET_NAME: "example-gcs-bucket"

handlers:
- url: .*
  secure: always
  redirect_http_response_code: 301
  script: auto

network:
  session_affinity: true

manual_scaling:
  instances: 1

【问题讨论】:

    标签: google-app-engine session socket.io express-session


    【解决方案1】:

    由于网络或应用配置,您的应用在 GAE 上运行时更有可能无法从会话存储中检索用户。有关您正在使用的会话存储、快速配置以及 app.yaml 的更多信息将有助于解决此问题。 GAE 不太可能从 HTTP 响应标头中删除 cookie。

    我发现为了在 express/express-session 中使用 redis,我需要在 app.yaml 中设置网络名称。

    network:
      name: default
    

    不幸的是,您似乎无法将其用于标准环境,因此我也不得不进行更改:

    runtime: nodejs
    env: flex
    

    并且在切换到柔性环境时还需要在package.json中指定一个引擎。

    "engines": {
      "node": "10.x"
    }
    

    【讨论】:

    • 谢谢,我将尝试一下应用程序配置,看看是否有任何改变。我认为能够访问会话存储不是问题,它在 websockets 之外工作正常,但我还没有能够测试它,因为我什至无法获取会话 ID 来检索用户. - 还将会话存储 (MemoryStore) 和 app.yaml 添加到我的问题中。
    • 更新:使用flex环境也没有成功,我想知道是否可以拦截socket.io建立套接字连接的初始HTTP请求。我认为您可以在那里毫无问题地获得 sessionID,即使经过一些研究,我也不知道该怎么做
    猜你喜欢
    • 1970-01-01
    • 2012-12-09
    • 1970-01-01
    • 1970-01-01
    • 2020-07-29
    • 2013-09-12
    • 1970-01-01
    • 2014-08-14
    • 1970-01-01
    相关资源
    最近更新 更多