Egg Csrf 安全配置
开启与关闭配置
注意:除非清楚地确认后果,否则不建议擅自关闭安全插件提供的功能。
框架的安全插件是默认开启的,如果我们想关闭其中一些安全防范,直接设置该项的 enable
属性为 false 即可。
exports.security = { csrf: { enable: false, }, };
开启 CSRF 也很简单,在上述的 enable 变更为 true 即可。
通常来说,对于 CSRF 攻击有一些通用的防范方案,简单的介绍几种常用的防范方案:
- Synchronizer Tokens:通过响应页面时将 token 渲染到页面上,在 form 表单提交的时候通过隐藏域提交上来。
- Double Cookie Defense:将 token 设置在 Cookie 中,在提交(POST、PUT、PATCH、DELETE 等)请求时提交 Cookie,并通过 header 或者 body 带上 Cookie 中的 token,服务端进行对比校验。
- Custom Header:信任带有特定的 header(例如
X-Requested-With: XMLHttpRequest
)的请求。这个方案可以被绕过,所以 rails 和 django 等框架都放弃了该防范方式。
框架结合了上述几种防范方式,提供了一个可配置的 CSRF 防范策略。
使用方式
同步表单的 CSRF 校验
在同步渲染页面时,在表单请求中增加一个 name 为 _csrf
的 url query,值为 ctx.csrf
,这样用户在提交这个表单的时候会将 CSRF token 提交上来:
<form method="POST" action="/upload?_csrf={{ ctx.csrf | safe }}" enctype="multipart/form-data" > title: <input name="title" /> file: <input name="file" type="file" /> <button type="submit">upload</button> </form>
传递 CSRF token 的字段可以在配置中改变:
// config/config.default.js module.exports = { security: { csrf: { queryName: '_csrf', // 通过 query 传递 CSRF token 的默认字段为 _csrf bodyName: '_csrf', // 通过 body 传递 CSRF token 的默认字段为 _csrf }, }, };
为了防范 BREACH 攻击,通过同步方式渲染到页面上的 CSRF token 在每次请求时都会变化,egg-view-nunjucks 等 View 插件会自动对 Form 进行注入,对应用开发者无感知。
AJAX 请求
在 CSRF 默认配置下,token 会被设置在 Cookie 中,在 AJAX 请求的时候,可以从 Cookie 中取到 token,放置到 query、body 或者 header 中发送给服务端。
var csrftoken = Cookies.get('csrfToken'); function csrfSafeMethod(method) { // these HTTP methods do not require CSRF protection return /^(GET|HEAD|OPTIONS|TRACE)$/.test(method); } $.ajaxSetup({ beforeSend: function (xhr, settings) { if (!csrfSafeMethod(settings.type) && !this.crossDomain) { xhr.setRequestHeader('x-csrf-token', csrftoken); } }, });
通过 header 传递 CSRF token 的字段也可以在配置中改变:
// config/config.default.js module.exports = { security: { csrf: { headerName: 'x-csrf-token', // 通过 header 传递 CSRF token 的默认字段为 x-csrf-token }, }, };
Session vs Cookie 存储
默认配置下,框架会将 CSRF token 存在 Cookie 中,以方便 AJAX 请求获取到。但是所有的子域名都可以设置 Cookie,因此当我们的应用处于无法保证所有的子域名都受控的情况下,存放在 Cookie 中可能有被 CSRF 攻击的风险。框架提供了一个配置项,可以将 token 存放到 Session 中。
// config/config.default.js module.exports = { security: { csrf: { useSession: true, // 默认为 false,当设置为 true 时,将会把 csrf token 保存到 Session 中 cookieName: 'csrfToken', // Cookie 中的字段名,默认为 csrfToken sessionName: 'csrfToken', // Session 中的字段名,默认为 csrfToken }, }, };
本文来自博客园,作者:我就丶是逗比,转载请注明原文链接:https://www.cnblogs.com/lonewolfyx/articles/16324817.html