手绘10张图,把CSRF跨域攻击、JWT跨域认证说得明明白白的( 二 )


因此,当你要使用 Referer Check 来做为 防御 CSRF 攻击的主要手段时,请确保你的用户群体使用的一定是最安全的最新版本的浏览器,并且默认用户不会手动关闭 Referer。
 
3.3 加验证码验证码,强制用户必须与应用进行交互,才能完成最终请求 。
其实加验证码,是能很好遏制 CSRF 攻击,但是网站总不能给所有的操作都加上验证码吧,那样的话,用户估计都跑光光了,因此为了保证用户体验,验证码只能作为一种辅助手段,不能作为主要解决方案 。
 
3.4 CSRF TokenCSRF 攻击之所以能够成功,是因为黑客可以完全伪造用户的请求,该请求中所有的用户验证信息都是存在于 cookie 中,因此黑客可以在不知道这些验证信息的情况下,直接利用用户自己的 cookie 来通过安全验证 。
所以要抵御 CSRF,关键在于要在请求中放入黑客所不能伪造的信息,并且该信息不存在于 cookie 之中(不然黑客又能拿到了) 。
业界普遍的防御方案是使用 CSRF Token
使用 CSRF Token 根据token验证方式的不同,也可以分为两种:
第一种:如图所示

手绘10张图,把CSRF跨域攻击、JWT跨域认证说得明明白白的

文章插图
  1. 当用户请求一个更新用户名的页面时,由服务端生成一个随机数 Token,然后放入HTML表单中传给浏览器,并且存入 session 中 。
  2. 当用户提交表单请求时,表单数据会带上这个 Token 发送给服务端 ;
  3. 服务端收到表单请求后,会从表单数据里取出 Token,然后和 session 里的 token 进行对比,如果是一样的,就是合法的用户请求,将新的用户名存入数据库,如果不一样,那就是非法的请求,应当拒绝 。
第二种:
手绘10张图,把CSRF跨域攻击、JWT跨域认证说得明明白白的

文章插图
  1. 当用户请求一个更新用户名的页面时,由服务端生成一个随机数 Token,然后放入HTML表单中,并且会把这个 Token 放在 cookie 里发给浏览器 。
  2. 当用户提交表单请求时,表单数据会带上这个 Token 发送给服务端,并且带上携带 token 的 cookie ;
  3. 服务端收到表单请求后,会从表单数据里取出 Token,与 cookie 里的 token 进行对比,如果是一样的,就是合法的用户请求,将新的用户名存入数据库,如果不一样,那就是非法的请求,应当拒绝 。
 
3.5 新增 Header使用上面的 CSRF Token 已经可以避免 CSRF 攻击,但是它却有可能又引入了另一个问题 。
若 CSRF Token 没有使用 cookie,就必须要将 Token 存储在服务端的 Session 中,这样就会面临几个问题
  1. 服务端每生成一个 Token,都会存放入 session 中,而随着用户请求的增多,服务端的开销会明显增大 。
  2. 如果网站有多个子域,分别对应不同的服务器,比如 taobao.com 后台是服务器 a,zhibo.baotao.com 后台是 服务器b,不同子域要想使用同一个 Token,就要求所有的服务器要能共享这个 Token 。一般要有一个中心节点(且应是一个集群)来存储这个Token,这样看下来,架构就变得更加复杂了 。
想要解决这些问题,可以使用我们接下来要讲的 JWT(全称:JSON Web Token)
使用了 JWT 后,有了哪些变化呢
  1. 服务器只负责生成 Token和校验Token,而不再存储Token
  2. 将服务器的压力分摊给了所有的客户端 。
  3. 服务端的 鉴权不使用 cookie ,而是由新增的 Header 字段:Authorization 里的 JWT。
JWT 是本篇文章重要知识点之一,下面我会详细说说关于 JWT 的内容 。
手绘10张图,把CSRF跨域攻击、JWT跨域认证说得明明白白的

文章插图
 
JWT 的工作原理及目的为了让你直观感受 JWT 的工作原理,我画了下面这张图
手绘10张图,把CSRF跨域攻击、JWT跨域认证说得明明白白的

文章插图
  1. 用户以 Web表单 的形式,将自己的用户名和密码 POST 到后端的接口 。
  2. 后端核对用户名和密码成功后,会计算生成JWT Payload 字符串(具体计算方法,后续会讲),然后返回 response 给浏览器 。
  3. 浏览器收到 JWT 后,将其保存在 cookie 里或者 localStorage 或者 sessionStorage 里(具体如何选,后面会说) 。
  4. 后续在该域上发出的请求,都会将 JWT放入HTTP Header 中的 Authorization 字段 。
  5. 后端收到新请求后,会使用密钥验证 JWT 签名 。
  6. 验证通过后后端使用 JWT 中包含的用户信息进行其他相关操作,返回相应结果 。


    推荐阅读