当前位置: 首页 > java >正文

NestJS 系列教程(五):守卫(Guards)与 JWT 用户认证

🛡️ NestJS 系列教程(五):守卫(Guards)与 JWT 用户认证

✨ 本篇目标

你将学会:

  • 什么是守卫(Guard)?与中间件有何不同?
  • 如何使用守卫进行访问控制
  • 使用 Passport 和 JWT 实现用户登录认证
  • 基于角色控制访问权限

🤔 守卫(Guard)是什么?

守卫是用于控制请求是否被执行的机制,通常用于认证和授权。

它拦截请求,执行逻辑判断:

  • 如果返回 true,请求继续;
  • 如果返回 false 或抛出异常,请求被拒绝。

与中间件不同的是,守卫能访问路由处理上下文(比如 handler metadata)和参数装饰器的值,适合做「权限控制」。


🧱 搭建 Auth 模块

创建认证模块及其控制器和服务:

nest g module auth
nest g controller auth
nest g service auth

安装 Passport 和 JWT:

npm install @nestjs/passport passport @nestjs/jwt passport-jwt
npm install --save-dev @types/passport-jwt

🔐 AuthService(模拟用户登录)

auth.service.ts 中:

import { Injectable } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';@Injectable()
export class AuthService {constructor(private jwtService: JwtService) {}// 模拟验证用户名和密码async validateUser(username: string, pass: string): Promise<any> {const user = { userId: 1, username: 'admin', password: '123456', role: 'admin' };if (username === user.username && pass === user.password) {const { password, ...result } = user;return result;}return null;}async login(user: any) {const payload = { username: user.username, sub: user.userId, role: user.role };return {access_token: this.jwtService.sign(payload),};}
}

📦 配置 AuthModule 与 JWT

auth.module.ts 中:

import { Module } from '@nestjs/common';
import { AuthService } from './auth.service';
import { AuthController } from './auth.controller';
import { JwtModule } from '@nestjs/jwt';
import { JwtStrategy } from './jwt.strategy';@Module({imports: [JwtModule.register({secret: 'my-secret-key', // 实际项目应放在 .env 文件signOptions: { expiresIn: '1h' },}),],controllers: [AuthController],providers: [AuthService, JwtStrategy],exports: [AuthService],
})
export class AuthModule {}

✍️ 编写登录接口

auth.controller.ts 中:

import { Controller, Post, Body, UnauthorizedException } from '@nestjs/common';
import { AuthService } from './auth.service';@Controller('auth')
export class AuthController {constructor(private readonly authService: AuthService) {}@Post('login')async login(@Body() body: any) {const user = await this.authService.validateUser(body.username, body.password);if (!user) {throw new UnauthorizedException('Invalid credentials');}return this.authService.login(user);}
}

🧠 实现 JWT 策略(Strategy)

创建 jwt.strategy.ts

import { Injectable } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { ExtractJwt, Strategy } from 'passport-jwt';@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {constructor() {super({jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),ignoreExpiration: false,secretOrKey: 'my-secret-key',});}async validate(payload: any) {return { userId: payload.sub, username: payload.username, role: payload.role };}
}

🛡️ 创建 JWT 守卫(Guard)

创建 jwt-auth.guard.ts

import { Injectable } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {}

使用方式:

@UseGuards(JwtAuthGuard)
@Get('profile')
getProfile(@Request() req) {return req.user;
}

🧑‍⚖️ 创建角色守卫(RoleGuard)

定义 roles.decorator.ts

import { SetMetadata } from '@nestjs/common';export const Roles = (...roles: string[]) => SetMetadata('roles', roles);

定义 roles.guard.ts

import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { Reflector } from '@nestjs/core';@Injectable()
export class RolesGuard implements CanActivate {constructor(private reflector: Reflector) {}canActivate(context: ExecutionContext): boolean {const requiredRoles = this.reflector.getAllAndOverride<string[]>('roles', [context.getHandler(),context.getClass(),]);if (!requiredRoles) return true;const { user } = context.switchToHttp().getRequest();return requiredRoles.includes(user.role);}
}

使用方式:

@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('admin')
@Get('admin')
getAdminStuff() {return '只有管理员能看到';
}

🧪 测试认证流程

  1. 调用 POST /auth/login 获取 token
  2. 在后续请求中添加 Header:
Authorization: Bearer <token>
  1. 访问受保护路由 /cats/admin,根据角色控制访问权限

✅ 本章小结

你已经学会:

  • 守卫的原理和使用场景
  • 使用 JWT + Passport 实现用户登录认证
  • 编写角色守卫控制访问权限
  • 使用装饰器、策略和守卫构建灵活的权限体系

🔮 下一篇预告

第6篇:拦截器(Interceptor)与统一响应格式封装

我们将讲解如何使用拦截器对响应结果统一封装、记录日志、实现响应缓存等能力。

http://www.xdnf.cn/news/15192.html

相关文章:

  • 【Elasticsearch】post_filter
  • 代码审计-Struts2漏洞分析
  • java进阶(一)+学习笔记
  • 【嵌入式】51单片机学习笔记-Keil5软件安装教程
  • 【6.1.3 漫画分布式锁】
  • 算法魅力-BFS解决最短路问题
  • Android音视频探索之旅 | C++层使用OpenGL ES实现视频渲染
  • 【文献阅读】DEPTH PRO: SHARP MONOCULAR METRIC DEPTH IN LESS THAN A SECOND
  • AI:机器人行业发展现状
  • 【软件测试面试】面试了字节、美团、腾讯等30几家公司后,才知道软件测试面试全是这个套路......
  • PyVision:基于动态工具的具身智能体
  • linux学习第30天(线程同步和锁)
  • 【世纪龙科技】比亚迪新能源汽车结构原理体感教学软件
  • 从零到一:企业如何组建安全团队
  • CSS选择器进行定位
  • 医疗AI前端开发中的常见问题分析和解决方法
  • 计算机视觉与深度学习 | 基于Matlab的多特征融合可视化指纹识别系统(附完整代码)
  • 电脑上如何查看WiFi密码
  • [BUUCTF 2018]Online Tool
  • tp8.0\jwt接口安全验证
  • 什么是 Bootloader?怎么把它移植到 STM32 上?
  • 《人件》第六章 快乐地工作
  • Python-难点-uinttest
  • 秋招笔试考什么?如何针对性去练习?
  • w459客户管理系统
  • xml映射文件的方式操作mybatis
  • 多线程进阶——JUC的常见类
  • 跨系统开发代码换行符如何解决
  • docker-compose方式搭建lnmp环境——筑梦之路
  • 2025 XYD Summer Camp 7.10 筛法