如何使用csurf保护我的React应用程序API?

13

我正尝试为我的React应用程序添加CSRF保护,但我一直收到“无效令牌”错误。

import bodyParser from 'body-parser';
import cookieSession from 'cookie-session';
import passport from 'passport';
import csrf from 'csurf'
import config from '../../config'
import AuthRoutes from "./routes/AuthRoutes";

/* Test only */
import cookieParser from 'cookie-parser';


const session = cookieSession({
    maxAge:24 * 60 * 60 * 1000,
    keys:[config.COOKIE_KEY],
    name:'authentication',

});



export default app => {

    app.use(bodyParser.urlencoded({
        extended: true
    }));
    app.use(bodyParser.json());
    app.use(session);
    app.use(passport.initialize());
    app.use(passport.session());

    /* Test */
    app.use(cookieParser());
    app.use(csrf({ cookie: true }));

    app.use(function (err, req, res, next) {
        if (err.code !== 'EBADCSRFTOKEN') return next(err)

        // handle CSRF token errors here
        res.status(403)
        res.send('form tampered with')
    })

    /*Passport Config*/
    require('../../services');

    /* Register, Login these are routes i want to protect */
    AuthRoutes(app);

}
2个回答

19

你需要做以下事情:
1. 在服务器上配置csrf库。这可以确保该库将在服务器响应中发送第一部分数据。
2. 在服务器上使用csrf库生成第二部分数据,并将其附加到服务器响应(例如发送给客户端的HTML表单)中。完成此步骤后,服务器响应将携带两个CSRF数据部分。
3. 在客户端中获取第二部分数据,并将其插入到即将发送的请求中(例如即将提交的表单)。

第一步
目前只完成了第(1)步。您要求csrf库以cookie的形式发送第一部分数据。您可以使用更好的配置:

app.use(csrf({cookie: {
    httpOnly: true,
}}));

它确保浏览器不允许客户端的任何JS接触cookie中的第一部分数据,这是好的,因为没有正当理由让任何脚本知道这个cookie里面的内容。在生产环境中并且使用HTTPS时,您可以选择将 secure: true 添加到上述配置中,使服务器拒绝通过非安全连接发送此Cookie。

步骤2
要获取第二部分数据,请调用csrfToken()函数。为了方便起见,csrf中间件添加了另一个属性到Request对象中,因此可以这样调用:const secondPiece = req.csrfToken()。您可以以任何方式将第二部分数据放入服务器响应中,例如将其放入带有任意名称的另一个cookie(除了步骤1 cookie已经使用的_csrf名称)或以您喜欢的任何名称命名的HTTP标头中。

例如,以下代码将把第二部分数据放入另一个cookie中:

res.cookie('XSRF-TOKEN', req.csrfToken());

步骤3
在客户端编写JS以获取第二个数据,并将其放入预定义的某个位置/位置(请求中要发送到服务器的位置之一),其中csrf中间件默认情况下会搜索它。


1
将令牌作为cookie从服务器发送到客户端是否比作为端点响应的正文更安全(必须为httpOnly:false,否则客户端无法获取并填充到标头中)? - Pere

4

以防万一,如果任何解决方案都不起作用。

我刚刚经历了几天的调试,原因是cookie名称错误。确保将您的cookie命名为 XSRF-COOKIE(注意它使用了 - 符号),因为我错误地使用下划线 XSRF_COOKIE 命名我的cookie,这让我痛苦了好几天。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接