前后端星散架构下CSRF防御机制

原文: http://feclub.cn/post/content…

背景

1、什么是CSRF进击?

这里不再引见CSRF,已相识CSRF道理的同砚能够直接跳到:“3、前后端星散下有何差别?”。

不太相识的同砚能够看这两篇对CSRF引见比较细致的参考文章:

假如来不及相识CSRF的道理,能够这么明白:有一个人发给你一个搞(mei)笑(nv)图片链接,你翻开这个链接以后,便马上收到了短信:你的银行里的钱已转移到这个人的帐户了

2、有哪些防备计划?

上面这个例子固然有点耸人听闻,固然能够一定的是确切会有如许的破绽:你翻开了一个未知域名的链接,然后你就自动发了条广告帖子、你的Gmail的邮件内容就泄露了、你的百度登录状况就没了……

防备计划在上面的两篇文章里也有提到,总结下,无外乎三种:

  1. 用户操纵限定,比方考证码;

  2. 要求泉源限定,比方限定HTTP Referer才完成操纵;

  3. token考证机制,比方要求数据字段中增加一个token,相应要求时校验其有效性;

第一种计划显著严重影响了用户体验,而且另有分外的开辟本钱;第二种计划本钱最低,然则并不能保证100%平安,而且很有可能会埋坑;第三种计划,可取!

token考证的CSRF防备机制是公认最合适的计划,也是本文议论的重点。

3、前后端星散下有何差别?

《CSRF 进击的应对之道》这篇文章里有提到:

要把一切要求都改成 XMLHttpRequest 要求,如许几乎是要重写全部网站,这价值无疑是不能接收的

我们前端架构早已告别了效劳端言语(PHP/JAVA等)绑定路由、照顾数据衬着模板引擎的体式格局(毕竟是2011年的文章了,我们笑而不语)。

固然, 前端不要愉快的太早:前后端星散以后,Nodejs不具备完美的效劳端SESSION、数据库等功用。

总结一下,在“更先进”的前端架构下,与以往的架构会有一些区分:

  • Nodejs层不处置惩罚SESSION,没法直接完成会话状况数据保留;

  • 一切的数据经由过程Ajax异步猎取,能够天真完成token计划;

完成思绪

如上文提到,这里仅仅议论在“更先进”的前端后端架构背景下的token防备计划的完成。

1、可行性计划

token防备的团体思绪是:

  • 第一步:后端随机发生一个token,把这个token保留在SESSION状况中;同时,后端把这个token交给前端页面;

  • 第二步:下次前端须要提议要求(比方发帖)的时刻把这个token加入到要求数据或许头信息中,一同传给后端;

  • 第三步:后端校验前端要求带过来的token和SESSION里的token是不是一致;

上文提到过,前后端星散状况下,Nodejs是不具备SESSION功用的。那这类token防备机制是不是是就没法完成了呢?

一定不是。我们能够借助cookie把这个流程晋级下:

  • 第一步:后端随机发生一个token,基于这个token经由过程SHA-56等散列算法天生一个密文;

  • 第二步:后端将这个token和天生的密文都设置为cookie,返回给前端;

  • 第三步:前端须要提议要求的时刻,从cookie中猎取token,把这个token加入到要求数据或许头信息中,一同传给后端;

  • 第四步:后端校验cookie中的密文,以及前端要求带过来的token,举行正向散列考证;

固然如许完成也有须要注重的:

  • 散列算法都是须要盘算的,这里会有机能风险;

  • token参数必须由前端处置惩罚以后交给后端,而不能直接经由过程cookie;

  • cookie更痴肥,会不可避免地让头信息更重;

如今计划一定了,详细该怎样完成呢?

2、详细完成

我们的手艺栈是 koa(效劳端) + Vue.js(前端) 。有兴致能够看这些材料:

