Skip to content

Nest 使用 JWT

配置文件

我这里用的dev.yml文件

bash
# jwt 配置
jwt:
  secretkey: 'jsopy'
  expiresin: '1h'
  refreshExpiresIn: '2h'

安装

bash
pnpm i -S @nestjs/jwt passport-jwt @types/passport-jwt

新建 jwt 模块

bash
nest g module jwt
nest g service jwt
  • 这样就挂载到 app.module.ts 文件上了

代码

我这里的配置文件 用的是 .yml文件

  • jwt.module.ts
ts
import { Global, Module } from "@nestjs/common";
import { JwtModule } from "@nestjs/jwt";
import { ConfigService } from "@nestjs/config";
import { JwtServiceAll } from "./jwt.service";

@Global()
@Module({
  imports: [
    JwtModule.registerAsync({
      global: true,
      inject: [ConfigService],
      useFactory: async (configService: ConfigService) => ({
        secret: configService.get("jwt").secretkey,
        signOptions: {
          expiresIn: configService.get("jwt").expiresin,
        },
      }),
    }),
  ],
  providers: [JwtServiceAll],
  exports: [JwtModule, JwtServiceAll],
})
export class JwtAllModule {}
  • jwt.service.ts
ts
import { Injectable, Inject } from "@nestjs/common";
import { JwtService } from "@nestjs/jwt";
import { ConfigService } from "@nestjs/config";
@Injectable()
export class JwtServiceAll {
  // 注入配置文件
  @Inject()
  private readonly configService: ConfigService;
  constructor(private readonly jwtService: JwtService) {}

  async setToken(userInfo: any) {
    // 这里不能写用户密码,怕破译
    const payload = {
      sub: userInfo.id, // sub 就是用户名称
      username: userInfo.username, // username 就是用户姓名
    };
    const result = await this.jwtService.sign(payload);
    // 生成token
    return result;
  }
  // 验证token
  verifyToken(token: string) {
    return this.jwtService.verify(token, {
      secret: this.configService.get("jwt").secretkey,
    });
  }
  // refreshToken
  async setRefreshToken(userInfo: any) {
    const payload = {
      sub: userInfo.id, // sub 就是用户名称
      username: userInfo.username, // username 就是用户姓名
    };
    const result = await this.jwtService.sign(payload, {
      expiresIn: this.configService.get("jwt").refreshExpiresIn,
    });
    return result;
  }
}

其他模块使用

  • user.service.ts
ts
import { Inject, Injectable } from "@nestjs/common";
import { RedisService } from "../redis/redis.service";
import { ConfigService } from "@nestjs/config";
import { JwtServiceAll } from "../jwt/jwt.service";
@Injectable()
export class UserService {
  // 注入配置文件
  @Inject()
  private readonly configService: ConfigService;
  // 注入Redis
  @Inject()
  private readonly redisService: RedisService;
  // 注入jwt
  @Inject()
  private readonly jwtService: JwtServiceAll;
  async redistest() {
    // 插入
    await this.redisService.set("name", "张三");
    // 查询
    const name = await this.redisService.get("name");
    // 插入过期时间 单位秒
    await this.redisService.set("age", 18, 60);
    return name;
  }
  // 测试redis
  async test() {
    const result = await this.configService.get("redis");
    return result;
  }

  // 2. 测试jwt
  async testjwt() {
    const result = await this.jwtService.setToken({ id: 1, username: "张三" });
    console.log(result);
    return result;
  }
}
  • user.controller.ts
ts
import {
  Controller,
  Get,
  Post,
  Body,
  Patch,
  Param,
  Delete,
} from "@nestjs/common";
import { UserService } from "./user.service";

@Controller("user")
export class UserController {
  constructor(private readonly userService: UserService) {}

  // 注册
  @Post("testjwt")
  async testjwt() {
    const token = await this.userService.testjwt();
    return {
      data: {
        token,
      },
    };
  }

  // 需要验证jwt
  @Post("testcheckjwt")
  async testcheckjwt() {
    return {
      data: "通过了",
    };
  }
}

守卫

  • 全局守卫
ts
import {
  CanActivate,
  ExecutionContext,
  Inject,
  Injectable,
} from "@nestjs/common";
import { Observable } from "rxjs";
import { GlobalCheckException } from "./globalcheck.exception";
import { ConfigService } from "@nestjs/config";
import { JwtServiceAll } from "../modules/jwt/jwt.service";
@Injectable()
export class GlobalGuard implements CanActivate {
  @Inject()
  private configService: ConfigService;
  @Inject()
  private jwtService: JwtServiceAll;
  canActivate(
    context: ExecutionContext
  ): boolean | Promise<boolean> | Observable<boolean> {
    //权限验证
    const request = context.switchToHttp().getRequest();
    // 白名单
    const whiteList = this.configService.get("perm").router.whiteList;
    // 验证
    if (whiteList.includes(request.url)) {
      return true;
    } else {
      // 判断
      const authorization = request.header("Authorization") || "";

      const bearer = authorization.split(" ");

      if (!bearer || bearer.length < 2) {
        throw new GlobalCheckException("登录 token 错误");
      }

      const token = bearer[1];
      try {
        const info = this.jwtService.verifyToken(token);
        // 我这里是解析出来后把userId赋值给request 这样控制器就拿到了
        (request as any).userId = info.sub; // 换成你自己的payload对应字段
        return true;
      } catch (e) {
        const result = JSON.stringify([{ message: "token 错误" }]);
        throw new GlobalCheckException(result);
      }
    }
  }
}

使用

  • 头部参数带上 Authorization: Bearer xxxx
bash

### 验证token

POST  http://localhost:5000/user/testcheckjwt
content-type: application/json
Authorization: bear eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOjEsInVzZXJuYW1lIjoi5byg5LiJIiwiaWF0IjoxNzU5NzEzNzcxLCJleHAiOjE3NTk3MTczNzF9.Pp9b6SOr8zykEJbYIEVMGbKQW-a_ESFCaaUhPSgxr_E