关于前端:jwt实现token鉴权nodejs-koa

6次阅读

共计 1944 个字符,预计需要花费 5 分钟才能阅读完成。

为什么须要 token?

在后盾管理系统中,咱们通常应用 cookie-session 的形式用于鉴权,如何通过 cookie、session 鉴权(nodejs/koa)但这种形式存在着以下问题

  1. 比方 cookie 的容量太小
  2. 浏览器端和 app 端发送 http 申请时携带 cookie 会有差别
  3. 分布式系统和服务器集群保障如何保障 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){}
正文完
 0