在效劳端,完成了一个token天生的中间件,koa-grace-csrf

  // 注重:代码有做精简
  
  const tokens = require('./lib/tokens');
  return function* csrf(next) {
    let curSecret = this.cookies.get('密文的cookie');
    // 其他假如要猎取参数,则为设置参数值
    let curToken = '要求http头信息中的token';
    
    // token不存在
    if (!curToken || !curSecret) {
      return this.throw('CSRF Token Not Found!',403)
    }

    // token校验失利
    if (!tokens.verify(curSecret, curToken)) {
      return this.throw('CSRF token Invalid!',403)
    }

    yield next;

    // 不管何种状况都种两个cookie
    // cookie_key: 当前token的cookie_key,httpOnly
    let secret = tokens.secretSync();
    this.cookies.set(options.cookie_key, secret);
    // cookie_token: 当前token的的content,不须要httpOnly
    let newToken = tokens.create(secret);
    this.cookies.set(options.cookie_token, newToken)
  }

在前端代码中,对发送ajax要求的封装稍作优化:

  this.$http.post(url, data, {
      headers: {
          'http要求头信息字段名': 'cookie中的token'
      }
  }).then((res) => {})

总结一下:

  • Nodejs天生一个随机数,经由过程随机数天生散列密文;并将随机数和密文存到cookie;

  • 客户端JS猎取cookie中的随机数,经由过程http头信息交给Nodejs;

  • Nodejs相应要求,校验cookie中的密文和头信息中的随机数是不是婚配;

这里照旧有个细节值得提一下:Nodejs的上层平常是nginx,而nginx默许会过滤头信息中不合法的字段(比方头信息字段名包括“_”的),这里在写头信息的时刻须要注重。

“One more thing…”

上文也提到,经由过程cookie及http头信息通报加密token会有许多弊病;有无更文雅的完成计划呢?

1、cookie中samesite属性

回溯下CSRF发生的根本原因:cookie会被第三方提议的跨站要求照顾,这本质上是HTTP协定设想的破绽。

那末,我们能不能经由过程cookie的某个属性制止cookie的这个特征呢?

好消息是,在最新的RFC范例中已加入了“samesite”属性。细节这里不再赘述,能够参考:

  1. SameSite Cookie,防备 CSRF 进击

  2. Same-site Cookies

2、更文雅的架构

固然,目前为止,客户端对samesite属性的支撑并非迥殊好;回到前后端星散架构下,我们明白下前后端星散框架的基础原则:

后端(Java / PHP )职责:

  • 效劳层颗粒化接口,以便前端Nodejs层异步并发挪用;

  • 用户状况保留,完成用户权限等种种功用;

前端(Nodejs + Javascript)职责:

  • Nodejs层完成路由托管及模板引擎衬着功用

  • Nodejs层不担任完成任何SESSION和数据库功用

我们提到,前端Nodejs层不担任完成任何SESSION和数据库功用,但有无可能把后端缓存体系做成大众效劳提供给Nodejs层运用呢?想一想觉得前端整条路都亮了有木有?!这里先挖一个坑,后续逐步填。

3、延长

这里再趁便提一下,新架构下的XSS防备

犹记得,在狼厂运用PHP的年代,经常被平安部门曝出各种XSS破绽,然后就在smaty里增加种种escape滤镜,然则增加以后发明居然把原始数据也给转义了。

固然,如今更多要归功于种种MVVM单页面运用:使得前端完整不须要经由过程读取URL中的参数来掌握VIEW。

不过,另有一点值得一提:前后端星散框架下,路由由Nodejs掌握;我本身要猎取的后端参数和须要用在营业逻辑的参数,在主观上前端同砚更好把握一些。

所以, 在koa(效劳端) + Vue.js(前端)架构下基础不必挂念XSS题目(最少不会被全安组追着问XSS破绽啥时刻修复)。

总结

要不学PHP、看Java、玩Python做全栈好了?

    原文作者:wilee
    原文地址: https://segmentfault.com/a/1190000006944760
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