JWT(JSON Web Token)原理简介

原文:http://www.fengchang.cc/post/114

参考了一下这篇文章:https://medium.com/vandium-software/5-easy-steps-to-understanding-json-web-tokens-jwt-1164c0adfcec

原理说的非常清楚。总结如下:

 

首先这个先说这个东西是什么,干什么用的,一句话说:就是这是一种认证机制,让后台知道请求是来自于受信的客户端。

 

那么从这个角度而言,这个东西跟浏览器的cookie是一个作用,好比我在一个网站登录了,就可以往这个网站发送restful请求,请求的同时会捎带上cookie,后台检查这个cookie发现你是合法的,才响应你的请求。

 

只不过这里JWT的原理不同,但基本上最顶层的原理还是非常简单:

 

这个图中有三个主体: user, application server和authentication server

非常常见的一个架构,首先用户需要 通过登录等手段向authentication server发送一个认证请求,authentication会返回给用户一个JWT(这个JWT的具体内容格式是啥后面会说,先理解成一个简单的字符串好了)

此后用户向application server发送的所有请求都要捎带上这个JWT,然后application server会验证这个JWT的合法性,验证通过则说明用户请求时来自合法守信的客户端。

 

下面简单说一下这个JWT的格式,十分简单,就是一个三部分组成的字符串:

 

下面一部分一部分来讲:

header, 一个例子是:

非常简单,typ顾名思义就是type的意思,例如上面这里就指明是JWT的类型。alg顾名思义是algorithm的意思,指代一个加密算法,例如上面指代HS256(HMAC-SHA256),这个算法会在生成第三部分signature的时候用到。

 

payload,一个例子是:

这部分的本质是用户数据,怎么理解呢,就是JWT的目的是认证身份来源,那么你是不是得自报家门我是谁呢?所以总得往里塞点跟用户相关的信息吧,例如这里就是userId

 

signature,一个例子是:

signature顾名思义就是签名,签名一般就是用一些算法生成一个能够认证身份的字符串,具体算法就是上面表示的,也比较简单,不赘述,唯一说明的一点是上面hash方法用到了一个secret,这个东西需要application server和authentication server双方都知道,相当于约好了同一把验证的钥匙,最终才好做认证。

 

 

至此,三个部分,都解释完了,那么按照header.payload.signature这个格式串起来就行了,串之前注意,header和payload也要做一个base64url encoded的转换。那么最终拼出来的一个例子是:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiJiMDhmODZhZi0zNWRhLTQ4ZjItOGZhYi1jZWYzOTA0NjYwYmQifQ.-xN_h82PHVTCMA9vdoHrcZxH-x5mb11y1537t3rGzcM

 

再次强调一点,别看上面做了那么多hash,其实目的不在加密保护数据,而是为了认证来源,认证来源,认证来源。JWT不保证数据不泄露,因为JWT的设计目的就不是数据加密和保护。

 

最后再解释一下application server如何认证用户发来的JWT是否合法,首先application server 和 authentication server必须要有个约定,例如双方同时知道加密用的secret(这里假设用的就是简单的对称加密算法),那么在applicaition 收到这个JWT是,就可以利用JWT前两段(别忘了JWT是个三段的拼成的字符串哦)数据作为输入,用同一套hash算法和同一个secret自己计算一个签名值,然后把计算出来的签名值和收到的JWT第三段比较,如果相同则认证通过,如果不相同,则认证不通过。就这么简单,当然,上面是假设了这个hash算法是对称加密算法,其实如果用非对称加密算法也是可以的,比方说我就用非对称的算法,那么对应的key就是一对,而非一个,那么一对公钥+私钥可以这样分配:私钥由authentication server保存,公钥由application server保存,application server验证的时候,用公钥解密收到的signature,这样就得到了header和payload的拼接值,用这个拼接值跟前两段比较,相同就验证通过。总之,方法略不同,但大方向完全一样。

 

一个实战问题:jwt如何实现logout?

一种是设置expire time, 这种可以称为"被动logout",即超过了一定时间自动失效,但是如果等不及,就是想主动logout怎么办呢?由于jwt的这种"无状态"的天然属性,理论上是没有办法直接主动logout的,但是有一个间接的方法,就是可以在服务器后台存一个"黑名单",这个黑名单专门用来存尚未过期但又想主动标明失效的的token,然后登录状态检查的时候多做一步黑名单检查即可.

 

 

提两个best practice:

1. 发送JWT要用https,原因前面说了,JWT本身不保证数据安全

2.JWT的payload中设置expire时间,为什么要这样做其实跟cookie为什么要设置过期时间一样,都是为了安全。

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页