Node.js、Angular、express-session:Chrome 80 不保存会话,因为 cookie 策略(sameSite cookie)

jon*_*ola 6 session-cookies node.js express express-session samesite

我有一个 Node.js,Angular 应用程序。(用 TypeScript 编写的 Node.js 服务器)。Node.js 服务器在 Amazon EC-2 实例上运行,Angular 客户端在另一台服务器上。

对于登录会话,我使用 express-session。我没有在应用程序中使用 cookie,所以我认为问题在于快速会话 cookie。 在 Firefox 上它可以正常工作,但在 Google Chrome (80.0.3987.149) 上它不起作用:Chrome 不保存会话(所以我不能离开登录页面)并警告:

http://addressof.myserverapp.com/上的跨站点资源关联的 cookie设置为没有该SameSite属性。它已被阻止,因为 Chrome 现在仅在设置了SameSite=None和 的情况下才提供具有跨站点请求的 cookie Secure。您可以在应用程序>存储>Cookies 下的开发人员工具中查看 cookie,并在https://www.chromestatus.com/feature/5088147346030592https://www.chromestatus.com/feature/5633521622188032 上查看更多详细信息。

在 Node.js 服务器中,我以这种方式设置了 express-sessions:

import cookieParser from 'cookie-parser';
app.use(cookieParser(secret));

app.use(session({
    secret: secret,
    resave: false,
    saveUninitialized: false,
    cookie: {
        httpOnly: false,
        maxAge: null,
        secure: true,
        sameSite: 'none'
    },
    store: sessionStore // MySqlStore - express-mysql-session
}));
Run Code Online (Sandbox Code Playgroud)

我也尝试用这个代码片段解决这个问题(来自https://github.com/expressjs/session/issues/725#issuecomment-605922223

Object.defineProperty(session.Cookie.prototype, 'sameSite', {
    // sameSite cannot be set to `None` if cookie is not marked secure
    get() {
        return this._sameSite === 'none' && !this.secure ? 'lax' : this._sameSite;
    },
    set(value) {
        this._sameSite = value;
    }
});
Run Code Online (Sandbox Code Playgroud)

服务器 npm 包:

"cors": "^2.8.5",
"cookie-parser": "^1.4.5",
"express": "^4.17.1",
"express-mysql-session": "^2.1.3",
"express-session": "^1.17.0",
Run Code Online (Sandbox Code Playgroud)
Npm version: 6.13.4
Node version: 12.16.1
Run Code Online (Sandbox Code Playgroud)

我花了几天的时间解决这个问题来弄清楚我做错了什么......

dav*_*d_p 0

这里的问题是,您正在通过 HTTP 访问网站,但 cookiesecure设置为true,这意味着它只会通过 HTTPS 发送。

如果你设置secure: falseexpress-sessioncookie 选项,它将起作用:

import cookieParser from 'cookie-parser';
app.use(cookieParser(secret));

app.use(session({
    secret: secret,
    resave: false,
    saveUninitialized: false,
    cookie: {
        httpOnly: false,
        maxAge: null,
        // allow the cookie to be sent via HTTP ("true" means "HTTPS only)
        secure: false, 
        sameSite: 'lax'
    },
    store: sessionStore
}));
Run Code Online (Sandbox Code Playgroud)

  • `secure: false` 不适用于 Chrome 80+ 中的 `sameSite: 'none'` (2认同)