Express session cookie 未在浏览器中设置
Express session cookie not being set in browser
我在尝试通过代理(最初是 NGINX,现在是 AWS ALB)实施 HTTPS 以保护与我的节点服务器的连接时遇到问题。我的 login
请求处理得很好,但是 login
之后的后续请求被标记为 isAuthenticated === false
,因此我的节点应用程序返回 401。
我知道 isAuthenticated === false
是由未在浏览器中设置 session cookie 引起的,但是我似乎无法弄清楚为什么没有设置 session cookie正在设置(或发送?)。
我正在配置 express-session 如下:
app.use(cookieParser('secret'));
app.set('trust proxy', 1);
// add & configure middleware
app.use(session({
name: 'session',
store: new redisStore(),
secret: 'secret',
resave: false,
saveUninitialized: false,
cookie: { httpOnly: true,
secure: true }
}));
我的节点应用程序位于 AWS Application Load Balancer 后面,它通过 HTTP 与应用程序通信,因此我将 trust proxy
配置为 1。
我的passport配置和本地攻略就在下面:
// configure passport.js to use the local strategy
passport.use(new LocalStrategy(
{ usernameField: 'email' },
(email, password, done) => {
mysql.getConnection((err, conn) => {
conn.query('SELECT u.user_id, u.email, u.password, o.uuid FROM user AS u INNER JOIN organization AS o ON o.id = u.org_id WHERE email = ?;', [email], ( err, rows ) => {
if (err) throw err;
if (rows.length !== 1)
return done(null, false, { message: 'User does not exist.\n' });
else if (!bcrypt.compareSync(password, rows[0].password))
return done(null, false, { message: 'Incorrect password.\n' });
else{
return done(null, {user_id: rows[0].user_id, email: email, uuid: rows[0].uuid});
}
});
conn.release();
});
}
));
来自反应客户端的请求是:
axios.post('https://sub.mydomain.com' + '/api/login', userObj, {withCredentials: true})
.then(res => {
if (res.status === 200) {
initUser(res.data, true);
}
else {
this.setState({errors: {password: 'Incorrect username or password'}})
this.props.history.push('/login');
}
})
.catch((e) => {
this.setState({errors: {password: 'Unable to login'}})
this.props.history.push('/login');
});
发出请求时,我收到了 200 状态码,其中包含我所期望的用户信息。请参阅下面 PostMan 的屏幕截图:
这些也是 Chrome 中的回复 headers:
access-control-allow-credentials: true
access-control-allow-origin: https://sub.mydomain.com
content-length: 89
content-type: text/html; charset=utf-8
date: Tue, 12 Mar 2019 07:49:45 GMT
etag: W/"59-T0xi+VpB6A/MLCHMb8Qz3Pq9dwc"
status: 200
vary: Origin
x-powered-by: Express
似乎 session cookie 无法从节点应用程序发送,或者在浏览器中设置。
我 运行 在我的本地机器上完全一样,并且在浏览器中设置 cookie 没问题。我的本地和服务器之间的唯一区别是节点应用程序前面的 ALB,我在本地设置 secure: false
(因为我没有使用 HTTPS)。
仅供参考 - 我最初尝试在我的服务器上使用 NGINX proxy_pass 来处理 HTTPS 连接,但遇到了同样的问题。在找不到 NGINX 解决方案后,我曾尝试删除代理通道并使用 AWS Application Load Balancer(我认为我的 NGINX 配置可能存在问题)。这让我相信问题出在 express-session 配置作为这里的共同点,但是我可能遗漏了其他东西。
仅供参考 2 - 我尝试将 trust proxy
设置为 true
、1
、2
、3
等,还尝试设置 secure
到 false
,还尝试将 httpOnly
设置为 false
- 以及上述的无数变体,但我似乎仍然没有在浏览器中获取 cookie。
仅供参考 3 - 我尝试删除代理并恢复到与 Node 应用程序的直接 HTTP 连接,但我仍然没有在我的浏览器(或 PostMan)中获取 cookie。
希望有人能指出我遗漏的问题,希望能解决这个问题。
提前致谢!
所以经过几天的调查,问题原来是我的 Redis 服务器已经终止并且无法重新启动。 捂脸
无法生成(或存储)sessionID,因为它无法连接到 Redis 存储以在服务器端保存会话信息。
启动 Redis 服务器立即解决了这个问题,但是如果 express/passport 有一些详细的日志记录来通知用户就更好了。
希望其他人觉得这有用!
我在尝试通过代理(最初是 NGINX,现在是 AWS ALB)实施 HTTPS 以保护与我的节点服务器的连接时遇到问题。我的 login
请求处理得很好,但是 login
之后的后续请求被标记为 isAuthenticated === false
,因此我的节点应用程序返回 401。
我知道 isAuthenticated === false
是由未在浏览器中设置 session cookie 引起的,但是我似乎无法弄清楚为什么没有设置 session cookie正在设置(或发送?)。
我正在配置 express-session 如下:
app.use(cookieParser('secret'));
app.set('trust proxy', 1);
// add & configure middleware
app.use(session({
name: 'session',
store: new redisStore(),
secret: 'secret',
resave: false,
saveUninitialized: false,
cookie: { httpOnly: true,
secure: true }
}));
我的节点应用程序位于 AWS Application Load Balancer 后面,它通过 HTTP 与应用程序通信,因此我将 trust proxy
配置为 1。
我的passport配置和本地攻略就在下面:
// configure passport.js to use the local strategy
passport.use(new LocalStrategy(
{ usernameField: 'email' },
(email, password, done) => {
mysql.getConnection((err, conn) => {
conn.query('SELECT u.user_id, u.email, u.password, o.uuid FROM user AS u INNER JOIN organization AS o ON o.id = u.org_id WHERE email = ?;', [email], ( err, rows ) => {
if (err) throw err;
if (rows.length !== 1)
return done(null, false, { message: 'User does not exist.\n' });
else if (!bcrypt.compareSync(password, rows[0].password))
return done(null, false, { message: 'Incorrect password.\n' });
else{
return done(null, {user_id: rows[0].user_id, email: email, uuid: rows[0].uuid});
}
});
conn.release();
});
}
));
来自反应客户端的请求是:
axios.post('https://sub.mydomain.com' + '/api/login', userObj, {withCredentials: true})
.then(res => {
if (res.status === 200) {
initUser(res.data, true);
}
else {
this.setState({errors: {password: 'Incorrect username or password'}})
this.props.history.push('/login');
}
})
.catch((e) => {
this.setState({errors: {password: 'Unable to login'}})
this.props.history.push('/login');
});
发出请求时,我收到了 200 状态码,其中包含我所期望的用户信息。请参阅下面 PostMan 的屏幕截图:
这些也是 Chrome 中的回复 headers:
access-control-allow-credentials: true
access-control-allow-origin: https://sub.mydomain.com
content-length: 89
content-type: text/html; charset=utf-8
date: Tue, 12 Mar 2019 07:49:45 GMT
etag: W/"59-T0xi+VpB6A/MLCHMb8Qz3Pq9dwc"
status: 200
vary: Origin
x-powered-by: Express
似乎 session cookie 无法从节点应用程序发送,或者在浏览器中设置。
我 运行 在我的本地机器上完全一样,并且在浏览器中设置 cookie 没问题。我的本地和服务器之间的唯一区别是节点应用程序前面的 ALB,我在本地设置 secure: false
(因为我没有使用 HTTPS)。
仅供参考 - 我最初尝试在我的服务器上使用 NGINX proxy_pass 来处理 HTTPS 连接,但遇到了同样的问题。在找不到 NGINX 解决方案后,我曾尝试删除代理通道并使用 AWS Application Load Balancer(我认为我的 NGINX 配置可能存在问题)。这让我相信问题出在 express-session 配置作为这里的共同点,但是我可能遗漏了其他东西。
仅供参考 2 - 我尝试将 trust proxy
设置为 true
、1
、2
、3
等,还尝试设置 secure
到 false
,还尝试将 httpOnly
设置为 false
- 以及上述的无数变体,但我似乎仍然没有在浏览器中获取 cookie。
仅供参考 3 - 我尝试删除代理并恢复到与 Node 应用程序的直接 HTTP 连接,但我仍然没有在我的浏览器(或 PostMan)中获取 cookie。
希望有人能指出我遗漏的问题,希望能解决这个问题。
提前致谢!
所以经过几天的调查,问题原来是我的 Redis 服务器已经终止并且无法重新启动。 捂脸
无法生成(或存储)sessionID,因为它无法连接到 Redis 存储以在服务器端保存会话信息。
启动 Redis 服务器立即解决了这个问题,但是如果 express/passport 有一些详细的日志记录来通知用户就更好了。
希望其他人觉得这有用!