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