这是一篇关于 JWT(JSON Web Token) 的简短介绍。
什么是JWT
JWT, 全称是JSON Web Token,
是一种易于使用、无状态的鉴权(Authorization)方式。
简单的来说,就是
Server端把JSON数据经过加密做成token,以授权给Client端。
多说无益,上代码,举个栗子。
当Client端登录完成以后,
Server端要返回一个7天有效的token,
那么对应的Python的样例代码会是这样的:
(使用了PyJWT包:pip install pyjwt
)
import time
import jwt
exp = int(time.time()) + 86400 * 7 # 失效时间
user = 'liriansu' # 用户表示
key = 'hunter2' # 密钥
payload = {'exp': exp, 'user': user} # JSON 数据
token = jwt.encode(payload, key)
print(token)
# token可能会长这样子
# eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.EoKoMCjq_zGqUg5HDfqw4EN7EiG6gMjkUZle0uGJDGU
然后Client端每次在authorization header或者是query string里带上token。
Server端收到请求的时候,
用payload = jwt.decode(token, key)
验证权限就行了。
验证通过以后,payload中就是整个JSON数据。
理论上你可以往token payload里塞任何_非敏感_数据。
所以综合来说,
假如使用JWT作为鉴权方式,
有以下几个特性:
- Client端不用管任何加密/解密,只用存token,在请求里面带上就行了。
- Server端可以实现不依赖外部存储鉴权,所有的数据都丢在token里。
- 也就是说鉴权这一步不需要File/MySQL/Redis之类的数据库,也能知道用户身份。
- 因为token带失效时间,所以需要在失效前/后再刷新token。
好了,以上就是关于JWT的所有描述了。
本次的简单介绍就到此结束。(雾)
(不过上次关于Hawk的介绍大概就是这样的)
关于JWT的更多说明
讲了这么多,实质上就是用个JSON数据当token,
这破token真的安全吗?能伪造吗?
emmmmmm, 好问题(表示这个问题很尖锐,难以正面回答,准备迂回)
JWT使用很广泛,久经考验,大家都在用(表现了我也不懂,应该不会有问题吧?的一种从众心理)
认真地发表一下个人意见:
首先token/key泄漏了,
后果基本是跟其它鉴权方式一样严重。
其次JWT可以选择合适的加密方式,
加上合适的key是基本伪造不了的。
还有就是在JWT之外,
一定要用HTTPS!
不用JWT相当于没有门禁,
不用HTTPS基本是不穿内裤了。。。
我想了解更详细的JWT生成/验证过程
具体说明请参照来源 RFC7519 - JSON Web Token (JWT)
简单的来说,JWT是由以下三部分组成的:
- 第一部分指定了加密算法(alg)和token类型(typ)。
- 第二部分就是我们定义的payload。
- 第三部分是由加密算法产生的签名。
获取了三部分数据以后,
分别用base64加密,
把最末的等号去掉,
再用小数点连在一起,
就是一个token了。
验证的话,基本就是把这个过程反过来。
我去,那token里的信息就是明文的啊?
是的。
所以token里不要带任何敏感信息。
文档上把payload里带的信息叫Claim
,
有这么几个可选的Claim
:
iss: Issuer, 签发方。
比如这个token是微信签发的,
那么可以是{'iss': 'wechat'}
aud: Audience, 接收方。
比如王者荣耀想用微信登录,
那么可以是{'aud': 'king-of-glory'}
exp: Expiration Time, 失效时间。
使用的是整形Unix时间戳,
关于时间戳可以看看《互联网上的日期和时间》
RFC7519里面还有一点很好玩,
就是上面每一个Claim
最后都加了一句Use of this claim is OPTIONAL
(RFC2119还定义过啥叫OPTIONAL)
也就是说我们可以往payload里丢任何东西。
只要符合这种加密/解密/鉴权的方式,
我们都可以说“我们用了JWT”。
那token会不会很大?
有可能会。
所以payload里的东西能少则少,
看文档里,连issuer -> iss
, audience -> aud
这种地方都给省了好几个字符。
还有就是传输JWT的时候,
相较于放query string里,
更推荐放在Request Headers里面。
与其他鉴权方式的对比
详尽的比较超越了本文的范畴,
(写这句话好爽,可以少查一万个资料)
下面就用个简单的表格来对比一下_我了解的_几种鉴权方式吧:
JWT, OAuth, Session, Hawk
JWT | OAuth | Session | Hawk | |
---|---|---|---|---|
易用性 | 容易,就一个token | 麻烦,要用Refresh Token刷Access Token | 容易,用Cookie就行 | 麻烦,每个请求都要单独计算header |
泛用性 | 各种场合都适用 | 带三方授权的场合特别适用 | 还行吧… | 能用header的都适用 |
安全性 | 跟别的方案差不多,key泄漏了就完蛋了 | Auth Server安全就行, | 还行吧… | 我!能!防!中间人攻击! |
接受度 | 有一定安全度,client端很喜欢,用的还是很多的 | 繁琐和安全的折中方案,很多大厂都用 | 真的广… | 目前只听说了我司在用Hawk |
其它感受
JWT全称叫JSON Web Token,
小心别写了类似jwt_token
这样的变量名了(语义重复)。RFC7519还定义了JWT读起来是类似于jot的发音。
然而实际中交流都会说JWT(怕听不懂)。JWT说是说用同一个key就行了,
不过我们在项目实际中还是根据不一样的user用了不一样的key。
(同时也用了数据库)假如payload里带了失效时间,
理论上JWT签发后是不会失效的,
也就是Server端管理不了这些token。
(所以可以加个数据库来管)
(好像变复杂了)用JWT想做“记住登录状态”这个功能的话,
可以设定token失效期比如是7天,
然后用户每天登录的时候刷一次token。
这样除非用户一周内都没登录,
才会请求重新登录。我对互联网安全的认知是真的有限,
经常看文档,
一句话学到三四个新的词。
还是要多学习一个啊。
所谓苟日新,日日新,又日新
是也。