Koa2使用RSA256+jsonwebtoken的实现JWT验证

项目介绍

使用RSA256加密实现jwt鉴权最终获取token

项目开始

1.安装依赖

npm install jsonwebtoken

2.获取RSA公钥和私钥

(因系统不同命令有所不同 ,我这边是mac栗子)

openssl
genrsa -out rsa_private_key.pem 1024
pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt
rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem

完成后生成两个文件(rsa_private_key.pem 与 rsa_public_key.pem)
当然这块也可以修改文件名,我修改成了我喜欢的 ,并统一放到了文件夹下,如图所示:
在这里插入图片描述

代码实现

1.设置登录的路由

    koa.use(koaRoute.post('/sessions', controller.post.bind(controller)))

2.Controller层SessionsController.js

//登录post接口
post (ctx) {
      //首先判断headers不能为空
    if (ctx.headers.authorization === undefined || ctx.headers.authorization === null || ctx.headers.authorization === '') {
      ctx.throw(400, 'Authorization header must be provided!')
    } else {
      return this._handleAuthorization(ctx)
    }
  }

  _handleAuthorization (ctx) {
    const [type] = ctx.headers.authorization.split(' ')
    if (type.toLowerCase() === 'basic') {
      return this._handleBasicAuthentication(ctx)
    } else {
      ctx.throw(400, 'Invalid authentication type!')
    }
  }

  _handleBasicAuthentication (ctx) {
    const [, base64String] = ctx.headers.authorization.split(' ')
console.log(base64String)
    const [username, password] = Buffer.from(base64String, 'base64').toString().split(':')
    console.log(username + password)
    return this.getUserByCredentials(username, password)
      .then(user => this._handleUser(ctx, user))
      .then(jwt => this._respondWithJwt(ctx, jwt))
  }

  async getUserByCredentials (username, password) {
      //密码加密
    const passwordHash = crypto.createHash('sha256')
      .update(password)
      .digest('hex')
      console.log(passwordHash)
    const user = await this._getUserByUsername(username)
    console.log(user)
    if (user === null) {
      return null
    } else {
      if (user.passwordHash === passwordHash) {
        return user
      } else {
        return null
      }
    }
  }


  _getUserByUsername (username) {
  //查询user表用户名和传入的用户名是否一样
    return this._User.findOne({
      where: { userName: username }
    })
  }

  _handleUser (ctx, user) {
    if (user === null) {
      ctx.throw(400, 'Invalid user!')
    } else {
        const payload = {
            usr: user.id,
            role: user.role,
            name: user.name
          }
          console.log(payload)
          return this._generateJwt(payload)
    }
  }

// jwt.sign(payload, secretOrPrivateKey, [options, callback])
//   第一个是token载体,放一些需要存放在token里的内容,我这里希望token传递userId,role,name
//   第二个是密钥,可以简单的输入string作为密钥,也可以采用加密算法,例如我现在用的RSA256
//   第三个是option,因为jsonwebtoken加密方式默认是RS256,所以如果用其他加密方式需要在option的algorithm中进行申明,以及其他一些参数
  _generateJwt (payload) {
    const minutes = 432000
    const privateKey = fs.readFileSync('rsaKeys/jwtRS256.key')
    const options = { algorithm: 'RS256', expiresIn: minutes * 60 }
    return jwt.sign(payload, privateKey, options)
  }

  _respondWithJwt (ctx, jwt) {
    ctx.status = 201
    ctx.body = jwt
    return ctx
  }
}

3.入口文件引入(app.js)

const jwt = require('koa-jwt')
const fs = require("fs")
const publicKey = fs.readFileSync('./rsaKeys/jwtRS256.key.pub')//引用公钥
app.use(jwt({
  secret: publicKey,
  key:'token'
}).unless({
  path: ['/sessions']
}));

测试登录接口

1.插件测试登录接口,返回token

我这里用的是谷歌自带的插件测试接口
在这里插入图片描述
headers 里Authorization输入登录的用户名密码
在这里插入图片描述
设置这里就结束里 触发send按钮 就返回得到token
在这里插入图片描述

2.测试其他接口加上token访问

不带token,接口返回结果如图(401)
在这里插入图片描述
带token接口返回结果如图
在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章