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

为什么须要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){
    
}

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理