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

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 接口的类&#xff0c;就是守卫。 守护只做一件事情。他们根据运行时的某些条件&#xff08;如权限、角色、ACL等&#xff09;来决定一个给定的请求是否会被路由处理程序处理。这通常被称为授权。在传统的Express应用程序中…...

【软考网络管理员】2023年软考网管初级常见知识考点(3)- 网络体系结构

【写在前面】也是趁着五一假期前再写几篇分享类的文章给大家&#xff0c;希望看到我文章能给软考网络管理员备考的您带来一些帮助&#xff0c;5月27号也是全国计算机软件考试统一时间&#xff0c;也就不用去各个地方找资料和代码了。紧接着我就把我整理的一些资料分享给大家哈&…...

javascript正则表达式大括号、中括号、小括号的作用以及应用场景

在JavaScript正则表达式中&#xff0c;大括号 {}、中括号 [] 和小括号 () 都有不同的作用和应用场景。 大括号 {} 在正则表达式中&#xff0c;大括号 {} 表示重复次数。以下是一些常见的应用场景&#xff1a; {n}&#xff1a;精确匹配出现的次数&#xff0c;例如 \d{3} 匹配…...

5年测试老鸟总结,自动化测试的实施到落地,看这一篇足够...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 Python自动化测试&…...

通达信顾比倒数线指标公式,信号不漂移

顾比倒数线是由技术派大师戴若顾比发明的&#xff0c;该指标利用三个重要的价格来判断入场或离场时机&#xff0c;可用于盘后制定下一个交易日的操作计划。此外&#xff0c;顾比倒数线还可以用于补充验证其他指标。 在编写顾比倒数线选股公式之前&#xff0c;需要先了解顾比倒…...

网络安全: CIDR无类别路由

网络安全&#xff1a; CIDR无类别路由 CIDR是无类别路由&#xff0c;出现CIDR的原因是因为ipv4的地址被使用完客&#xff0c;CIDR的出现暂缓了ipv4用完的速度。 原本的ipv4很刻板&#xff0c;网络号分成8位&#xff0c;16位&#xff0c;24位作为掩码&#xff0c;也就是 xxx.0…...

NetMQ | 发布订阅时使用含通配符的Topic

NetMQ | 发布订阅时使用含通配符的Topic 文章目录 NetMQ | 发布订阅时使用含通配符的Topic前言通配符如何使用通配符通配符的作用结束语 前言 今天我来介绍一下NetMQ发布订阅时如何使用含通配符的Topic&#xff0c;让我们能够更加灵活地订阅消息。 什么是Topic? 在NetMQ中&am…...

行为型模式-模板方法模式

模板方法模式 概述 在面向对象程序设计过程中&#xff0c;程序员常常会遇到这种情况&#xff1a;设计一个系统时知道了算法所需的关键步骤&#xff0c;而且确定了这些步骤的执行顺序&#xff0c;但某些步骤的具体实现还未知&#xff0c;或者说某些步骤的实现与具体的环境相关…...

IPsec中IKE与ISAKMP过程分析(快速模式-消息1)

IPsec中IKE与ISAKMP过程分析&#xff08;主模式-消息1&#xff09;_搞搞搞高傲的博客-CSDN博客 IPsec中IKE与ISAKMP过程分析&#xff08;主模式-消息2&#xff09;_搞搞搞高傲的博客-CSDN博客 IPsec中IKE与ISAKMP过程分析&#xff08;主模式-消息3&#xff09;_搞搞搞高傲的博客…...

PostgreSQL 数据类型转换

各种数据类型&#xff08;日期/时间、integer、floating point和numeric&#xff09;转换成格式化的字符串及反过来从格式化的字符串转换成指定的数据类型&#xff0c;在实际操作中经常遇到。下面总结了一些常用的函数。 日期操作函数 函数返回类型描述实例to_char(timestamp…...

【Java笔试强训 1】

&#x1f389;&#x1f389;&#x1f389;点进来你就是我的人了博主主页&#xff1a;&#x1f648;&#x1f648;&#x1f648;戳一戳,欢迎大佬指点! 欢迎志同道合的朋友一起加油喔&#x1f9be;&#x1f9be;&#x1f9be; 目录 一、选择题 二、编程题 &#x1f525;组队竞…...

你买票了吗?五一火车票发售量创历史新高,车票总发售2209万张票

五一劳动节已经成为了除春节国庆节外最隆重的节日&#xff0c;是全国性的庆祝节日。在这个节日里&#xff0c;人们可以通过旅游、购物、娱乐等方式来放松身心&#xff0c;充满活力地迎接新的挑战。同时&#xff0c;五一假期也成为了国内外客流量最大的旅游黄金周之一&#xff0…...

DiffUtil的使用

