Nestjs全网最佳翻译-概况-守卫-Guards
守卫
带上装饰器 @Injectable() 并实现了 CanActivate 接口的类,就是守卫。

守护只做一件事情。他们根据运行时的某些条件(如权限、角色、ACL等)来决定一个给定的请求是否会被路由处理程序处理。这通常被称为授权。在传统的Express应用程序中,授权、认证通常由中间件处理。中间件对于认证来说是一个很好的选择,因为像令牌验证和为请求对象附加属性这样的事情与特定的路由上下文(及其元数据)没有紧密联系。
但是,中间件存在天然缺陷。它不知道在调用next()函数后,哪个处理程序将被执行。另一方面,守卫可以访问 ExecutionContext 实例,因此知道下一步将执行什么。它们的设计很像异常过滤器、管道和拦截器,可以让你在请求/响应周期中的正确位置插入处理逻辑,而且是以声明的方式进行。
守护在所有中间件之后执行,但在任何拦截器或管道之前。
授权守卫
如前所述,授权是守卫的典型的使用案例,因为只有当调用者(通常是一个特定的认证用户)有足够的权限时,特定的路由才能使用。下面代码里面的 AuthGuard 假定有一个经过认证的用户(因此,在请求头文件中附有一个令牌)。它将提取并验证令牌,并使用提取的信息来确定请求是否可以继续。
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { Observable } from 'rxjs';@Injectable()
export class AuthGuard implements CanActivate {canActivate(context: ExecutionContext,): boolean | Promise<boolean> | Observable<boolean> {const request = context.switchToHttp().getRequest();return validateRequest(request);}
}
如果你正在寻找一个关于如何在你的应用程序中实现认证机制的真实案例,请访问本章。同样,对于更复杂的授权例子,请查看本页面。
validateRequest()函数内部的逻辑可以根据需要简单或复杂。这个例子的重点是展示守卫是如何融入请求/响应周期的。
每个守卫都必须实现一个canActivate()函数。这个函数应该返回一个布尔值,表明当前的请求是否被允许。它可以同步或异步地返回响应(通过Promise或Observable)。Nest使用返回值来控制下一个动作:
如果它返回true,该请求将被处理。
如果它返回false,Nest将拒绝该请求。
执行上下文
canActivate()函数需要一个参数,即ExecutionContext(执行上下文)实例。ExecutionContext 继承自 ArgumentsHost。我们之前在异常过滤器一章中看到了ArgumentsHost。在上面的例子中,我们只是使用了定义在ArgumentsHost上的相同的辅助方法,我们先前使用了这些方法,以获得对Request对象的引用。你可以参考异常过滤器一章中的Arguments host部分,了解更多关于这个主题的内容。
通过扩展ArgumentsHost,ExecutionContext还增加了几个新的辅助方法,提供关于当前执行过程的额外细节。这些细节有助于构建更多的通用守护,这些守护可以在广泛的控制器、方法和执行上下文中工作。在这里了解更多关于ExecutionContex的信息。
基于角色的认证
让我们建立一个功能更强的守卫,只允许具有特定角色的用户访问。我们将从一个基本的守卫开始,并在接下来的章节中对其进行构建。现在,它允许所有请求继续进行:
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { Observable } from 'rxjs';@Injectable()
export class RolesGuard implements CanActivate {canActivate(context: ExecutionContext,): boolean | Promise<boolean> | Observable<boolean> {return true;}
}
绑定守卫
像管道和异常过滤器一样,守护可以作用在控制器上,方法上,或者全局的。下面,我们使用@UseGuards()装饰器设置了一个控制器上的守卫。这个装饰器可以接受一个单独的参数,或者一个逗号分隔的参数列表。这让你可以通过一个声明轻松地应用适当的守卫集。
@Controller('cats')
@UseGuards(RolesGuard)
export class CatsController {}
@UseGuards() 装饰器是从 @nestjs/common 包中导入的。
上面,我们传递了RolesGuard类(而不是一个实例),将实例化的责任留给了框架,并实现了依赖性注入。与管道和异常过滤器一样,我们也可以传递一个新的实例:
@Controller('cats')
@UseGuards(new RolesGuard())
export class CatsController {}
上面的代码处理的时候会将守卫附加到这个控制器所声明的每个处理程序上。如果我们希望守卫只适用于一个方法,我们可以在方法层应用@UseGuards() 装饰器。
为了设置全局守卫,使用Nest应用程序实例的useGlobalGuards()方法:
const app = await NestFactory.create(AppModule);
app.useGlobalGuards(new RolesGuard());
对于混合型应用程序,useGlobalGuards()方法默认不为网关和微服务设置守卫(关于如何改变这一行为的信息,请参见混合型应用程序)。对于 “标准”(非混合型)微服务应用程序,useGlobalGuards()确实在全局范围内安装防护。(译者注:这里和pipes里面的一样的)
全局守卫在整个应用程序中会作用在每个控制器和每个路由处理程序。在依赖注入方面,从任何模块之外注册的全局守卫(如上面的例子中使用useGlobalGuards())不能注入依赖,因为这是在任何模块的上下文之外进行的。为了解决这个问题,你可以使用下面的方式直接从任何模块中设置一个守卫:(译者注:就是上面直接在app注册的守卫,module是引用不到的)
import { Module } from '@nestjs/common';
import { APP_GUARD } from '@nestjs/core';@Module({providers: [{provide: APP_GUARD,useClass: RolesGuard,},],
})
export class AppModule {}
当使用这种方法为守卫进行依赖性注入时,请注意,无论在哪个模块采用这种方式,守卫实际上都是全局性的。这应该在哪里进行呢?选择定义了防护(上面例子中的RolesGuard)的模块。另外,useClass并不是处理自定义提供者注册的唯一方法。在这里了解更多。
我们的RolesGuard可以工作了,但是它还不够聪明。我们还没有利用最重要的守卫特性–执行上下文。它还不知道角色,或者每个处理程序允许哪些角色。例如,CatsController可以为不同的路线提供不同的权限方案。有些可能只对管理员用户开放,而有些可能对所有人开放。我们怎样才能以一种灵活和可重用的方式将角色与路由相匹配呢?
这就是自定义元数据发挥作用的地方(在这里了解更多)。Nest提供了通过@SetMetadata()装饰器将自定义元数据附加到路由处理程序的能力。这个元数据提供了我们缺失的角色数据,智能守卫需要这些数据来做出决定。让我们来看看如何使用@SetMetadata():
@Post()
@SetMetadata('roles', ['admin'])
async create(@Body() createCatDto: CreateCatDto) {this.catsService.create(createCatDto);
}
@SetMetadata()装饰器是从@nestjs/common包中导入的。
通过上面的结构,我们将角色元数据(角色是一个key,而[‘admin’]是一个特定的value)附加到create()方法中。虽然这很有效,但在你的路由中直接使用@SetMetadata()并不是好的做法。相反,创建你自己的装饰器,如下所示:
import { SetMetadata } from '@nestjs/common';
export const Roles = (...roles: string[]) => SetMetadata('roles', roles);
这种方法更简洁、更易读,而且是强类型的。现在我们有一个自定义的@Roles()装饰器,我们可以用它来装饰create()方法。
@Post()
@Roles('admin')
async create(@Body() createCatDto: CreateCatDto) {this.catsService.create(createCatDto);
}
完善RolesGuard
现在让我们把 RolesGuard 功能完善起来。目前,它在所有情况下都简单地返回true,允许每个请求继续进行。我们想在比较分配给当前用户的角色和当前正在处理的路由所要求的实际角色的基础上,使返回值成为条件。为了访问路由的角色(自定义元数据),我们将使用Reflector帮助类,它是由框架提供的,并可以从@nestjs/core包中导入。
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 roles = this.reflector.get<string[]>('roles', context.getHandler());if (!roles) {return true;}const request = context.switchToHttp().getRequest();const user = request.user;return matchRoles(roles, user.roles);}
}
在node.js世界中,通常的做法是将授权用户附加到请求对象中。因此,在我们上面的示例代码中,我们假设 request.user 包含用户实例和允许的角色。在你的应用程序中,你可能会在你的自定义认证防护(或中间件)中进行这种关联。请查看本章以了解有关这一主题的更多信息。
matchRoles()函数内部的逻辑可以根据需要简单或复杂。这个例子的重点是展示守卫如何融入请求/响应周期。
请参考执行上下文章节的反射和元数据部分,了解以上下文敏感的方式利用反射器的更多细节。
当权限不足的用户请求一个端点时,Nest自动返回以下响应:
{"statusCode": 403,"message": "Forbidden resource","error": "Forbidden"
}
请注意,当一个守卫返回错误时,Nestjs框架会抛出一个ForbiddenException。如果你想返回一个不同的错误响应,你应该抛出你自己的特定异常。比如说:
throw new UnauthorizedException();
由守卫装置抛出的任何异常将由异常层(全局异常过滤器和应用于当前上下文的任何异常过滤器)处理。
如果你正在寻找一个关于如何实现授权的真实例子,请查看本章。
总结
本章节主要内容如下:
守卫的主要职责。
守卫的重要特性ExecutionContext(执行上下文)。
守卫的作用范围。
如何建立基于角色的守卫。
利用装饰器封装守卫。
注意本章节代码只是演示代码,文中有具体例子的链接。
相关文章:
Nestjs全网最佳翻译-概况-守卫-Guards
守卫 带上装饰器 Injectable() 并实现了 CanActivate 接口的类,就是守卫。 守护只做一件事情。他们根据运行时的某些条件(如权限、角色、ACL等)来决定一个给定的请求是否会被路由处理程序处理。这通常被称为授权。在传统的Express应用程序中…...
【软考网络管理员】2023年软考网管初级常见知识考点(3)- 网络体系结构
【写在前面】也是趁着五一假期前再写几篇分享类的文章给大家,希望看到我文章能给软考网络管理员备考的您带来一些帮助,5月27号也是全国计算机软件考试统一时间,也就不用去各个地方找资料和代码了。紧接着我就把我整理的一些资料分享给大家哈&…...
javascript正则表达式大括号、中括号、小括号的作用以及应用场景
在JavaScript正则表达式中,大括号 {}、中括号 [] 和小括号 () 都有不同的作用和应用场景。 大括号 {} 在正则表达式中,大括号 {} 表示重复次数。以下是一些常见的应用场景: {n}:精确匹配出现的次数,例如 \d{3} 匹配…...
5年测试老鸟总结,自动化测试的实施到落地,看这一篇足够...
目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 Python自动化测试&…...
通达信顾比倒数线指标公式,信号不漂移
顾比倒数线是由技术派大师戴若顾比发明的,该指标利用三个重要的价格来判断入场或离场时机,可用于盘后制定下一个交易日的操作计划。此外,顾比倒数线还可以用于补充验证其他指标。 在编写顾比倒数线选股公式之前,需要先了解顾比倒…...
网络安全: CIDR无类别路由
网络安全: CIDR无类别路由 CIDR是无类别路由,出现CIDR的原因是因为ipv4的地址被使用完客,CIDR的出现暂缓了ipv4用完的速度。 原本的ipv4很刻板,网络号分成8位,16位,24位作为掩码,也就是 xxx.0…...
NetMQ | 发布订阅时使用含通配符的Topic
NetMQ | 发布订阅时使用含通配符的Topic 文章目录 NetMQ | 发布订阅时使用含通配符的Topic前言通配符如何使用通配符通配符的作用结束语 前言 今天我来介绍一下NetMQ发布订阅时如何使用含通配符的Topic,让我们能够更加灵活地订阅消息。 什么是Topic? 在NetMQ中&am…...
行为型模式-模板方法模式
模板方法模式 概述 在面向对象程序设计过程中,程序员常常会遇到这种情况:设计一个系统时知道了算法所需的关键步骤,而且确定了这些步骤的执行顺序,但某些步骤的具体实现还未知,或者说某些步骤的实现与具体的环境相关…...
IPsec中IKE与ISAKMP过程分析(快速模式-消息1)
IPsec中IKE与ISAKMP过程分析(主模式-消息1)_搞搞搞高傲的博客-CSDN博客 IPsec中IKE与ISAKMP过程分析(主模式-消息2)_搞搞搞高傲的博客-CSDN博客 IPsec中IKE与ISAKMP过程分析(主模式-消息3)_搞搞搞高傲的博客…...
PostgreSQL 数据类型转换
各种数据类型(日期/时间、integer、floating point和numeric)转换成格式化的字符串及反过来从格式化的字符串转换成指定的数据类型,在实际操作中经常遇到。下面总结了一些常用的函数。 日期操作函数 函数返回类型描述实例to_char(timestamp…...
【Java笔试强训 1】
🎉🎉🎉点进来你就是我的人了博主主页:🙈🙈🙈戳一戳,欢迎大佬指点! 欢迎志同道合的朋友一起加油喔🦾🦾🦾 目录 一、选择题 二、编程题 🔥组队竞…...
你买票了吗?五一火车票发售量创历史新高,车票总发售2209万张票
五一劳动节已经成为了除春节国庆节外最隆重的节日,是全国性的庆祝节日。在这个节日里,人们可以通过旅游、购物、娱乐等方式来放松身心,充满活力地迎接新的挑战。同时,五一假期也成为了国内外客流量最大的旅游黄金周之一࿰…...
DiffUtil的使用
RecyclerView的DiffUtil用于计算并更新RecyclerView中数据集的变化。通过使用DiffUtil,我们可以避免完全重新加载整个列表,并且只会更改必要的视图。 以下是DiffUtil的基本用法: 创建一个继承自DiffUtil.Callback的类来计算差异。在这个类中…...
【Python】【进阶篇】18、Django初始化项目环境精讲
目录 18、Django初始化项目环境精讲1. 完成数据库迁移2. PyMySQL模块的使用3. migrate与makemigrations命令详解1) makegrations生成数据库迁移文件2) migrate执行数据库迁移命令3) 完成数据库迁移总结 18、Django初始化项目环境精讲 上一节中,我们完成了对 settin…...
Web前端基础
一.说明 如果你要了解web前端领域,那么三种语言是你必须要了解的,即html5、CSS、Javascript是你必须要了解的,通过前面的专栏内容你一定对html标记语言非常熟悉,那么其他两种语言是什么,他们怎么和html联系在一起&…...
ACM 1007 | 分段函数求值
文章目录 0x00 前言 0x01 题目描述 0x02 问题分析 0x03 代码设计 0x04 完整代码 0x05 运行效果 0x06 总结 0x00 前言 C 语言网不仅提供 C 语言,还包括 C 、 java 、算法与数据结构等课程在内的各种入门教程、视频录像、编程经验、编译器教程及软件下载、题解博…...
ChatGPT技术原理 第十四章:未来发展方向
目录 14.1 多模态对话生成 14.2 跨语言对话生成 14.3 增量学习 14.4 深度强化学习...
大型水利投资集团,打造数智财资管理新范式
随着我国城市化进程的不断推进,城市基础设施在国民经济中的作用愈加重要,其建设水平直接影响一个城市的竞争力。国有城投、水投等企业作为城市基础设施建设的主要参与者,其重要性不言而喻。随着国家、地方对基础设施重要性认识的加深以及政府…...
【java】彻底剖析 Synchronized
文章目录 前言对象结构Monitor 对象Synchronized特征原子性可见性有序性可重入锁 锁升级的过程 前言 源码级别剖析Synchronized 对象结构 Synchronized是Java中的隐式锁,它的获取锁和释放锁都是隐式的,完全交由JVM帮助我们操作,在了解Sync…...
有反爬机制就爬不了吗?那是你还不知道反反爬,道高一尺魔高一丈啊
文章目录 一、从用户请求的Headers反爬虫二、基于用户行为反爬虫(1)方法1(2)方法2 三、动态页面的反爬虫四.总结 不知道你们在用爬虫爬数据的时候是否有发现,越来越多的网站都有自己的反爬机制,抓取数据已经…...
汽车生产虚拟实训中的技能提升与生产优化
在制造业蓬勃发展的大背景下,虚拟教学实训宛如一颗璀璨的新星,正发挥着不可或缺且日益凸显的关键作用,源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例,汽车生产线上各类…...
【Go】3、Go语言进阶与依赖管理
前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课,做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程,它的核心机制是 Goroutine 协程、Channel 通道,并基于CSP(Communicating Sequential Processes࿰…...
高危文件识别的常用算法:原理、应用与企业场景
高危文件识别的常用算法:原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件,如包含恶意代码、敏感数据或欺诈内容的文档,在企业协同办公环境中(如Teams、Google Workspace)尤为重要。结合大模型技术&…...
令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍
文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结: 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析: 实际业务去理解体会统一注…...
算法岗面试经验分享-大模型篇
文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer (1)资源 论文&a…...
Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战
说明:这是一个机器学习实战项目(附带数据代码文档),如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下,风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...
[大语言模型]在个人电脑上部署ollama 并进行管理,最后配置AI程序开发助手.
ollama官网: 下载 https://ollama.com/ 安装 查看可以使用的模型 https://ollama.com/search 例如 https://ollama.com/library/deepseek-r1/tags # deepseek-r1:7bollama pull deepseek-r1:7b改token数量为409622 16384 ollama命令说明 ollama serve #:…...
Docker拉取MySQL后数据库连接失败的解决方案
在使用Docker部署MySQL时,拉取并启动容器后,有时可能会遇到数据库连接失败的问题。这种问题可能由多种原因导致,包括配置错误、网络设置问题、权限问题等。本文将分析可能的原因,并提供解决方案。 一、确认MySQL容器的运行状态 …...
Kubernetes 节点自动伸缩(Cluster Autoscaler)原理与实践
在 Kubernetes 集群中,如何在保障应用高可用的同时有效地管理资源,一直是运维人员和开发者关注的重点。随着微服务架构的普及,集群内各个服务的负载波动日趋明显,传统的手动扩缩容方式已无法满足实时性和弹性需求。 Cluster Auto…...
Linux安全加固:从攻防视角构建系统免疫
Linux安全加固:从攻防视角构建系统免疫 构建坚不可摧的数字堡垒 引言:攻防对抗的新纪元 在日益复杂的网络威胁环境中,Linux系统安全已从被动防御转向主动免疫。2023年全球网络安全报告显示,高级持续性威胁(APT)攻击同比增长65%,平均入侵停留时间缩短至48小时。本章将从…...
