如何在Node+React项目中防止CSRF攻击

什么是CSRF攻击

CSRF(Corss-site request forgery)即跨站请求伪造攻击,也常缩写为XSRF,是一种常见的web攻击方式。前端

简单来讲,CSRF攻击就是:用户访问正常网站A的时候,会在浏览器中留下一些登陆信息(好比cookie),恶意网站B利用这些登陆信息,伪造一些请求信息,告诉正常网站A我使合法用户,从而对网站A进行攻击。ios

下面经过一张图来阐述该攻击的过程和原理:web

如何防护CSRF攻击

在项目中防护CSRF攻击的时候,能够遵循如下几个方面:shell

  • Get请求不对网站中的数据进行修改
  • 设置cookie的安全数据,不让第三方网站访问到用户的cookie
  • 组织第三方网站请求接口
  • 服务端接收到请求时,校验验证信息,好比验证码或者token

下面咱们已Node + React项目为例,来阐述如何经过校验token来方式CSRF攻击。这里咱们使用到一个很成熟的第三方包:csurfnpm

须要说明的是,这个示例中后端使用cookie来辅助管理token信息,因此项目中已经使用了 cookie-parser ,更详细的信息能够参考 csurf 官当文档axios

从开发角度来讲,能够分为三个步骤:后端

  1. 后端API生成token
  2. 前端发送请求,获取token并存储到本地,在后续的请求中讲token附带到请求头中
  3. 后端接收到请求,校验请求头中的token是否合法,若是合法则继续执行,不然直接返回相关报错信息给前端。

在后端API中生成token并返回给前端请求

首先执行一下脚本,讲csurf包安装到项目中:浏览器

npm install csurf
复制代码

而后在项目中引入该包,写一个生成token的API,代码示例以下:安全

var csrf = require('csurf')

var csrfProtection = csrf({ cookie: true });
app.get(`/getCsrfToken`, csrfProtection, (req, res) => {
    res.send({ csrfToken: req.csrfToken() });
})
复制代码

前端获取token并添加到后续请求头中

在使用React开发的前端项目中,能够在根组件挂载完成以后,在其余全部请求以前,调用 /getCsrfToken 请求,获取token。这里建议在根组件的 componentDidMount 生命周期中发起请求,而后将获得的token保存到sessionStorage中。示例代码以下:markdown

import axios from 'axios';

componentDidMount() {
    axios.get('/getCsrfToken')
        .then(res => {
            if (res && res.data && res.data.csrfToken) {
                window.sessionStorage.setItem('CSRF-Token', res.data.csrfToken);
            } else {
                throw new Error("Get CSRF token failed");
            }
        }).catch(() => {
            throw new Error("Get CSRF token failed");
        });
}
复制代码

获取token以后,在其余的API请求中,都将该token设置到请求头中,一块儿发送到后端API中。这里以 axios 为例,展现如何设置请求头:

import axios from 'axios';

// 在建立axios实例的时候,设置请求头信息
this.axios = axios.create({
    headers: {
        'CSRF-Token': window.sessionStorage.getItem('CSRF-Token') || ""
    }
})

// 修改已建立的axios实例的请求头信息
this.axios.defaults.headers.common['CSRF-Token'] =  window.sessionStorage.getItem('CSRF-Token');
复制代码

如此一来,前端在发送请求的时候,就会将token信息附在请求头中,一块儿发给后端进行处理。

在后端校验token信息的合法性

在前面生成token信息的时候,咱们已经经过如下代码建立了一个csurf实例:

var csrfProtection = csrf({ cookie: true });
复制代码

咱们能够直接以中间件的形式使用该实例对token进行校验,即:

app.use(csrfProtection);
复制代码

到这里,一个基本的防护CSRF攻击的措施就完成了,须要注意的是,使用csurf包进行防护CSRF攻击的时候,会校验两个变量:一个是自动添加到cookie中的_csrf,一个就是上述生成的token,两者缺一不可。

写在后面

博客中若有错误之处,还但愿各位达大佬予以纠正。

相关文章
相关标签/搜索