如何从 CSRF 中间件中排除端点
How to exclude an endpoint from CSRF middleware
请参阅下面的更新...
我的 React 前端能够调用我的 Node 后端 API。但是,当外部站点调用我的 API 时,它会收到错误消息。如果我注释掉设置的 CSRF 部分(5 行),那么第 3 方服务就可以调用我的 API.
const express = require("express");
const cookieParser = require("cookie-parser");
const csurf = require("csurf");
var cors = require("cors");
var corsOptions = {
origin: process.env.CORS_ORIGIN_URL.split(","),
credentials: true,
exposedHeaders: ["set-cookie"],
};
app.use(cors(corsOptions));
app.use(
cookieParser(process.env.COOKIE_SECRET, {
sameSite: true,
httpOnly: true,
secure: process.env.NODE_ENV === "production",
maxAge: process.env.COOKIE_MAX_AGE,
})
);
// If I comment out the next 5 lines, 3rd party services CAN call upon my API
app.use(csurf({ cookie: true }));
app.use(function (req, res, next) {
res.cookie("XSRF-TOKEN", req.csrfToken());
next();
});
app.use("/api/csrf", (req, res) => {
return res.status(200).json({
status: true,
csrfToken: req.csrfToken(),
});
});
app.use("/api", api);
更新
我想根据请求的路由(见下文)将 CSRF 配置包装在 if-else 语句中。这似乎可行,但这是正确且安全的设置吗?
var csrf = csurf({ cookie: true });
app.use(function (req, res, next) {
// skip csrf for certain routes
if (req.url === '/api/mollie_webhook') {
return next();
} else {
app.use(csrf);
// Is this allowed? Since we already have app.use 4 lines up, but don't know how else to do this...
app.use(function (req, res, next) {
res.cookie("XSRF-TOKEN", req.csrfToken());
next();
});
app.use("/api/csrf", (req, res) => {
return res.status(200).json({
status: true,
csrfToken: req.csrfToken(),
});
});
next();
}
});
app.use("/api", api);
这不是 CSRF 保护的目的。 CSRF 保护是为了防止直接 posting 数据到您的站点。换句话说,客户端实际上必须 post 通过批准的路径,例如将数据填写到表单并提交。
因此 api 将排除 Csrf,因为其目的通常是允许第 3 方实体访问和修改您网站上的数据。因此,作为一项规则,任何 API 视图都不应该使用 CSRF。您可以通过各种方式保护您的端点,例如 oauth,还有其他最佳实践
实现您想要的效果的最简单方法是在添加 CSRF 中间件之前声明 Web Hook 路由。
但是,您可以有条件地应用 CSRF 保护,方法是直接跳到特定忽略路由上的 next
中间件。
您还需要在 webhook 路由上启用 CORS 以允许来自远程服务器的传入请求。
const express = require('express');
const cors = require('cors');
const csurf = require('csurf');
const cookies = require('cookie-parser');
const app = express();
const shared = cors({
origin: 'https://api.mollie.com',
methods: 'POST'
});
const protect = csurf({ cookie: true });
const ignore = [ '/api/webhook' ];
app.use(cookies(process.env.COOKIE_SECRET, {
sameSite: true, httpOnly: true,
secure: process.env.NODE_ENV === "production",
maxAge: process.env.COOKIE_MAX_AGE,
}));
app.use((req, res, next) => {
if (ignore.includes(req.url)) {
next();
} else {
protect(req, res, next);
}
});
app.use((req, res, next) => {
if (req.csrfToken) {
res.cookie("XSRF-TOKEN", req.csrfToken());
} next();
});
app.use('/api/webhook', shared, (req, res) => {
res.sendStatus(200);
});
app.use("/api/csrf", (req, res) => {
res.json({
status: true,
csrfToken: req.csrfToken(),
});
});
app.listen(process.env.PORT);
请参阅下面的更新...
我的 React 前端能够调用我的 Node 后端 API。但是,当外部站点调用我的 API 时,它会收到错误消息。如果我注释掉设置的 CSRF 部分(5 行),那么第 3 方服务就可以调用我的 API.
const express = require("express");
const cookieParser = require("cookie-parser");
const csurf = require("csurf");
var cors = require("cors");
var corsOptions = {
origin: process.env.CORS_ORIGIN_URL.split(","),
credentials: true,
exposedHeaders: ["set-cookie"],
};
app.use(cors(corsOptions));
app.use(
cookieParser(process.env.COOKIE_SECRET, {
sameSite: true,
httpOnly: true,
secure: process.env.NODE_ENV === "production",
maxAge: process.env.COOKIE_MAX_AGE,
})
);
// If I comment out the next 5 lines, 3rd party services CAN call upon my API
app.use(csurf({ cookie: true }));
app.use(function (req, res, next) {
res.cookie("XSRF-TOKEN", req.csrfToken());
next();
});
app.use("/api/csrf", (req, res) => {
return res.status(200).json({
status: true,
csrfToken: req.csrfToken(),
});
});
app.use("/api", api);
更新
我想根据请求的路由(见下文)将 CSRF 配置包装在 if-else 语句中。这似乎可行,但这是正确且安全的设置吗?
var csrf = csurf({ cookie: true });
app.use(function (req, res, next) {
// skip csrf for certain routes
if (req.url === '/api/mollie_webhook') {
return next();
} else {
app.use(csrf);
// Is this allowed? Since we already have app.use 4 lines up, but don't know how else to do this...
app.use(function (req, res, next) {
res.cookie("XSRF-TOKEN", req.csrfToken());
next();
});
app.use("/api/csrf", (req, res) => {
return res.status(200).json({
status: true,
csrfToken: req.csrfToken(),
});
});
next();
}
});
app.use("/api", api);
这不是 CSRF 保护的目的。 CSRF 保护是为了防止直接 posting 数据到您的站点。换句话说,客户端实际上必须 post 通过批准的路径,例如将数据填写到表单并提交。
因此 api 将排除 Csrf,因为其目的通常是允许第 3 方实体访问和修改您网站上的数据。因此,作为一项规则,任何 API 视图都不应该使用 CSRF。您可以通过各种方式保护您的端点,例如 oauth,还有其他最佳实践
实现您想要的效果的最简单方法是在添加 CSRF 中间件之前声明 Web Hook 路由。
但是,您可以有条件地应用 CSRF 保护,方法是直接跳到特定忽略路由上的 next
中间件。
您还需要在 webhook 路由上启用 CORS 以允许来自远程服务器的传入请求。
const express = require('express');
const cors = require('cors');
const csurf = require('csurf');
const cookies = require('cookie-parser');
const app = express();
const shared = cors({
origin: 'https://api.mollie.com',
methods: 'POST'
});
const protect = csurf({ cookie: true });
const ignore = [ '/api/webhook' ];
app.use(cookies(process.env.COOKIE_SECRET, {
sameSite: true, httpOnly: true,
secure: process.env.NODE_ENV === "production",
maxAge: process.env.COOKIE_MAX_AGE,
}));
app.use((req, res, next) => {
if (ignore.includes(req.url)) {
next();
} else {
protect(req, res, next);
}
});
app.use((req, res, next) => {
if (req.csrfToken) {
res.cookie("XSRF-TOKEN", req.csrfToken());
} next();
});
app.use('/api/webhook', shared, (req, res) => {
res.sendStatus(200);
});
app.use("/api/csrf", (req, res) => {
res.json({
status: true,
csrfToken: req.csrfToken(),
});
});
app.listen(process.env.PORT);