我必须在 React SPA 中使用 csrf 保护吗?

Posted

技术标签:

【中文标题】我必须在 React SPA 中使用 csrf 保护吗?【英文标题】:Do i have to use csrf protection in React SPA? 【发布时间】:2019-07-01 10:42:48 【问题描述】:

我使用 React 单页应用程序作为客户端或创建 React 应用程序 (CRA)。

在我的后端我使用 Node.js 和 Express。

要获取数据或存储,我需要从客户端调用 API 到后端。

实际上我已经看到有几个中间件,例如:- Express CSURF

但老实说,我不明白如何在每次请求时向客户端发送 CSRF 令牌。我已经尝试了几次,通过将 CSRF 插入 cookie 然后将其带到客户端。但是当第一个请求或新 cookie 被存储时,我得到错误Invalid CSRF Token

即使我这样做了:

app.use(session(
    genid: function (req) 
        return uuidv4() // use UUIDs for session IDs
    ,
    name:keys.session.name,
    secret: keys.session.secret,
    resave: false,
    saveUninitialized: true,
    rolling:true,
    cookie:  
        secure: false,
        httpOnly: true,
        maxAge:keys.session.maxAge, // satu hari,
        sameSite:true,
     

));
app.use(passport.session());
app.use(cookieParser());
app.use(csrf( cookie: false ));


app.use((req,res,next)=>
     res.cookie('CSRF_token', req.csrfToken(),  sameSite: true );
)

这意味着 CSRF_token cookie 将更改每个请求。但我只设置了一次:axios.defaults.headers.common['csrf-token'] = csrf; 并且结果仍然有效,但应该不起作用。

那么我需要 CSRF 吗?或如何在 react SPA 上配置正确的。

【问题讨论】:

我很想知道这个问题的答案 【参考方案1】:

那么我需要 CSRF 吗?

如此处所述:Am I under risk of CSRF attacks in a POST form that doesn't require the user to be logged in? 我认为您仍然应该设置它。

至于为什么它不适合你,我认为是因为标题名称。你可以查看CSURF checks by default是什么。

默认值是从以下位置读取令牌的函数,按顺序:

req.body._csrf - 通常由 body-parser 模块生成。 req.query._csrf - Express.js 的内置函数,用于从 URL 查询字符串中读取。 req.headers['csrf-token'] - CSRF-Token HTTP 请求标头。 req.headers['xsrf-token'] - XSRF-Token HTTP 请求标头。 req.headers['x-csrf-token'] - X-CSRF-Token HTTP 请求标头。 req.headers['x-xsrf-token'] - X-XSRF-Token HTTP 请求标头。

按照 CSURF 检查的内容,您有多种选择,请查看 axios, it seems to have a couple options for setting xsrf cookie and header names。

...
// `xsrfCookieName` is the name of the cookie to use as a value for xsrf token
xsrfCookieName: 'XSRF-TOKEN', // default

// `xsrfHeaderName` is the name of the http header that carries the xsrf token value
xsrfHeaderName: 'X-XSRF-TOKEN', // default
...

例如为了使用axios默认自带的X-XSRF-TOKEN header key,我在我的App.js文件中使用了如下方法:

componentDidMount() 
    axios.get(`/api/csrf`) // Send get request to get CSRF token once site is visited.
      .then(res => 
        axios.defaults.headers.post['X-XSRF-TOKEN'] = res.data; // Set it in header for the rest of the axios requests.
      )
  

但是,您可以使用表单隐藏输入或您喜欢的任何其他方法。您可以阅读更多关于为什么将它们放在 cookie 中的常见原因here。

我不确定您为您的客户使用的是什么,但如果您使用的是 Redux,您可能会向 here 寻求帮助。如果还是不行,你可以谷歌其他方法。

【讨论】:

这有多安全?通过端点请求 csrf 令牌。这不会破坏 csrf 令牌的目的吗? @alex067 理想情况下,您将有一个前端服务器将令牌注入您的前端应用程序。从某种意义上说,这不是最好的解决方案,您是正确的,但是如果没有前端服务器,我无法找到缓解这种情况的方法。否则,您可以在 jwt cookie 中对令牌进行签名,以确保它没有被替换。 我花了一整天的时间寻找解决方案,但我做不到。似乎没有人知道如何正确地做到这一点。

以上是关于我必须在 React SPA 中使用 csrf 保护吗?的主要内容,如果未能解决你的问题,请参考以下文章

SPA 使用的经过身份验证的 Rest API:如何获取用于登录和注册表单的 CSRF 令牌?

Laravel SPA 是不是仍应使用 CSRF 令牌来保证安全?

使用双重提交 cookie 的角度 SPA 中的 CSRF 保护

在React SPA中打开图形元标记和SEO

在 Laravel + React SPA 应用程序中应用 TDD

React js - Laravel 5:在 POST 方法中使用 csrf-token