如何允许快速后端 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,但您可以通过不同的方式对其进行编辑:
same-site:'None'
。 Express has a way to do so explaind on its docs。请记住,当 cookie 未标记为 Secure
时,浏览器也有一个新策略来忽略 same-site:'None'
,这需要使用 HTTPS
(我想如果你想检查这个行为可以在你的浏览器设置中编辑使用HTTP
)。
显然,任何要求用户更改浏览器设置的策略都是行不通的,因此same-site:'None'
必须运行HTTPS
和Secure
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 并设置allowedHeaders
和origin
,如下所示,
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:GUI 中的无限滚动分页,但允许搜索所有条目
如何使用 Advanced REST Client 或 Postman 测试 Express/node REST API 后端?