NodeJS中token生成與認證

  • 導入依賴

    koa、koa-router、basic-auth、jsonwebtoken

    // package.json
    "dependencies": {
        "basic-auth": "^2.0.1",
        "jsonwebtoken": "^8.4.0",
        "koa": "^2.7.0",
        "koa-router": "^7.4.0"
      }
    
  • 生成token

    const jwt = require('jsonwebtoken')
    
    const generateToken = function(uid, scope){
        const secretKey = "abcdefg"; // 生成token時的密鑰,不能泄露
        const expiresIn = 60*60; // 生成的token的有效期
        // 生成token
        // 第一個參數是我們要存儲到token中的用戶信息數據,uid是用戶id,scope是用戶權限;
        // 第二個參數是加密的密鑰;
        // 第三個參數是附帶的屬性信息,expiresIn是生成的token的有效期
        const token = jwt.sign({
            uid,
            scope
        },secretKey,{
            expiresIn
        })
        return token
    }
    
  • token認證

    • 編寫token認證的中間件

      const baseAuth = require("basic-auth");
      const jwt = require("jsonwebtoken");
      
      class Authenticate {
          constructor() {
          }
      
          // auth是屬性,不是方法,返回值是一個方法(中間件)
          get auth() {
              // 返回token認證中間件(中間件是一個函數,而不能是對象)
              return async (ctx, next) => {
                  // 注意baseAuth的參數是ctx.req,而不是ctx.request,ctx.req是node.js原生的request對象,而ctx.request是koa對原生request封裝後的對象
                  const userToken = baseAuth(ctx.req);
                  if(!userToken || !userToken.name) {
                      // 拋出自定義的異常
                      throw new global.errors.Forbidden("token令牌不能爲空");
                  }
                  let decode;
                  try {
                      // 跟生成token時的密鑰要保持一直,可以放在配置文件中
                      const secretKey = "abcdefg";
                      // 對token進行解密操作,獲取保存到token中的用戶信息
                      decode = jwt.verify(userToken.name, secretKey);
                  } catch(error) {
                      if(error.name === "TokenExpiredError") {
                          throw new global.errors.Forbidden("token令牌已過期");
                      }
                      throw new global.errors.Forbidden("token令牌無效");
                  }
                  // 將用戶信息保存到ctx中,可以在其他的中間件中獲取到
                  ctx.auth = {
                      uid: decode.uid,
                      scope: decode.scope
                  }
                  // 前面必須要加上await,才能保證洋蔥模型,如果不調用next(),就不會執行下一個中間件
                  await next();
              }
          }
      }
      
      module.exports = {
          Authenticate
      };
      
    • 使用token認證中間件

      const Router = require("koa-router");
      const {Authenticate} = require("../../../middlewares/authenticate");
      const router = new Router({
          prefix: "/v1/classic" // 路由前綴
      })
      
      // router上可以註冊多箇中間件,按照註冊順序執行,比如這裏註冊了兩個中間件,第一個參數是路由地址,後面兩個參數都是中間件
      router.get("/laster", new Authenticate().auth(第一個中間件), (ctx, next) => {
        ctx.body = ctx.auth;
      }(第二個中間件))
      

      如果第一個中間件(new Authenticate().auth)中認證token沒有通過導致拋出了異常,就不會進入到下一個中間件中()

    • 訪問:url GET http:localhost:8082/v1/classic/laster

      在PostMan中發送請求,請求方式是GET,Authenrizention的Type選擇Base Auth,參數Username填上面生成的token,Password空着不填

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