当授权socket.io连接时,Google App引擎会删除会话Cookie

时间:2019-04-13 20:11:18

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

当用户打开WebSocket连接时,我试图从express-session中获取用户的sessionID。下面的代码显示了如何完成此操作。问题是,当我将服务器部署到Google App Engine时,在授权套接字连接时不再能看到会话cookie。在本地运行时,它可以正常工作,因此Google App引擎必须在做某些事情才能删除Cookie?我不太熟悉Google App引擎,因此不胜感激。

我尝试了许多从网上找到的解决方案,例如npm的passport.socketio,我相信其中许多实现了最终写给自己的解决方案。

编辑1:

更具体地说,data.headers.cookies从本地主机运行时包含一个ioconnect.sidexpress.sid cookie。在google app引擎上运行时,它仅包含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,但在Google App Engine上为null。

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

1 个答案:

答案 0 :(得分:0)

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

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

network:
  name: default

不幸的是,您似乎无法在标准环境中使用它,因此我还必须进行更改:

runtime: nodejs
env: flex

切换到灵活环境时,还需要在package.json中指定引擎。

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