NestJS 的 csrf 令牌无效
我想用 NestJS 和 Quasar 实现 Csrf 保护。 但我想我误解了一些东西...... 顺便说一句,我不做 SSR,所以我不会将表单从后面发送到视图。
这是 NestJs 后端代码:
async function bootstrap() {
const PORT = process.env.PORT;
const app = await NestFactory.create(AppModule, {
cors: true,
bodyParser: false,
});
console.log(`your App is listening on port ${PORT}`);
// Added Cookie-parser to user csurf packages
// Prevent CSRF attack
app.use(cookieParser());
app.use(csurf({ cookie: true }));
await app.listen(PORT);
}
bootstrap();
所以我只使用 CookieParser 和 csurf 包。 在我的登录页面上,我调用“csrf 端点”只是为了将 cookie 发送到视图,并通过 post 调用(登录)将其发送回来。 我仍然收到“无效的 csrf 令牌”和 CORS 错误,但不知道为什么......(请参见下面的屏幕),有什么建议可以让它发挥作用吗?
后端错误:
相同如果我因失眠而尝试请求,则会出错。 我认为 CSRF 令牌附加到“网络浏览器”以通过嵌套请求返回后端,那么为什么我仍然收到此错误? Insomnia 会根据正确的请求自动发送 cookie,因此令牌应该返回到后端。 有什么想法吗? 问候
编辑: 多次阅读文档后,似乎CSRF保护仅适用于SSR?无需使用 SPA 添加 csrf 安全性?任何人都可以确认吗?
编辑:这是另一项工作:
这里的目的是在登录之前发送请求以获取 csrf 令牌,我可以将其放入 cookie 中以便在使用 POST 方法登录时重新发送。
这是我的端点:
import { Controller, Get, Req, Res, HttpCode, Query } from "@nestjs/common";
@Controller("csrf")
export class SecurityController {
@Get("")
@HttpCode(200)
async getNewToken(@Req() req, @Res() res) {
const csrfToken = req.csrfToken();
res.send({ csrfToken });
}
}
这是我在 main.ts 文件中所做的事情(我将在下面解释):
async function bootstrap() {
const PORT = process.env.PORT;
const app = await NestFactory.create(AppModule, {
cors: {
origin: "*",
methods: ["GET,HEAD,OPTIONS,POST,PUT"],
allowedHeaders: [
"Content-Type",
"X-CSRF-TOKEN",
"access-control-allow-methods",
"Access-Control-Allow-Origin",
"access-control-allow-credentials",
"access-control-allow-headers",
],
credentials: true,
},
bodyParser: false,
});
app.use(cookieParser());
app.use(csurf({ cookie: true }));
console.log(`your App is listening on port ${PORT}`);
await app.listen(PORT);
}
bootstrap();
这里是我的 VueJS 前端中请求的 axiosInstance 拦截器:
axiosInstance.interceptors.request.use(
(req) => {
const token = Cookies.get('my_cookie')
if (token) {
req.headers.common['Authorization'] = 'Bearer ' + token.access_token
}
req.headers['Access-Control-Allow-Origin'] = '*'
req.headers['Access-Control-Allow-Credentials'] = 'true'
req.headers['Access-Control-Allow-Methods'] = 'GET,HEAD,OPTIONS,POST,PUT'
req.headers['Access-Control-Allow-Headers'] =
'access-control-allow-credentials,access-control-allow-headers,access-control-allow-methods,access-control-allow-origin,content-type,x-csrf-token'
const csrfToken = Cookies.get('X-CSRF-TOKEN')
if (csrfToken) {
req.headers['X-CSRF-TOKEN'] = csrfToken
console.log(req)
}
return req
},
(err) => {
console.log(err)
},
这里的回复也是如此:
axiosInstance.interceptors.response.use(
(response) => {
if (response?.data?.csrfToken) {
const {
data: { csrfToken },
} = response
Cookies.set('X-CSRF-TOKEN', csrfToken)
}
return response
},
在我的登录名中我调用我的登录组件的已安装函数:
async mounted() {
const result = await securityService.getCsrf()
},
现在解释一下:
正如我所说,我不是在构建 SSR 项目,这就是为什么我想将令牌发送到经典的 axios 响应并将其存储在一个 Cookie(这部分是为了测试我听说将 csrf 令牌存储到经典 cookie 中不是正确的方法。) 对于下一个请求,我获取 csrf 令牌并将其“附加”到请求的标头中,使我的标头成为“自定义”。 这是一个问题,我不知道如何使自定义标头与 NestJS 和 CORS 一起使用,这就是为什么我在 NestJS 中尝试使用 CORS 选项进行很多操作,并在请求转到后端之前编写一些自定义标头,但没有成功,我收到相同的错误消息:
我对这个问题有点困惑,CORS/CSRF 对于 spa 来说是一件大事,我的问题仍然相同,使用 CORS 和 SameSite cookie 属性,并且我的 api 位于我前端的子域中,是否真的有必要制作反 csrf 模式?
顺便说一句,我怎样才能使我的自定义标头正常工作以及为什么 CORS 对我说没有“Access-Control-Allow-Origin”标头,但有:
I would like to implement Csrf protection with NestJS and Quasar.
But I think I misunderstand something...
btw I'm not doing SSR, so I don't send the form from the back to the view.
Here is the NestJs back-end code:
async function bootstrap() {
const PORT = process.env.PORT;
const app = await NestFactory.create(AppModule, {
cors: true,
bodyParser: false,
});
console.log(`your App is listening on port ${PORT}`);
// Added Cookie-parser to user csurf packages
// Prevent CSRF attack
app.use(cookieParser());
app.use(csurf({ cookie: true }));
await app.listen(PORT);
}
bootstrap();
So I'm just using CookieParser and csurf package.
On my login page I call a "csrf endpoint" just to send a cookie to the view, to send it back with the post call (login).
I still get the "invalid csrf token" AND a CORS error and don't know why....(see screen below), any suggestions to make it works ?
When I try to login, error in the browser:
And error in the back-end:
Same error if I try a request with insomnia.
I thought that the CSRF token is attached to the "web browser" to go back to the back-end with nest request, so why I'm still getting this error ?
Insomnia send the cookie automatically with the right request so the token should go back to the back-end.
Any idea ?
Regards
EDIT:
After many times reading docs, It seems that CSRF protection is for SSR only ? No need to add csrf security with SPA ? Could anyone can confirm ?
EDIT: Here's another work:
The purpose here is to send a request before login to get a csrf token that I can put into a cookie to resend when I login with a POST method.
Here is my endpoint:
import { Controller, Get, Req, Res, HttpCode, Query } from "@nestjs/common";
@Controller("csrf")
export class SecurityController {
@Get("")
@HttpCode(200)
async getNewToken(@Req() req, @Res() res) {
const csrfToken = req.csrfToken();
res.send({ csrfToken });
}
}
Here is what I've done into my main.ts file (I'll explain below):
async function bootstrap() {
const PORT = process.env.PORT;
const app = await NestFactory.create(AppModule, {
cors: {
origin: "*",
methods: ["GET,HEAD,OPTIONS,POST,PUT"],
allowedHeaders: [
"Content-Type",
"X-CSRF-TOKEN",
"access-control-allow-methods",
"Access-Control-Allow-Origin",
"access-control-allow-credentials",
"access-control-allow-headers",
],
credentials: true,
},
bodyParser: false,
});
app.use(cookieParser());
app.use(csurf({ cookie: true }));
console.log(`your App is listening on port ${PORT}`);
await app.listen(PORT);
}
bootstrap();
And here my axiosInstance Interceptors of the request in my VueJS frontend:
axiosInstance.interceptors.request.use(
(req) => {
const token = Cookies.get('my_cookie')
if (token) {
req.headers.common['Authorization'] = 'Bearer ' + token.access_token
}
req.headers['Access-Control-Allow-Origin'] = '*'
req.headers['Access-Control-Allow-Credentials'] = 'true'
req.headers['Access-Control-Allow-Methods'] = 'GET,HEAD,OPTIONS,POST,PUT'
req.headers['Access-Control-Allow-Headers'] =
'access-control-allow-credentials,access-control-allow-headers,access-control-allow-methods,access-control-allow-origin,content-type,x-csrf-token'
const csrfToken = Cookies.get('X-CSRF-TOKEN')
if (csrfToken) {
req.headers['X-CSRF-TOKEN'] = csrfToken
console.log(req)
}
return req
},
(err) => {
console.log(err)
},
Here the same for repsonse:
axiosInstance.interceptors.response.use(
(response) => {
if (response?.data?.csrfToken) {
const {
data: { csrfToken },
} = response
Cookies.set('X-CSRF-TOKEN', csrfToken)
}
return response
},
And inside my login I make a call on the mounted function of my login component:
async mounted() {
const result = await securityService.getCsrf()
},
So now to explain:
As I said I'm not building a SSR project, that's why I want to send the token into a classic axios reponse and store it in a Cookie (this part is for test I heard that storing a csrf token into a classic cookie is not the right way.)
And for each next request I get the csrf token and "attach" it to the request into the headers, making my headers "custom".
Here is a problem I don't know how to make custom headers works with nestJS and CORS, that's why I try many thing with CORS options in NestJS and writte some custome header before the request go to the back-end but without success, I've got the same error message:
I'm a bit confuse about this problem and CORS/CSRF is a big deal for spa, my questions still the same, with CORS and SameSite cookie attributes, and my api is in a subdomain of my front-end, is it really necessary to make a anti-csrf pattern ?
Btw how can I make my custom headers working and why CORS say to me there is no "Access-Control-Allow-Origin" header but there is:
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
尝试生成 csrf 令牌并传递到每个请愿书
的前面: https:// github.com/nestjs/nest/issues/6552#issuecomment-1175270849
try to generate csrf token and pass to front on each petition
from: https://github.com/nestjs/nest/issues/6552#issuecomment-1175270849