快递不设置Cookie
Posted
技术标签:
【中文标题】快递不设置Cookie【英文标题】:Express not setting Cookie 【发布时间】:2020-02-19 17:34:21 【问题描述】:我有 2 台服务器。一个在 localhost:5555 上托管 next.js 应用程序,另一个在 localhost:4444 上托管 api 的快速服务器。
身份验证 api 返回一个 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没有设置。 用真实的域名试试,localhost
与存储、cookie、CORS 的交互效果很差,我记得也是依赖于浏览器的方式。通过hosts
或其他方式伪造一些127.0.0.1
域。编辑:在 Chrome 的情况下,它似乎是“wontfix”(***.com/questions/10883211/…)
请尝试将 127.0.0.1:5555 更改为 localhost:5555
【参考方案1】:
正如另一个答案中提到的,您不能在不同的域上设置 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 标头不是 *
之类的通配符时,凭据选项才有效我创建了一个server 来模仿您发布的代码。服务器基本上回显了请求 cookie。
可以通过这个stackblitz访问。您可以切换 withCredentials 标志以查看响应的差异
【讨论】:
【参考方案2】:您尝试做的事情绝对是可能的,问题是 cookie 不是特定于端口的:Are HTTP cookies port specific? 所以您应该指定域名但不指定端口。
如果你在自己的域上设置了一个Cookie(或者你根本没有指定它),所有后续的请求都会携带这个cookie,即使是由不同的端口发起的(仅当withCredentials
设置为@ 987654326@,不过)。另外请注意,如果设置,Cookie 的域必须与当前域或父域完全匹配(localhost
被认为与127.0.0.1
不同)
注意:这样做会在 Chrome 中显示以下警告:
与http://example.com/ 的跨站点资源关联的 cookie 设置时没有
SameSite
属性。 Chrome 的未来版本 如果设置了跨站点请求,则只会传递 cookie 与SameSite=None
和Secure
。您可以在开发人员中查看 cookie 应用程序>存储>Cookies下的工具,并在以下位置查看更多详细信息 https://www.chromestatus.com/feature/5088147346030592 和 https://www.chromestatus.com/feature/5633521622188032.
所以,为未来的网络标准准备你的代码!
【讨论】:
【参考方案3】:我在使用 nuxt.js 时遇到了类似的问题。要使用 express 在浏览器中设置 cookie,我建议使用库 Cookies
在我的例子中,我在 express 中设置了 cookie,如下所示:
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);
【讨论】:
【参考方案4】:您不能为其他域设置 cookie,因为这将是一个巨大的安全风险。
但是,如果您正在寻找一种在您的应用程序之间共享 cookie 的方法,那么您唯一的方法就是在这些应用程序之间共享一个域,或者通过 url 前缀将它们分开,或者将其中一个创建为其他应用程序的子域.
domain.com
和 api.domain.com
。这样,通过在您的 cookie 中指定 domain.com
,两个域都可以访问它
如果您关心自己的开发环境,可以在单域中使用nginx
和proxy_pass
这两个应用程序
【讨论】:
【参考方案5】:我设法通过如下设置我的 res.cookie 来解决服务器未设置浏览器 cookie 的问题
res.cookie("Test", "If you see this then it works", httpOnly: false, secure: true, sameSite: "none").json(message: "Finished");
我通过打开 chrome 开发工具、进入应用程序、cookie 和站点 URL 来检查是否设置了 cookie。
对于上面的代码,我有一些偏好。此方法仅适用于以 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);
);
【讨论】:
以上是关于快递不设置Cookie的主要内容,如果未能解决你的问题,请参考以下文章