表示没有设置Cookie
Express not setting Cookie
我有2台服务器。一个在 localhost:5555 上托管 next.js 应用程序,另一个在 localhost:4444 上托管 api 的快速服务器.
身份验证 api returns 一个 cookie 但是这没有在 localhost:5555 上的浏览器 运行 中设置。
res.cookie('cokkieName', 'bob', {
domain: '127.0.0.1:5555',
maxAge: 900000,
httpOnly: true,
});
res.status(200).json({
session: jwtSigned,
role: 'default',
});
我的 cors 设置是:
const options: cors.CorsOptions = {
allowedHeaders: ['Origin', 'X-Requested-With', 'Content-Type', 'Accept', 'X-Access-Token', 'Authorization'],
credentials: true,
methods: 'GET,HEAD,OPTIONS,PUT,PATCH,POST,DELETE',
origin: 'http://localhost:5555',
preflightContinue: false,
};
我更愿意使用 api 设置 cookie,而不是通过 next.js。
我试过交替使用 cors 设置,但没有成功。客户端调用使用 axios 并设置了 withCredentials
。
您尝试做的事情绝对是可能的,问题是 cookie 不是特定于端口的: 所以您应该指定一个域名而不是端口。
如果你在自己的域上设置了一个Cookie(或者你根本不指定),所有后续的请求即使是由不同的端口发起的也会携带这个cookie(仅当withCredentials
设置为 true
,不过)。另请注意,如果设置,Cookie 的域必须与当前域或父域完全匹配(localhost
被认为不同于 127.0.0.1
)
注意:这样做会在Chrome中显示以下警告:
A cookie associated with a cross-site resource at http://example.com/
was set without the SameSite
attribute. A future release of Chrome
will only deliver cookies with cross-site requests if they are set
with SameSite=None
and Secure
. You can review cookies in developer
tools under Application>Storage>Cookies and see more details at
https://www.chromestatus.com/feature/5088147346030592 and
https://www.chromestatus.com/feature/5633521622188032.
所以,为未来的网络标准准备你的代码!
我遇到了与 nuxt.js 类似的问题。要使用 express 在浏览器中设置 cookie,我建议使用库 Cookies
在我的例子中,我像这样在 express 中设置 cookies:
setResponseCookie(req, res, token, strategyName) {
const isHttps = req.protocol === 'https';
let { cookie: { maxAge } } = config;
const cookieSettings = isHttps => ({
maxAge,
httpOnly: true,
secure: isHttps,
});
const cookies = new Cookies(req, res);
cookies.set('auth.strategy', strategyName, cookieSettings(isHttps))
cookies.set('auth.token', token, cookieSettings(isHttps))
}
然后在快速路线中,您可以像这样添加:
let token = sign(user);
this.setResponseCookie(req, res, token, 'local-login')
res.json({ token, status: 'success' });
或
let token = sign(req.user);
this.setResponseCookie(req, res, token, 'google')
res.redirect(config.client.url);
您不能为其他域设置 cookie,因为那将是一个巨大的安全风险。
但是,如果您正在寻找一种在您的应用程序之间共享 cookie 的方法,那么您唯一的方法就是在这些应用程序之间共享一个域,通过 url 前缀将它们分开或创建一个它们作为其他的子域。
domain.com
和 api.domain.com
。这样,通过在您的 cookie 中指定 domain.com
,两个域都可以访问它
如果你担心自己的开发环境,可以在单域中使用Nginx
和proxy_pass
这两个应用程序
如其他答案中所述,您不能在不同的域上设置 cookie,因为这可能存在安全风险。
但是从你的问题来看...
由于 API 服务器是 运行 身份验证逻辑,cookie 应该设置在 API 服务器域,而不是客户端域
因此在您的 API 服务器中,您可以将代码更改为
res.cookie('cokkieName', 'bob', {
domain: '127.0.0.1:4444',
maxAge: 900000,
httpOnly: true,
});
或者只删除域,因为它默认为服务器域。
res.cookie('cokkieName', 'bob', {
maxAge: 900000,
httpOnly: true,
});
由于您在 localhost:5555 上有一个客户端 运行 并且在 localhost:4444 上有一个 API 服务器 运行,这是一个跨域调用,您需要通过withCredentials
选项 axios
以传递 cookie。您可能无法在浏览器中看到 cookie,因为它可能存在安全风险,但可以在服务器控制台上回显 cookie 值。
axios.get("url",{
withCredentials: true
}).then(res => {
console.log(res);
});
请注意,凭据选项仅在 Access-Control-Allow-Origin header 不是像 *
这样的通配符时才有效
我创建了一个 server 来模仿您发布的代码。服务器基本上回显了请求cookie。
可以通过这个stackblitz访问。您可以切换 withCredentials 标志以查看响应的差异
我通过如下设置 res.cookie 来解决服务器未设置浏览器 cookie 的问题
res.cookie("Test", "If you see this then it works", {httpOnly: false, secure: true, sameSite: "none"}).json({message: "Finished"});
我通过打开 chrome 开发工具检查是否设置了 cookie,转到应用程序,然后是 cookie,然后是站点 URL。
关于上面的代码,我想优先考虑一些事情。此方法仅适用于以 https 开头的 URL,这意味着如果在像 http://localhost:3000 这样的 URL 上,它将无法解决问题。我不知道 httpOnly 是真还是假是否重要。此外,以这种方式设置 cookie 时需要传入属性 secure: true, sameSite: "none"
。将这些值传递给 res.cookie 最终为我解决了这个问题。我还没有在任何地方看到这个解决方案,所以我决定让你知道。
我从 API 获取数据并触发服务器设置浏览器 cookie 的代码对于任何感兴趣的人来说都是这样的。
fetch(domain.com/testSetCookie', {
method: 'get',
mode: "cors",
credentials: 'include' //<-- important
})
.then((res) => {
//console.log(res);
return; //res.json();
})
.then((data) => {
console.log(data);));
})
.catch((err) => {
console.log("an error happeoned");
console.log(err);
});
我有2台服务器。一个在 localhost:5555 上托管 next.js 应用程序,另一个在 localhost:4444 上托管 api 的快速服务器.
身份验证 api returns 一个 cookie 但是这没有在 localhost:5555 上的浏览器 运行 中设置。
res.cookie('cokkieName', 'bob', {
domain: '127.0.0.1:5555',
maxAge: 900000,
httpOnly: true,
});
res.status(200).json({
session: jwtSigned,
role: 'default',
});
我的 cors 设置是:
const options: cors.CorsOptions = {
allowedHeaders: ['Origin', 'X-Requested-With', 'Content-Type', 'Accept', 'X-Access-Token', 'Authorization'],
credentials: true,
methods: 'GET,HEAD,OPTIONS,PUT,PATCH,POST,DELETE',
origin: 'http://localhost:5555',
preflightContinue: false,
};
我更愿意使用 api 设置 cookie,而不是通过 next.js。
我试过交替使用 cors 设置,但没有成功。客户端调用使用 axios 并设置了 withCredentials
。
您尝试做的事情绝对是可能的,问题是 cookie 不是特定于端口的: 所以您应该指定一个域名而不是端口。
如果你在自己的域上设置了一个Cookie(或者你根本不指定),所有后续的请求即使是由不同的端口发起的也会携带这个cookie(仅当withCredentials
设置为 true
,不过)。另请注意,如果设置,Cookie 的域必须与当前域或父域完全匹配(localhost
被认为不同于 127.0.0.1
)
注意:这样做会在Chrome中显示以下警告:
A cookie associated with a cross-site resource at http://example.com/ was set without the
SameSite
attribute. A future release of Chrome will only deliver cookies with cross-site requests if they are set withSameSite=None
andSecure
. You can review cookies in developer tools under Application>Storage>Cookies and see more details at https://www.chromestatus.com/feature/5088147346030592 and https://www.chromestatus.com/feature/5633521622188032.
所以,为未来的网络标准准备你的代码!
我遇到了与 nuxt.js 类似的问题。要使用 express 在浏览器中设置 cookie,我建议使用库 Cookies
在我的例子中,我像这样在 express 中设置 cookies:
setResponseCookie(req, res, token, strategyName) {
const isHttps = req.protocol === 'https';
let { cookie: { maxAge } } = config;
const cookieSettings = isHttps => ({
maxAge,
httpOnly: true,
secure: isHttps,
});
const cookies = new Cookies(req, res);
cookies.set('auth.strategy', strategyName, cookieSettings(isHttps))
cookies.set('auth.token', token, cookieSettings(isHttps))
}
然后在快速路线中,您可以像这样添加:
let token = sign(user);
this.setResponseCookie(req, res, token, 'local-login')
res.json({ token, status: 'success' });
或
let token = sign(req.user);
this.setResponseCookie(req, res, token, 'google')
res.redirect(config.client.url);
您不能为其他域设置 cookie,因为那将是一个巨大的安全风险。
但是,如果您正在寻找一种在您的应用程序之间共享 cookie 的方法,那么您唯一的方法就是在这些应用程序之间共享一个域,通过 url 前缀将它们分开或创建一个它们作为其他的子域。
domain.com
和 api.domain.com
。这样,通过在您的 cookie 中指定 domain.com
,两个域都可以访问它
如果你担心自己的开发环境,可以在单域中使用Nginx
和proxy_pass
这两个应用程序
如其他答案中所述,您不能在不同的域上设置 cookie,因为这可能存在安全风险。
但是从你的问题来看...
由于 API 服务器是 运行 身份验证逻辑,cookie 应该设置在 API 服务器域,而不是客户端域
因此在您的 API 服务器中,您可以将代码更改为
res.cookie('cokkieName', 'bob', {
domain: '127.0.0.1:4444',
maxAge: 900000,
httpOnly: true,
});
或者只删除域,因为它默认为服务器域。
res.cookie('cokkieName', 'bob', {
maxAge: 900000,
httpOnly: true,
});
由于您在 localhost:5555 上有一个客户端 运行 并且在 localhost:4444 上有一个 API 服务器 运行,这是一个跨域调用,您需要通过withCredentials
选项 axios
以传递 cookie。您可能无法在浏览器中看到 cookie,因为它可能存在安全风险,但可以在服务器控制台上回显 cookie 值。
axios.get("url",{
withCredentials: true
}).then(res => {
console.log(res);
});
请注意,凭据选项仅在 Access-Control-Allow-Origin header 不是像 *
这样的通配符时才有效我创建了一个 server 来模仿您发布的代码。服务器基本上回显了请求cookie。
可以通过这个stackblitz访问。您可以切换 withCredentials 标志以查看响应的差异
我通过如下设置 res.cookie 来解决服务器未设置浏览器 cookie 的问题
res.cookie("Test", "If you see this then it works", {httpOnly: false, secure: true, sameSite: "none"}).json({message: "Finished"});
我通过打开 chrome 开发工具检查是否设置了 cookie,转到应用程序,然后是 cookie,然后是站点 URL。
关于上面的代码,我想优先考虑一些事情。此方法仅适用于以 https 开头的 URL,这意味着如果在像 http://localhost:3000 这样的 URL 上,它将无法解决问题。我不知道 httpOnly 是真还是假是否重要。此外,以这种方式设置 cookie 时需要传入属性 secure: true, sameSite: "none"
。将这些值传递给 res.cookie 最终为我解决了这个问题。我还没有在任何地方看到这个解决方案,所以我决定让你知道。
我从 API 获取数据并触发服务器设置浏览器 cookie 的代码对于任何感兴趣的人来说都是这样的。
fetch(domain.com/testSetCookie', {
method: 'get',
mode: "cors",
credentials: 'include' //<-- important
})
.then((res) => {
//console.log(res);
return; //res.json();
})
.then((data) => {
console.log(data);));
})
.catch((err) => {
console.log("an error happeoned");
console.log(err);
});