nestjs守卫/全局守卫校验jwt

一、守卫

目标

部分接口需要用户登录后才可以访问,用户登录后可以颁发 jwt_token 给前端,前端在调用需要鉴权的接口,需要在请求头添加 jwt_token,后端校验通过才能继续访问,否则返回403无权访问

创建守卫 anth

安装依赖
npm i @nestjs/jwt -S
配置 jwt 常量参数 constants/index.ts
// jwt秘钥,固定随机字符串
export const JWT_SECRET = "NODE_TEST_SECRET";// jwt有效期 Eg: "60s", "3h", "2d"
export const JWT_EXPIRES = "2h"; // 2小时
创建 auth 模块 auth/auth.module.ts
import { Module } from '@nestjs/common';
import { JwtModule } from '@nestjs/jwt';
import { AuthService } from './auth.service';
import { JWT_SECRET, JWT_EXPIRES } from '../constants';@Module({imports: [JwtModule.register({secret: JWT_SECRET, // jwt秘钥signOptions: {expiresIn: JWT_EXPIRES, // jwt有效期}})],providers: [AuthService],exports: [AuthService]
})
export class AuthModule {}
创建 auth 服务 auth/auth.service.ts
import { Injectable } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';@Injectable()
export class AuthService {constructor(private readonly jwtService: JwtService) {}// 创建jwt_tokenasync createToken(userInfo) {// 将用户信息(userId、name)存放到 jwt 中return {access_token: this.jwtService.sign(userInfo)};}// 校验登录状态validateToken(token) {if (!token) {return false;}try {return this.jwtService.verify(token);} catch {return false;}}
}
创建 auth 守卫 auth/auth.guard.ts
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { AuthService } from './auth.service';@Injectable()
export class AuthGuard implements CanActivate {constructor(private authService: AuthService) {}canActivate(context: ExecutionContext) {const request = context.switchToHttp().getRequest();const token = request.headers['authorization']; // 从请求头中获取 tokenif (!token) {return false;} else {return this.authService.validateToken(token); // 如果 token 有效,返回 true,允许访问资源}}
}

使用守卫 auth

需要鉴权的模块添加 auth 模块

api.module.ts

...
import { AuthModule } from '../auth/auth.module';@Module({imports: [AuthModule],...
})
export class ApiModule {}
需要鉴权的接口引入守卫

api.controller.ts

...
import { Controller, Get, UseGuards } from '@nestjs/common';
import { AuthGuard } from '../auth/auth.guard';@Controller('api')
export class ApiController {constructor(private readonly apiService: ApiService) {}@Get('getUserInfo')@UseGuards(AuthGuard) // 需要鉴权的接口添加UseGuardsgetUserInfo(): any {return this.apiService.getUserInfo();}
}
登录

调用 auth/auth.service.ts 中的 createToken 生成 jwt_token 返回给前端

前端在请求头添加 authorization

如果请求头没有 authorization,或者 authorization 失效,则返回 403 Forbidden

二、全局守卫

目标

由于单个守卫需要引入守卫模块、守卫方法,并且针对每一个接口加 @UseGuards 装饰器,使用起来比较繁琐。项目中经常遇到非常多的接口都需要鉴权,所以就需要使用全局守卫来校验需要鉴权的接口。

注意:获取与解析 jwt_token 的方法上面守卫的方法一致,auth/auth.service,此处不再赘述。

创建全局守卫

配置需要鉴权的接口常量 constants/index.ts
// 需要校验 jwt 的 url 列表
export const ValidUrlList = ['/api/getUserInfo','/api/product/buy','/api/queryUserWallet'
];
新建全局守卫 global.guard.ts
import { Injectable, NestInterceptor, ExecutionContext, HttpException, HttpStatus } from '@nestjs/common';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { AuthService } from './auth/auth.service';
import { ValidUrlList } from './constants';@Injectable()
export class GlobalGuard implements NestInterceptor {constructor(private authService: AuthService) {}intercept(context: ExecutionContext, next): Observable<any> {// 在这里执行全局守卫逻辑const request = context.switchToHttp().getRequest();// 从请求头中获取 tokenconst token = request.headers['authorization'];// 请求的url,用于判断是否需要校验jwtconst url = request.url;if (ValidUrlList.includes(url)) {// 需要鉴权才能访问的接口const validRes = this.authService.validateToken(token);if (!validRes) {return next.handle().pipe(map(() => {// 如果没有提供令牌,返回错误响应或执行其他逻辑return new HttpException('Forbidden', HttpStatus.FORBIDDEN);}));}}// 不需要校验的接口、校验通过的接口直接放行return next.handle();}
}

在 app.module.ts 配置全局守卫

// ...
import { APP_INTERCEPTOR } from '@nestjs/core';
import { JwtModule } from '@nestjs/jwt';
import { GlobalGuard } from './global.guard';
import { JWT_SECRET, JWT_EXPIRES } from './constants';
import { AuthService } from './auth/auth.service';@Module({imports: [JwtModule.register({secret: JWT_SECRET, // jwt秘钥signOptions: {expiresIn: JWT_EXPIRES, // jwt有效期}}),],providers: [{provide: APP_INTERCEPTOR,useClass: GlobalGuard,},AuthService],
})
export class AppModule {}

三、swagger文档调用需要鉴权的接口

目标

接口添加 jwt 鉴权后,接口文档调用接口请求头没有添加 authorization,请求会返回403。为此,需要给文档需要鉴权的接口请求头也添加 authorization

步骤

main.ts 配置 BearerAuth 校验
const config = new DocumentBuilder().setTitle('接口文档').setDescription('接口文档描述').setVersion('1.0').addBearerAuth() // 注意此处:文档添加BearerAuth.build();
const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup('api-docs', app, document);
在需要鉴权的接口添加 @ApiBearerAuth() 装饰器
import { ApiBearerAuth } from '@nestjs/swagger';@Controller('api')
@ApiBearerAuth() // 在此处添加,表示/api/的接口请求头全都需要添加authorization
export class ApiController {@Get('getUserInfo')@UseGuards(AuthGuard)@ApiBearerAuth() // 在此处添加,表示当前接口请求头需要添加authorizationgetUserInfo(): any {return this.apiService.getUserInfo();}
}
使用

先调用登录接口获取到 jwt_token

点击文档顶部Authorize按钮

输入获取到的 jwt_token,并点击Authorize,然后关闭弹窗

再调用需要鉴权的接口,就可以鉴权通过了

注意:请求头的 Authorization 参数会在最前面添加 Bearer 字符,可以在守卫中将此字符移除

this.jwtService.verify(token.replace('Bearer ', ''))

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/221177.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

debezium数据脱敏配置介绍及源码分析

debezium官网地址参考&#xff1a; Debezium connector for MySQL :: Debezium Documentation 欢迎关注留言&#xff0c;我是收集整理小能手&#xff0c;笔芯笔芯. CDC采集数据时会有字段包含敏感字符需要做脱敏处理&#xff0c;debezium提供了4种脱敏方案&#xff0c;注意只…

mysql:不要在索引列进行数学运算和函数运算

不要在索引列进行数学运算和函数运算。这是因为数学运算和函数运算会改变索引列的值&#xff0c;导致索引失效。 如果需要进行计算或函数处理&#xff0c;最好将数据取出并在应用程序中进行处理。 下面举个对照的例子&#xff1a; 1&#xff09;看语句explain select * from …

注塑模具ERP有哪些功能?可以帮助企业解决什么难题

不同的注塑模具有不同的业务流程和生产环节&#xff0c;有些生产企业在订单、物料需求计划、车间、班组负荷评估、项目成本核算、边角料统计分析等方面还存在不少问题。 与此同时&#xff0c;也有部分注塑模具企业通过ERP软件科学制定注塑生产排产&#xff0c;智能核算注塑物料…

09 光流法实践

文章目录 09 光流法实践9.1 光流法9.2 直接法9.3 总结 09 光流法实践 光流法需要提取关键点&#xff0c;而不需要计算描述子&#xff1b;直接法直接利用像素信息&#xff0c;无需特征点。 9.1 光流法 光流法基于 灰度不变假设&#xff0c;即第一帧中的关键点的灰度与其在第二…

用print太慢了!强烈推荐这款Python Debug工具~

作为程序员&#xff0c;我们都深知调试&#xff08;Debug&#xff09;在编程过程中的重要性。然而&#xff0c;使用传统的"print"语句进行调试可能效率较低&#xff0c;今天&#xff0c;笔者将推荐一款独具一格的Python调试工具——Reloadium。Reloadium为IDE添加了热…

深入理解Spring Security授权机制原理

原创/朱季谦 在Spring Security权限框架里&#xff0c;若要对后端http接口实现权限授权控制&#xff0c;有两种实现方式。 一、一种是基于注解方法级的鉴权&#xff0c;其中&#xff0c;注解方式又有Secured和PreAuthorize两种。 Secured如&#xff1a; 1 PostMapping("…

elementui select中添加新增标签

<el-select v-model"ruleForm.eventType" :placeholder"请选择事件类型&#xff0c;可手动添加" ref"template" clearable visible-change"(v) > visibleChange(v, template)"><el-option v-for"item in eventTypeOp…

多域名SSL证书选择什么品牌比较好?

选择适合的品牌是申请多域名SSL证书的重要一步。不同品牌的SSL证书提供商在性能、安全性和客户支持等方面各有特点。本文将详细介绍选择多域名SSL证书品牌时应考虑的因素&#xff0c;并推荐几个知名的SSL证书品牌。 首先&#xff0c;我们需要考虑的是品牌的声誉和可靠性。选择一…

短地址漏洞

漏洞条件&#xff1a; 当地址的长度不足 20 byte (40个十六进制字符) 时&#xff0c;以太坊虚拟机 EVM 会进行高位补0x0转发以太币时没有对地址长度进行验证 1. input 数据 交易的 input 数据分为三个部分&#xff1a; 1&#xff09;4字节&#xff0c;是方法名的Hash值&…

MySQL_11.InnoDB Buffer Pool原理与配置

1.buffer pool原理 (1)innodb_buffer_pool_instances&#xff1a; windows default 1个实例、windows default 8个实例; 将热点打散,提高并发的性能改善并发,通过降低竞争因为不同的线程读和写cached pages&#xff08;缓存页&#xff09; 内存小于1G默认1个,这个选项只有当设置…

Android开发中压缩文件和文件夹

Android开发中&#xff0c;我们经常会遇到上传文件&#xff0c;用到压缩文件、文件夹的功能&#xff0c;今天我们主要讲解这个功能&#xff0c;具体的实现如下&#xff1a; /*** 压缩文件和文件夹** param srcFileString 要压缩的文件或文件夹* param zipFileString 压缩完成的…

【论文极速读】视频检索中的模态均衡方法

【论文极速读】视频检索中的模态均衡方法 FesianXu 20231206 at Baidu Search Team 前言 传统的视频搜索系统相关性部分主要以文本匹配为基础手段&#xff0c;在其中引入多模态向量容易收到『模态不均衡』的问题&#xff0c;论文[1]尝试对其进行解决&#xff0c;本文进行笔记。…

【算法技术专题】精彩解密KMP算法之跃进式搜索的深度探索

KMP算法 KMP算法介绍KMP算法历史KMP算法思路性能损耗算法思路结构模型准备KMP算法的实现步骤生成next数组构建next数组原理生成nexf数组代码实现 代码案例解释说明 字符串对比操作代码案例解释说明 算法效果 KMP算法介绍 KMP算法&#xff08;Knuth-Morris-Pratt算法&#xff0…

02markdown-学习笔记

一级标题 二级标题 三级标题 四级标题 五级标题 六级标题 换行符<br>标签 写入一段测试用的正文第二段测试文本,如果要对文本进行换行可以使用<br>标签 文本修饰符 字体为斜体的修饰&#xff0c;一对星号包含 字符为粗体&#xff0c;两对星号包含 字体为…

springboot 拦截器之Advisor不生效问题

SPringBoot使用方法注解拦截器时遇到不生效问题记录&#xff1a; 定义方法注解 Target({ElementType.TYPE, ElementType.METHOD}) Retention(RetentionPolicy.RUNTIME) Inherited Documented public interface DataScope {boolean enable() default true;}定义 Advisor Getter…

出现 java: 找不到符号 符号: 变量 log 的解决方法

目录 1. 问题所示2. 原理分析3. 解决方法3.1 增加编译参数3.2 增加lombok插件3.3 清楚本地缓存1. 问题所示 使用Springboot启动项目的时候,出现如下bug: java: 找不到符号符号: 变量 log位置: 类 org.springblade.example.consumer.rpc.BlogStu

如何定位线上OOM?

文章目录 造成OOM的原因1.一次性申请的太多2. 内存资源耗尽未释放3.本身资源不够 如何快速定位OOM&#xff1f;1.系统已经OOM了2.系统运行中还未OOM2.1导出dump文件&#xff1a;2.2.结合jvisualvm进行调试2.3 利用ArthasArthas可以做什么&#xff1f;如何使用Arthas小结 造成OO…

Docker常用命令总结

文章目录 Docker命令总结 Docker命令总结 简介&#xff1a;Docker是一个基于轻量级虚拟化技术的容器&#xff0c;整个项目基于Go语言开发&#xff0c;并采用了Apache 2.0协议。Docker可以将我们的应用程序打包封装到一个容器中&#xff0c;该容器包含了应用程序的代码、运行环…

【带头学C++】----- 九、类和对象 ---- 9.13 运算符重载——(9.13.7-9.13.8)

❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️创做不易&#xff0c;麻烦点个关注❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️ ❤️❤️❤️❤️❤️❤️❤️❤️❤️文末有惊喜&#xff01;献舞一支&#xff01;❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️ 目录 9.13…

Git篇---第九篇

系列文章目录 文章目录 系列文章目录前言一、使用过git merge和git rebase吗?它们之间有什么区别?二、使用过git cherry-pick,有什么作用?前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看…