在了解 CSRF 以前咱们须要科普两个前提。首先是登陆权限验证的方式有不少种,目前绝大多数网站采用的仍是 session 会话任务的方式。session 机制简单的来讲就是服务端使用一个键值对记录登陆信息,同时在 cookie 中将 session id(即刚才说的键)存储到 cookie 中。另外咱们又知道浏览器中 HTTP(s) 请求是会自动帮咱们把 cookie 带上传给服务端的。这样在每次请求的时候经过 cookie 获取 session id,而后经过它在服务端获取登陆信息便可完成用户权限的校验。php
原本这也是个不错的功能。可是因为 cookie 实在是太开放了,若是一个用户在 A 网站登陆了,若是用户在 B 网站访问的时候发送了一个 A 网站的请求,那么这个请求实际上是带有这个用户在 A 网站的登陆信息的。若是这时候 B 站的 A 网站请求是用户不知道的,那就是很是严重的危害了。以上的过程就是跨站请求攻击,即 Cross-Site Request Forgery,即 CSRF。html
简单总结 CSRF 漏洞就是利用网站权限校验方面的漏洞在用户不知觉的状况下发送请求,达到“假装”用户的目的。攻击者利用 CSRF 实现的攻击主要有如下几种:前端
其中 CSRF 蠕虫如其名所指就是产生蠕虫效果,会将 CSRF 攻击一传十,十传百。如:某社区私信好友的接口和获取好友列表的接口都存在CSRF漏洞,攻击者就能够将其组合成一个CSRF蠕虫——当一个用户访问恶意页面后经过CSRF获取其好友列表信息,而后再利用私信好友的CSRF漏洞给其每一个好友发送一条指向恶意页面的信息,只要有人查看这个信息里的连接,CSRF蠕虫就会不断传播下去,其可能形成的危害和影响很是巨大!web
从上文的描述中咱们能够知道 CSRF 有两个特色:利用 cookie 自动携带的特性以及跨站攻击。那么针对这两个特性可使用以下解决方法。浏览器
你们都知道 HTTP 头中有一个 Referer 字段,这个字段用以标明请求来源于哪一个地址。经过在网站中校验请求的该字段,咱们能知道请求是不是从本站发出的。咱们能够拒绝一切非本站发出的请求,这样避免了 CSRF 的跨站特性。cookie
const { parse } = require('url');
module.exports = class extends think.Logic {
indexAction() {
const referrer = this.ctx.referrer();
const {host: referrerHost} = parse(referrer);
if(referrerHost !== 'xxx') {
return this.fail('REFERRER_ERROR');
}
}
}
复制代码
一样以 ThinkJS 为例,只要在 Logic 中简单判断下便可。这种方式利用了客户端没法构造 Referrer 的特性,虽然简单,不过当网站域名有多个,或者常常变换域名的时候会变得很是的麻烦,同时也具备必定的局限性。session
因为 CSRF 是利用了浏览器自动传递 cookie 的特性,另一个防护思路就是校验信息不经过 cookie 传递,在其余参数中增长随机加密串进行校验。这里又有两种办法:post
除了上面说到的 cookie 登陆问题形成的 CSRF 攻击,还有就是增删改等操做使用 GET 请求完成,当该请求未校验登陆信息的时候也容易形成 CSRF 攻击。固然这种就比较低级了,不过也仍是须要注意。特别是当下 SPA 的流行,愈来愈多的 AJAX 请求,咱们更是要注意 CSRF 攻击的可能。网站
参考资料:ui