快递不设置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=NoneSecure。您可以在开发人员中查看 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.comapi.domain.com。这样,通过在您的 cookie 中指定 domain.com,两个域都可以访问它

如果您关心自己的开发环境,可以在单域中使用nginxproxy_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的主要内容,如果未能解决你的问题,请参考以下文章

小程序商城后台如何连接快递服务?

电商电子面单设置-快递鸟API接口

cookies不设置过期时间默认是永远不过期吗

javascript 快递js - 设置

设置cookie,获取cookie,删除cookie

c++cef禁止cookie设置