如何允许快速后端 REST API 在使用 axios 的反应前端中设置 cookie?

Posted

技术标签:

【中文标题】如何允许快速后端 REST API 在使用 axios 的反应前端中设置 cookie?【英文标题】:How to allow express backend REST API to set cookie in a react frontend which is using axios? 【发布时间】:2021-04-15 17:05:26 【问题描述】:

后端

我正在尝试使基于 JWT cookie 的身份验证工作。我目前正在执行以下 cookie 设置,作为后端 API 中登录路由的一部分。

res.cookie('authCookie', token, maxAge: 900000, httpOnly: true);

稍后当我验证任何其他请求时,我会读取此 cookie 并在 passport-jwt 策略中对其进行测试。

我在邮递员中完成了这项工作 - 当我执行登录并访问安全路由时 - 它工作得非常好 + cookie 也在邮递员中设置。

前端

现在,我在前端执行以下调用堆栈只是为了测试工作,

axios.post("http://localhost:3001/login", logInParams, config)
    .then(result => 
        // User is logged in so push them to the  respective dashboard
        console.log(result);
        axios.get("http://localhost:3001/user/profile")
            .then(result => 
                console.log(result);
            )
            .catch(err => 
                console.log(err);
                return;
            )
    )
    .catch(err => 
        console.log(err)
        return;
    );

所以基本上,我让用户登录并且工作得非常好 - 我得到了预期的 JSON 响应,但是调用应该设置一个它不是的 cookie,因此下一个 axios.get 调用没有返回成功地。尽管出于某种原因,我看到了session cookie 和CSRF cookie。只有这个 authCookie 或 jwt-cookie 没有设置。

一些额外的细节

我正在使用带有默认参数的 cors - 这可能是一个错误吗?或者我对 axios 有什么改变吗?我已经看到了一些答案,并且对 MERN 很陌生,我并不真正了解它们。有人知道或经历过并解决了吗?

【问题讨论】:

【参考方案1】:

我认为你应该在 res.cookie('authCookie', token, maxAge: 900000, httpOnly: true) 的末尾写 send('cookies are set');

【讨论】:

我不确定这会有什么帮助。能不能说的清楚一点? 我的意思是你不向客户端发送响应【参考方案2】:

您是否从与提供客户端的端口不同的端口运行服务器(即:在localhost:3000 上运行的 webpack-dev-server 和在localhost:3001 上的 Express 服务器)?这看起来像 same-site cookie 问题。在某些浏览器的最新版本中,例如 Chrome cookie 设置被阻止,当这个来自不同的源站点时。这是出于安全考虑;你可以了解更多关于同站点cookieshere。

浏览器中所做的更改与它们赋予名为same-site 的cookie 策略属性的默认值有关。旧的解决方法是默认将来自不同来源的所有 cookie 视为None,但去年它更改为将same-site 策略视为Lax,而服务器未明确提供same-site 策略。这是浏览器的理想行为,因为它有助于防止第三方网站使用服务器提供的 cookie,但您可以通过不同的方式对其进行编辑:

更改浏览器设置的默认同站点策略(有关同站点 cookie 的文章解释)。 从服务器发送same-site:'None'。 Express has a way to do so explaind on its docs。请记住,当 cookie 未标记为 Secure 时,浏览器也有一个新策略来忽略 same-site:'None',这需要使用 HTTPS(我想如果你想检查这个行为可以在你的浏览器设置中编辑使用HTTP)。

显然,任何要求用户更改浏览器设置的策略都是行不通的,因此same-site:'None' 必须运行HTTPSSecure cookie。

您总是有使浏览器和客户端同源的方法,因此same-site 不会有任何问题(即 Express 服务器返回您的客户端生产版本的 index.html 作为其主要静态)。我还没有找到任何方法可以将 CORS 模块配置为具有默认的相同站点 cookie 策略(或将其单独用作中间件来更改它),可能不是它的目的,但您可以通过 adding a dynamic origin config 尝试。

据我所见,Postman does not support the same-site cookie property yet,这可以解释为什么它可以在 Postman 上运行,但不能在浏览器上运行。

【讨论】:

嗨!我已经想通了。感谢您的帮助 【参考方案3】:

从外观上看 - 这似乎是 cors 工作方式的问题,我添加以下答案以帮助其他任何人遇到它。稍后谢谢我:)

服务器端

您的服务器中将有一个如下所示的 cors,

app.use(cors());

您必须将credentials 设置为true 并设置allowedHeadersorigin,如下所示,

app.use(cors(
    credentials: true,
    allowedHeaders: ['Content-Type', 'Authorization'],
    origin: ['http://localhost:3000']
));

这是因为如果服务器和客户端在同一个端口,通常不允许在浏览器中设置 cookie。要在服务器端处理此问题。

客户端

我们还必须在发送请求时传递 cookie,并使用 axios 执行此操作,只需在您的 react 应用程序的 index.js 中添加以下内容,

axios.defaults.withCredentials = true;

【讨论】:

以上是关于如何允许快速后端 REST API 在使用 axios 的反应前端中设置 cookie?的主要内容,如果未能解决你的问题,请参考以下文章

如何确保请求从固定页面命中 REST api?

Swagger rest API 描述

REST API:GUI 中的无限滚动分页,但允许搜索所有条目

如何使用 Advanced REST Client 或 Postman 测试 Express/node REST API 后端?

如何仅使用 Sails.js 的 REST API 作为混合 HTML5 应用程序的后端

Magento的REST API URL