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接口返回結果如圖
在這裏插入圖片描述

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