共计 1944 个字符,预计需要花费 5 分钟才能阅读完成。
为什么须要 token?
在后盾管理系统中,咱们通常应用 cookie-session 的形式用于鉴权,如何通过 cookie、session 鉴权(nodejs/koa)但这种形式存在着以下问题
- 比方 cookie 的容量太小
- 浏览器端和 app 端发送 http 申请时携带 cookie 会有差别
- 分布式系统和服务器集群保障如何保障 sessionId 是雷同
基于以上问题,有了 token 这种形式,token 的鉴权不受浏览器或 app 端的限度,通用性安全性都更强。
数据格式实现 token 的鉴权形式通常应用 jwt,即 json web token,jwt 的格局如 xxx.yyy.zzz
- xxx 的局部用来形容应用什么样的加密形式
- yyy 的局部是携带的数据,比方 id,name,通常还会携带 iat(issue at)公布工夫,exp(expiration time)过期工夫,用于鉴权的时候判断此 token 是否在有效期内,以上 xxx 和 yyy 都是对 json 数据以 base64 编码的形式进行转换
- zzz 是对 xxx.yyy 再加上密钥进行加密,加密的形式在 header 中。
比方上图中,服务器生成 token 应用的加密形式是 HS256,需保留的内容为 id 和 name,密钥为 123456
-
header 局部
{"alg":"HS256","typ":"JWT"} // base64 编码后果:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
-
playload 局部
{"id":1,"name":"Alice","iat":1630814528619,"exp":1630816048023} // base64 编码后果:eyJpZCI6MSwibmFtZSI6IkFsaWNlIiwiaWF0IjoxNjMwODE0NTI4NjE5LCJleHAiOjE2MzA4MTYwNDgwMjN9
-
signature 局部
// 加密后果为:B2df_qYbivZcjpJ_QtIyRu4ts6n_pwxlSQl41Bpsxz8
最初的后果就是把三局部拼接起来,以 . 分隔
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwibmFtZSI6IkFsaWNlIiwiaWF0IjoxNjMwODE0NTI4NjE5LCJleHAiOjE2MzA4MTYwNDgwMjN9.B2df_qYbivZcjpJ_QtIyRu4ts6n_pwxlSQl41Bpsxz8
能够看到 jwt 的 header 和 payload 都是用 base64 进行编码的,也可解码,所以并不能寄存重要信息,而 jwt 数据的传递也不是为了加密重要信息,jwt 的 singature 局部是须要通过密钥来加密的,只有密钥不泄露,身份就不容易被伪造。
如何应用
jwt 能够用于客户端向服务器发送的申请的时候携带,搁置到 header 中,应用 authorization 这个字段,应用 Bearer 的形式
公钥和私钥
- 对称加密算法,只用一个密钥加密和解密
- 非对称加密算法,公钥用于加密,私钥用于解密
openssl 中能够生成公钥和私钥
// 生成公钥
genrsa -out private.key 2048
// 生成私钥
rsa -in private.key -puout -out public.key
别离生成 public.key 和 private.key 文件
服务器如何鉴权
用户登录胜利后,服务器返回 token,以 Koa 来做个演示
const jwt = require("jsonwebtoken")
const PRIVATE_KEY = fs.readFileSync('./private.key')
const user = {id: 1, name: 'kiki'}
const token = jwt.sign(user, PRIVATE_KEY, {
expiresIn: 10, // 单位 s
algorithm: "RS256"
})
客户端将在 header 中的 authorization 携带 token 数据,服务器校验 token 的有效性和正确性
const PUBLIC_KEY = fs.readFileSync('./public.key')
const authorization = ctx.headers.authorization
const token = authorization.replace("Bearer", "")
// 如果失败会间接报错, 所以须要捕捉
try {
const result = jwt.verify(token, PUBLIC_KEY, {algorithms: ["RS256"]
})
// 拿到的信息是 {id: 1, name: 'kiki', iat: '', exp:''}
} catch(error){}
正文完