理论基础篇
JWT 是什么?
JWT:Json Web Token 是一个非常轻巧的规范,允许我们在用户和服务器传递安全可靠的信息;
· jwt 可以跨多种语言进行工作,.NET, Python, Node.js, Java, PHP, Ruby, Go, JavaScript;
·jwt 是自带信息体;意味着:通过jwt本身就可以携带基本信息,非常利于信息传递;
·jwt 本身是由三个部分组成的字符串,可以很容易传递;
JWT的组成
jwt由三个部分组成:头部 header 、载荷 payload、签名 signature,每部分中间用.
进行分割。
头部 (header)
{ "typ": "JWT", #定义了Type "alg": "HS256",#具体的签名算法 }
然后进行base64encode
编码,就是第一部分的内容:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
载荷(Payload)
这部分就是具体承载信息的部分,通常也称JWT Claims
.
通常分为三个部分:registered claim, public claim, and private claim. (翻译太奇怪了,就不翻译了)
Registered Claims
主要包换了一些标准的claims:
- “iss” : ‘‘laiyuquan’’ # jwt的签发者;
- “sub” : “374522516@qq.com” #jwt的主要信息,具体所面向的用户
- “aud” : “www.laiyuquan.com” #jwt具体面向地址
- “exp” : “1500819855” #jwt过期的时间戳
- “iat” : “1490819753” #jwt签发的时间
public claim
公共的claim 包含一些 姓名、和一些基本信息;(可以不用)
Private Claims
一般是一些个人的信息;(基本不用)
举个例子:
包含两个registered claims(iss、exp) 和 两个public claims (name 、admin)
{ "iss": "scotch.io", "exp": 1300819380, "name": "Chris Sevilleja", "admin": true }
然后进行base64encode
编码,就是第二部分的内容:
eyJpc3MiOiJzY290Y2guaW8iLCJleHAiOjEzMDA4MTkzODAsIm5hbWUiOiJDaHJpcyBTZXZpbGxlamEiLCJhZG1pbiI6dHJ1ZX0
签名 (Signature)
将头部 和 载荷 两部分信息,用一个secret 进行签名,就得到了第三个部分:
var encodedString = base64UrlEncode(header) + "." + base64UrlEncode(payload);
HMACSHA256(encodedString, 'secret'); 这样就得到了 第三个组成部分:
03f329983b86f7d9a9f5fef85305880101d5e302afafa20154d094b229f75773
最终完整的jwt:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzY290Y2guaW8iLCJleHAiOjEzMDA4MTkzODAsIm5hbWUiOiJDaHJpcyBTZXZpbGxlamEiLCJhZG1pbiI6dHJ1ZX0.03f329983b86f7d9a9f5fef85305880101d5e302afafa20154d094b229f75773
QA篇章:
Q :JWT存放在哪里?
A :JWT 是存放在客户端的, 服务端不需要存,服务端通过解析获得用户的信息(这就是jwt最大的特点)
Q : 信息通过base64编码,是可逆的,放在payload 的信息不就暴露了?
A : 是的,所以我们不要存放敏感的信息; 一般用户信息 存user_id 能够识别具体的用户就ok了
Q : payload 有exp 过期时间戳,jwt也有过期的概念吗?
A :从jwt本身的设计理论其实 jwt 是不会自动过期的,但我们实际运用过程中
如果一个token长期有效,就会产生各种各样的问题(重放攻击),不是一个安全的策略。
所以一般设置 exp 字段,然后用程序处理jwt的过期,让之失效;
Q : jWT 一般设置多长有效时间为好?
A :具体分应用场景:
如果是web应用:一般以天为单位(比如设置3天 即3天不登录 就自动重新登录)
当然也有人 设置2个小时; 也有一定的道理,主要还是从安全角度考虑;
如果是APP应用 :以月为单位(比如设置6个月 、或者12个月)
也有人设置永不过期,也可以吧
这里的有效期设计逻辑:还是要看具体的业务场景 和 对安全的敏感程度
Q :改密码 或者 注销时,需要注销吗?
A :改密码:如果是单应用,我觉得改密码 就完全不影响jwt,因为改完密码你不会再进行登录;
如果是多应用,这就要将原先的jwt token 注销掉,产生新的token了;
注销: 注销 退出登录之类的应用,客户端清空jwt token 即可;
当然,服务端将token 同时注销也OK;
从安全角度考虑: 还是同时注销服务端的j’wt token 更为稳妥;
Q : jwt 是保存在客户端的, 怎么进行注销呢?
A :这就在程序中 会引入黑名单功能,将注销的token 放入黑名单中;
Q:jwt的失效 和 黑名单 本质上都是让token无效, 两者有什么区别吗?
A: 失效:是指有效时间过期了, 这个直接通过程序判断即可
黑名单: 这个设计主要是为了:刷新token ,或者 注销token ,要让原先的token无效,
黑名单是需要进行存储的, 一般放redis 即可!
Q:刷新token?jwt 存放在客户端, 还是怎么刷新呢?
A:服务端设计:在过去失效3分钟之前,不会刷新token
如果检测在3分钟之内了,就会进行刷新token
所谓刷新token:就旧的token加入黑名单,产生新的token; 然后接口都会返回jwt token
前端或者客户端判断:如果服务端返回的token 和 本地存储的token不同,
则将本地存储的token 存储为服务端返回的新token;
Q:刷新token功能,是否会有并发失效的功能?
A:可能会,这里要新增黑名单的延期失效功能,比如黑名单延期生效3分钟;
下一篇文章: 就用laravel框架 采用tymon/jwt 类具体实战演示一遍