Deno JWT token 應用

視頻演示:

https://www.bilibili.com/video/BV1BT4y1E7Nh/?p=12

一起來完成以下步驟:

  1. 引用之前的工程代碼

  2. 創建員工信息interface和員工數組array

  3. 生成token

  4. 校驗token是否正確

  5. 運行命令: deno run --allow-net --allow-read main.ts

import { Context } from "https://deno.land/x/oak/mod.ts";
import { key } from "../middlewares/key.ts";
//引入jwt 模塊功能
import { makeJwt, setExpiration, Jose, Payload } from "https://deno.land/x/djwt/create.ts"
import employees from "../models/employees.ts";

//獲取工程目錄方法
const { cwd } = Deno;
//jwt頭部
const header: Jose = {
    alg: "HS256",
    typ: "JWT",
}


/**
 * 定義Controller
 */
class Controller {
    /**
     * 首頁
     * @param ctx 
     */
    static async hello(ctx: any) {
        //cwd獲取當前工程目錄 
        //注意 ' !== `
        ctx.render(`${cwd()}/views/index.ejs`, {
            title: "Testing",
            data: { name: " Deepincoding" }
        });
    }

    //遊客
    static async guest(ctx: Context) {
        ctx.response.body = "Hi Guest";
    }


    //獲取token
    static async token(ctx: Context) {
        //獲取員工信息
        const { value } = await ctx.request.body();
        console.log({ value });
        //檢查員工是否存在
        const hadEmployee = employees.find(employee => {
            return employee.username === value.username && employee.password === value.password;
        });

        if (hadEmployee) {
            //JWT body 可以放任何你想放的內容
            const payload: Payload = {
                iss: hadEmployee.username,
                exp: setExpiration(new Date().getTime() + 60000),
            }
            //生成JWT
            const jwt = makeJwt({ key, header, payload });

            ctx.response.status = 200;
            //返回
            ctx.response.body = {
                id: hadEmployee.id,
                username: hadEmployee.username,
                jwt,
            }
        } else {
            ctx.response.status = 422;
            //返回提示信息
            ctx.response.body = {
                message: 'Invalid username or password'
            };
        }

    }
    //需要token才能訪問admin
    static async admin(ctx: Context) {
        ctx.response.body = "Hi Admin";
    }

}

//導出Controller
export default Controller;

#middlewares/authMiddleware.ts


import { Context } from "https://deno.land/x/oak/mod.ts";
import { validateJwt } from "https://deno.land/x/djwt/validate.ts"
import { key } from "./key.ts";

//定義 authMiddleware 檢查token有效性
const authMiddleware = async (ctx: Context, next: any) => {

    //token 放在header裏面傳過來
    const headers: Headers = await ctx.request.headers;
    
    const authorization = headers.get('Authorization')
    // 傳過來的token是否以bearer開頭 + 空格 
    if (!authorization || !authorization.split(' ')[1] ) {
      ctx.response.status = 401;
      return;
    }
    const jwt = authorization.split(' ')[1];
    //校驗token
    const isValidateJwt = await validateJwt(jwt, key);
  
    //如果token正確,程序繼續往下走,否則返回401
    if (isValidateJwt.isValid) {
      await next();
      return;
    }
    ctx.response.status = 401;
    ctx.response.body = { message: 'Invalid jwt token' };
}

export default authMiddleware;

#models/employee.ts

//定義interface
export interface Employee{
    id: string,
    username: string,
    password: string
}

//初始化員工列表
const employees: Array<Employee> =[
    { 
        id: "1",
        username: "michael",
        password: "123456"
    },
    {
        id: "2",
        username: "alex",
        password: "654321"
    }
]
//導出
export default employees;

#routers/router.ts


//引入 Router
import { Router } from "https://deno.land/x/oak/mod.ts";
//引入自定義Controller
import Controller from "../controllers/Controller.ts";
import authMiddleware from "../middlewares/authMiddleware.ts";

//創建 router
const router = new Router();

//首頁uri
router.get("/",Controller.hello);

//不需要token可以訪問guest
router.get("/guest",Controller.guest);
//根據用戶名和密碼獲取token
router.post("/token",Controller.token);
//這裏加上token校驗的方法
router.get("/admin",authMiddleware,Controller.admin);


//導出 router
export default router;

#main.ts

//引入 Application
import { Application } from "https://deno.land/x/oak/mod.ts"
//引入頁面渲染模塊
import {viewEngine,engineFactory,adapterFactory} from "https://deno.land/x/view_engine/mod.ts";
//引入 router
import router from "./routers/router.ts";

//獲取頁面引擎
const ejsEngine = engineFactory.getEjsEngine();
//獲取oak適配器
const oakAdapter = adapterFactory.getOakAdapter();

// 創建app
const app = new Application();

// 應用頁面渲染引擎
app.use(viewEngine(oakAdapter,ejsEngine));
//應用 router
app.use(router.routes());
app.use(router.allowedMethods());

//log日誌
console.log("Server Port 8000");

await app.listen({port: 8000 })

 

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