RecyclerView的DiffUtil用于计算并更新RecyclerView中数据集的变化。通过使用DiffUtil&#xff0c;我们可以避免完全重新加载整个列表&#xff0c;并且只会更改必要的视图。 以下是DiffUtil的基本用法&#xff1a; 创建一个继承自DiffUtil.Callback的类来计算差异。在这个类中…...

【Python】【进阶篇】18、Django初始化项目环境精讲

目录 18、Django初始化项目环境精讲1. 完成数据库迁移2. PyMySQL模块的使用3. migrate与makemigrations命令详解1) makegrations生成数据库迁移文件2) migrate执行数据库迁移命令3) 完成数据库迁移总结 18、Django初始化项目环境精讲 上一节中&#xff0c;我们完成了对 settin…...

Web前端基础

一.说明 如果你要了解web前端领域&#xff0c;那么三种语言是你必须要了解的&#xff0c;即html5、CSS、Javascript是你必须要了解的&#xff0c;通过前面的专栏内容你一定对html标记语言非常熟悉&#xff0c;那么其他两种语言是什么&#xff0c;他们怎么和html联系在一起&…...

ACM 1007 | 分段函数求值

文章目录 0x00 前言 0x01 题目描述 0x02 问题分析 0x03 代码设计 0x04 完整代码 0x05 运行效果 0x06 总结 0x00 前言 C 语言网不仅提供 C 语言&#xff0c;还包括 C 、 java 、算法与数据结构等课程在内的各种入门教程、视频录像、编程经验、编译器教程及软件下载、题解博…...

ChatGPT技术原理 第十四章:未来发展方向

目录 14.1 多模态对话生成 14.2 跨语言对话生成 14.3 增量学习 14.4 深度强化学习...

大型水利投资集团,打造数智财资管理新范式

随着我国城市化进程的不断推进&#xff0c;城市基础设施在国民经济中的作用愈加重要&#xff0c;其建设水平直接影响一个城市的竞争力。国有城投、水投等企业作为城市基础设施建设的主要参与者&#xff0c;其重要性不言而喻。随着国家、地方对基础设施重要性认识的加深以及政府…...

【java】彻底剖析 Synchronized

文章目录 前言对象结构Monitor 对象Synchronized特征原子性可见性有序性可重入锁 锁升级的过程 前言 源码级别剖析Synchronized 对象结构 Synchronized是Java中的隐式锁&#xff0c;它的获取锁和释放锁都是隐式的&#xff0c;完全交由JVM帮助我们操作&#xff0c;在了解Sync…...

有反爬机制就爬不了吗?那是你还不知道反反爬,道高一尺魔高一丈啊

文章目录 一、从用户请求的Headers反爬虫二、基于用户行为反爬虫&#xff08;1&#xff09;方法1&#xff08;2&#xff09;方法2 三、动态页面的反爬虫四.总结 不知道你们在用爬虫爬数据的时候是否有发现&#xff0c;越来越多的网站都有自己的反爬机制&#xff0c;抓取数据已经…...

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端

&#x1f31f; 什么是 MCP&#xff1f; 模型控制协议 (MCP) 是一种创新的协议&#xff0c;旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议&#xff0c;它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)

目录 1.TCP的连接管理机制&#xff08;1&#xff09;三次握手①握手过程②对握手过程的理解 &#xff08;2&#xff09;四次挥手&#xff08;3&#xff09;握手和挥手的触发&#xff08;4&#xff09;状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...

【git】把本地更改提交远程新分支feature_g

创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...

工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配

AI3D视觉的工业赋能者 迁移科技成立于2017年&#xff0c;作为行业领先的3D工业相机及视觉系统供应商&#xff0c;累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成&#xff0c;通过稳定、易用、高回报的AI3D视觉系统&#xff0c;为汽车、新能源、金属制造等行…...

Java入门学习详细版(一)

大家好&#xff0c;Java 学习是一个系统学习的过程&#xff0c;核心原则就是“理论 实践 坚持”&#xff0c;并且需循序渐进&#xff0c;不可过于着急&#xff0c;本篇文章推出的这份详细入门学习资料将带大家从零基础开始&#xff0c;逐步掌握 Java 的核心概念和编程技能。 …...

全志A40i android7.1 调试信息打印串口由uart0改为uart3

一&#xff0c;概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本&#xff1a;2014.07&#xff1b; Kernel版本&#xff1a;Linux-3.10&#xff1b; 二&#xff0c;Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01)&#xff0c;并让boo…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)

本期内容并不是很难&#xff0c;相信大家会学的很愉快&#xff0c;当然对于有后端基础的朋友来说&#xff0c;本期内容更加容易了解&#xff0c;当然没有基础的也别担心&#xff0c;本期内容会详细解释有关内容 本期用到的软件&#xff1a;yakit&#xff08;因为经过之前好多期…...

return this;返回的是谁

一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请&#xff0c;不同级别的经理有不同的审批权限&#xff1a; // 抽象处理者&#xff1a;审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...

Python Ovito统计金刚石结构数量

大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...