前端时间和我朋友写了一个简易用户管理后台,功能其实很简单,涉及到的技术栈有:vue+elementUI,java+spring MVC以及node+egg,数据库用的mysql,简单方便。前端
一开始是我是只负责前端,可是前端开发的的速度太快,总是没事,加上他小子并无接触过实战的项目,又怕他出乱子,因此考虑我也写一个后端,vue
开始考虑的是用python+django,可是仍是在半途放弃了,由于总感受Django不过灵活,使用起来很是别扭,也多是用scrapy写爬虫写多了,难以理解django的框架设计,老是会把他想象成一个scrapy架构,也致使代码写的很乱,下面上一张scrapy架构图。java
因此最后考虑的用node,Express和Koa框架学习过node应该都知道,我之前也用过express(写过一个小demo),可是给个人感受这到像是一个只能有5年以上node开发经验才能玩的转的,由于express是很是的精简的,安装它后,会发现它几乎不会为你提供任何编码规范,也没有约束你的框架应该怎么设计,以致于新手下载完成后彻底不知道本身应该干吗,甚至不知道直接的文件应该写在哪,没有框架自己的约定,标准的MVC模型有着千奇百怪的写法,因此我以为没有必定的架构思想和经验是很难驾驭的。node
koa我并无直接的使用过,只是据说是express的原班人马打造的,中间件是基于洋葱圈模型实现的。下面上一张图洋葱圈模型图。python
而是后来直接就接触的egg,egg标语是“为企业级框架和应用而生”,通道mysql
废话说的有点多了,重点是通一套前端代码,开发了两套后端代码,功能是彻底一致的,后端都实现了相应的jwt验证功能,-->json web token,密钥都是咱们约定好的固定值,可是最后发现同样的密钥,相同的数据,使用的jwt包不一样产生的结果也不一样,这也就致使两端之间没法相互切换,每次切换必须从登录从新开始,这不太符合逻辑,并且重要的是后面的安排有须要这样的功能,没法作到无缝切换就直接致使实现不了下面的功能。web
其实做为一个前端开发人员,jwt实现原理我是不必懂得的,可是若是你不限于此,这算是个必不可少的内容了吧。算法
先上一张图。spring
图中数字1是后端使用jwt工具包生成的token,一般是由三部分组成,也就是token中间的两个“.”将其分为三部分,第一部分对应的是右边的数字2部分,而后依次对应。sql
这三部分分别是头部、有效载荷、签名。
头部:alg是指说用到的算法,type固然是令牌类型
有效荷载:sub所签发的用户,name是签发者的姓名,lat是这签发时间,exp是指到期时间,固然还有一些其余的,这些数据都是非必要数据,实则只有exp可能有用,由于有效数据实际都是在data里面,固然你也能够不这么作。
签名:前二者都是经过base64url编码过的,而非是算法加密的,因此几乎是透明的。可是签名是默认是经过hsa256算法加密的 ,加密的规则是:
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), your-256-bit-secret )
如何验证token呢?那更加简单了,就是用前端传回来的token前两部分和服务器存的秘钥再次加密一次,而后作base64url处理和第三部分比较,同样表明这个token是本身签发的,不同表明是伪造的,完了事后再将有效载荷部分进行base64url反编码,就获得exp,而后和当前时间比较是否过时。
通过测试,发现三个问题。
一、 node和java使用对应的jwt工具包生成的token不相同,这里是指在一系列参数彻底相同的状况下。
二、 还发现用java生成的token在jwt官网解析时候输入秘钥结果的到的签名和本身的签名不同,可是node是同样的,因而就产生了java工具包在输入签名的时候对密钥进行了其余处理的想法,可是他并无找出作出来怎么样的处理,也就是说咱们在生成签名的时候根本就连密钥都是不同的。
三、 不论是node仍是java生成的token,咱们用原来如出一辙的数据和同样的算法公式都产生不了和工具包生成同样的签名,也就是能够怀疑在进行hsa256算法加密前确实对秘钥进行处理了。
base64就是一种二进制编码方式,原理很简单,先准备一个包含64个字符的数组:
['A','B','C',...'a','b','c',...'0','1','2',...'+','/']
而后对二进制数据进行处理,每三个字节一组,一共24bit,一个字节8bit嘛,而后再将24分为4组,每组正好6bit。6bit的话就恰好能表示64个字符。若是编码字符不是3的倍数,就会剩下一个字节或者两个字节,这个时候就在后面填充\x00,再在编码末尾加上一个或者两个=号。解码的时候制动力去掉就行了。
base64url编码就是将字符编码成url能传递的参数,由于base64编码会出现+号和/号,而后就会在url中出现问题,因此base64url其实就是将+和/分别变成-和_