我正在尝试在nodejs,express和React Project中使用csurf
。我的 csurf 现在工作正常,但我想仔细检查我是否做对了。
这是我的nodejs路由器和中间件结构:
app.use(cookieParser());
app.use("/api/...") // routes that don't need csrf
app.use("/form/...",csrf({cookie:true})) // form path with csrf middleware
app.use(express.static("/img")) // image folder which doesn't need csrf
app.use(csrf({ cookie: true })); // enable csrf for the rest of the app
app.all("*", function(req, res, next) {
res.header("X-CSRF-Token", req.csrfToken()); // set csrf to header
return next();
});
app.use(express.static("/SPA")); // frontend project
当前行为:
当我第一次进入我的 Web 项目时,我的
response headers
中有X-CSRF-Token: xxxxx
和set-cookie: _csrf=yyyyy; Path=/
当我刷新页面时,
Cookie: _csrf=yyyyy;
出现在request headers
部分中。当我刷新页面时,
X-CSRF-Token
更改为不同的值。只有
X-CSRF-Token
值通过 post 请求传递,_csrf
cookie 中的值抛出 403。
问题:
一个。我相信设置app.use(csrf({ cookie: true }))
是多余的,但是当我将其设置为 false 或删除app.all(...)
部分时,应用程序会抛出 403/内部服务器错误。如何解决?
二.X-CSRF-Token
每次刷新页面时都会发生变化,这显然是一种正常行为,因为我将其放在标题中,但它是否违背了 csrf 的目的?既然我的项目是SPA,我真的那么在乎吗?
请指出逻辑/行为是否有任何问题?
谢谢。
既然我的项目是SPA,我真的那么在乎吗?
如果客户端应用程序(无论是否SPA)向后端发送一些数据,并且数据直接或间接地更改了后端的状态,例如通过后端代表客户端执行的操作,则存在CSRF漏洞,除非像Angular这样的SPA框架负责CSRF保护,否则您应该关注。使用SPA不会改变CSRF方面的任何东西,它没有帮助,也没有减轻任何作用。
使用cookie解析器中间件,csrf中间件的工作方式如下:
-
在传入请求中使用预定义的名称检查其 Cookie。如果未找到,则生成一个密钥并将其值(修饰一点)放入响应cookie中,希望在下一个请求中找到它。所以秘密不再是秘密了。
-
如果未找到cookie并且传入的请求像POST一样发生变化(例如不是GET,HEAD...),则失败,例如发送403并设置cookie。如果像 GET 那样不变异,则处理完成。
-
如果找到cookie,则检查第二条数据,默认情况下在少数位置,包括具有预定义名称的HTTP标头。如果未找到或找不到且不正确,则传入请求失败。否则,处理完成。
为确保此检查成功,您需要执行 2 个步骤:
- 在后端调用req.csrfToken()
获取第二条数据并存储在响应中。您选择将其存储在HTTP标头中,这很好。但是您可以使用任何标头名称。或者,您可以在<head>
部分中使用<meta>
标签。
- 在客户端上,从后端响应中的上述标头或<meta>
标签中获取第二条数据,并将其放入您将要发送的请求中,假设请求正在发生变化,例如 POST、PUT 等。此外,您需要将其放入请求中默认搜索 csrf 中间件的预定义位置之一。
关于您的代码:
1. 缺少负责第二步的客户端代码。
2. 在后端调用csrf({options})
函数一次并存储返回值。你已经叫了两次了。返回值,我们称之为retValue
,是配置好的 csrf 中间件,根据需要使用它:app.post(/<path>, retValue, ...req, res, next) => {...
3.至于选项,请设置为httpOnly: true
.此外,在生产集secure: true
中:
csrf({cookie: {
httpOnly: true,
secure: true
}})
A.我相信设置
app.use(csrf({ cookie: true }))
是多余的, 但是当我将其设置为 false 或删除app.all(...)
部分时,该应用程序 抛出 403/内部服务器错误。如何解决?
通过在路由之前设置app.use(csrf{cookie:true})
,可以告诉应用传递通过 csrf 中间件获取的每个请求(高于此命令的请求除外)。这个中间件应该做 3 件事。
首先是设置 csrf cookie,如果它还没有出现的话。此 cookie 是创建/验证 csrf 令牌所需的秘密。
其次是在调用req.csrfToken()
时创建新令牌。
第三是验证所有非 GET/HEAD/OPTION 请求的令牌。
了解使用此命令执行的操作也很重要:
app.all("*", function(req, res, next) { res.header("X-CSRF-Token", req.csrfToken());将 csrf 设置为标头返回下一个();});
您的所有请求(获取,发布,放置等)它们都会根据您在cookie中的机密生成新令牌。相同的秘密会生成随机令牌,因为随机盐用于此目的。
因此,如果您删除 app.all 部分req.csrfToken()
您将不会生成任何令牌,因此验证将失败。如果您删除app.use(csrf)
部分,您将无法验证任何内容,因为该部分进行验证,并且您也无法发行令牌。因为换句话说,中间件将被关闭。因此,您无法删除这两个命令中的任何一个,因为它们用于不同的目的。
B. 每次刷新页面时,x-csrf-Token 都会更改,这显然是一种正常行为,因为我将其放在标题中,但它是否违背了 csrf 的目的?既然我的项目是SPA,我真的那么在乎吗?
csrf 令牌的目的是验证请求是否来自您的网站,否则客户端将只有 cookie,而标头中没有令牌。按链接在您的网站上启动某些操作,但位于其他网站上不会为客户端生成 csrf 令牌。