jwt鉴权 Nodejs【学习笔记】

发布于:2025-07-17 ⋅ 阅读:(21) ⋅ 点赞:(0)

什么是 jwt?

JWT(JSON WEB Token)是一种开放的标准(RFC 7519),用于在网络应用间传递消息的一种方式。它是一种基于 JSON 的安全令牌,用于在客户端和服务端之间传输信息。官网地址

JWT由三部分组成,它们通过点 · 进行分隔:

  • Header(头部):包含了;令牌的类型和使用的加密算法等信息。通常采用 Base64 编码表示。
  • Payload(负载):包含了身份验证和授权等信息,如用户ID、角色、权限等,也可以自定义其他信息、同样采用 Base64 编码表示。
  • Signature(签名):使用指定的密钥对头部和负载进行签名,以确保令牌的完整性和真实性。

JWT 的工作流程如下:

  1. 用户提供有效的凭证(例如用户名和密码)进行身份验证。
  2. 服务器验证凭证,并生成一个 JWT 作为响应。JWT 包含了用户的身份信息和其他必要的数据。
  3. 服务器将 JWT 发送给客户端。
  4. 客户端在后续的请求中,将 JWT 放入请求的头部或其他适当的位置。
  5. 服务器在接收到请求后,验证 JWT 的签名以确保其完整性和真实性。如果验证通过,服务器使用 JWT 中的信息进行授权和身份验证。

依赖安装

  • passport:一个流行的用于身份验证和授权的Node.js库。
  • passport-jwt:是passport库的一个插件,用于支持使用 JSON WEB Token(JWT)进行身份验证和授权。
  • jsonwentoken:生成 Token 的库。
npm i passport passport-jwt jsonwebtoken

代码编写

src/jwt/index.ts

import { injectable } from "inversify";
import passport from "passport";
import jsonwebtoken from "jsonwebtoken";
import { Strategy, ExtractJwt } from "passport-jwt";

@injectable()
export class JWT {
    private secret: string = "fishcat should be happy!";
    private opts = {
        jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), // 从请求头中获取token
        secretOrKey: this.secret, // 密钥
    };

    constructor() {
        this.strategy(); // 初始化jwt策略
    }

    /* 初始化jwt */
    public strategy() {
        const strate = new Strategy(this.opts, (jwtPayload, done) => {
            // 验证token 自定义逻辑
            if (jwtPayload) {
                console.log('jwtPayload', jwtPayload)
                return done(null, jwtPayload); // 验证成功,返回用户信息
            } else {
                return done(null, false); // 验证失败,返回false
            }
        });
        // passport-jwt只是一个插件,不能直接使用,需要通过passport.use()方法注册到passport中
        passport.use(strate);
    }

    static middleware() {
        return passport.authenticate("jwt", { session: false }); // 不使用session
    }

    /* 创建token */
    public createToken(data: object) {
        return jsonwebtoken.sign(data, this.secret, { expiresIn: "7d" }) // 7天过期 1h 一小时
    }

    /* 初始化passport中间件 */
    public init() {
        return passport.initialize();
    }
}

services.ts

import { injectable, inject } from "inversify";
import { JWT } from "../jwt";
@injectable()
export class TokenService {
    constructor(@inject(JWT) private readonly jwt: JWT) { }

    public async createToken(user: object) {
        return this.jwt.createToken(user); // 创建token
    }
}

controller.ts

/* 控制层,不做具体功能实现 */
import { controller, httpGet as Get, httpPost } from "inversify-express-utils";
import { UserService, TokenService } from "./services"; // 引入服务层,它也可以当做一个类型
import { inject } from "inversify";
import type { Request, Response } from "express";
import { JWT } from "../jwt";

// 控制器,它是一个装饰器,接收一个路径参数
@controller("/user")
export class User {
    /**
     * @inject(UserService) 装饰器,提供依赖注入
     * private readonly 私有的 不可更改的
     * userService: UserService 依赖的服务名称及其类型
     * userService 左边的是修饰器的参数,右边是类型
     */
    constructor(@inject(UserService) private readonly userService: UserService) {
        // 这里可以做一些初始化操作,比如注入服务

    }

	// 修饰器中的第二个参数使用中间件鉴权 如果没有传 token 就会401
    @Get("/list", JWT.middleware())
    public async getIndex(req: Request, res: Response) {
        const data = await this.userService.getUserList(); // 调用服务层的方法
        // 做了鉴权之后,可以从 req.user 直接获取 token 包含的信息
        res.json({ data, info: req.user }) // 返回数据
    }

    @httpPost("/add")
    public async createUser(req: Request, res: Response) {
        const data = await this.userService.addUser(req.body);
        res.json({ data })
    }
}

@controller("/getToken")
export class Token {
    constructor(@inject(TokenService) private readonly token: TokenService) { }

    @Get("/")
    public async createToken(req: Request, res: Response) {
        const token = await this.token.createToken({ name: "fishcat", code: "0221418512" });
        res.json({ token, params: req.params })
    }
}

main.ts

// 引入 reflect-metadata 以支持装饰器,必须顶层
import "reflect-metadata";
import express from "express";
import { InversifyExpressServer } from "inversify-express-utils";
import { Container } from "inversify";
import { JWT } from "./src/jwt"; // 引入 jwt 模块
import { TokenService } from "./src/user/services";
// 创建一个 Inversify 容器
const container = new Container();

/**
 * jwt模块 注入容器
 */
container.bind(JWT).toSelf(); // 绑定 JWT 模块"

container.bind(TokenService).toSelf(); // 绑定 TokenService 服务

// 创建一个 InversifyExpressServer 实例,传入容器
const server = new InversifyExpressServer(container);
// 设置中间件
server.setConfig((app) => {
    app.use(express.json()); // 解析 JSON 请求体
    app.use(container.get(JWT).init()); // 关联 express
});
// 创建服务
const app = server.build();


app.listen(3000, () => {
    console.log("Server is running on http://localhost:3000");
});

不传 token,返回结果 401,校验不通过
在这里插入图片描述
传入 token,结果正常响应。
在这里插入图片描述
参考:
https://xiaoman.blog.csdn.net/article/details/136312225


网站公告

今日签到

点亮在社区的每一天
去签到