什么是Guard
在 Nest.js 中,Guard(守卫)是一种用于保护路由端点的机制。类似于中间件,在请求到达路由处理程序之前,Guard 可以对请求进行拦截并在特定条件下允许或拒绝请求。
可以将 Guard 想象成一个安全守卫或门卫,它会检查进入系统的请求是否符合特定的要求才能通过。通常情况下,Guard 在路由处理程序之前执行,用于验证请求是否具备执行相应操作的权限或满足其他特定条件。这些条件可以是身份验证、授权、角色检查、IP 地址过滤等。
Guard 可以被应用到整个应用程序、模块或具体的路由上。它可以是同步的,也可以是异步的,这取决于你的需求。当 Guard 拦截请求并确定其通过或拒绝时,它可以返回 表示允许请求通过,或者返回一个包含详细错误信息的异常对象来拒绝请求。
通过使用 Guard,你可以确保只有符合特定条件的请求才能访问和操作受保护的资源。这样可以增强应用程序的安全性,并实现更细粒度的权限控制。
总结起来,Nest.js 中的 Guard 就像是一个保安人员,用于在请求到达路由处理程序之前进行检查,并决定请求是否被允许通过。它通过验证身份、权限或其他条件来保护应用程序的资源。
Guard的作用
刚才我们也提到了,Guard在路由处理程序之前执行,用于验证请求是否具备执行相应操作的权限或满足其他特定条件,如果验证通过则放行,验证失败则会拒绝。
能够对身份验证,授权,ip地址过滤等进行处理
注意一点: Guard(守卫)在所有中间件之后执行,但在任何拦截器或管道之前执行。所以它的权限还是比较高的
项目中的应用
Guard基本使用
创建Guard
首先通过命令创建一个Guard
nest g gu auth --no-spec
每个guard都必须实现一个功能。并且这个函数返回一个布尔值,指示是否允许当前请求。它可以同步或异步返回响应。Nest 使用返回值来控制下一个操作
如果返回true,请求将被处理。
如果它返回false,Nest将拒绝该请求
使用Guard
在要做权限验证的模块的controller中使用@UseGuard()装饰器将类(不是实例)上,将实例化的责任留给了框架并启用依赖注入
同样,我们也可以直接传递一个实例
与管道,拦截器,过滤器一样,我们可以将Guard注册为全局的
全局防护用于整个应用程序,用于每个控制器和每个路由处理程序。在依赖关系注入方面,从任何模块外部注册的全局防护(如上例所示)无法注入依赖关系,因为这是在任何模块的上下文之外完成的,没有从模块中导出或者引入,可以这样处理,来为注入依赖关系
在app根模块中提供
角色验证案例
元数据
对于不同的路由,可以有不同的权限方案。有些可能仅对管理员用户可用,而另一些可能对所有人开放。我们如何以灵活且可重用的方式将角色与路由匹配?
Nest 提供了通过装饰器将自定义元数据附加到路由处理程序的功能。我们可以通过元数据来对权限进行限制 Nest.js 中的SetMetadata()是一个装饰器工具函数,用于在类、方法或参数上设置自定义的元数据。元数据是与被装饰项(类、方法或参数)相关的任意信息,可以在运行时使用反射和元编程技术进行访问。
但是这种方式在controller中设置,不灵活,我们可以自定义一个装饰器,通过命令创建一个装饰器
nest g d role --no-spec
这时候在controller中使用 此方法更清晰、更具可读性,并且是强类型。
角色校验
上面我们通过设置了路由的元数据,我们将实际功能开放给的用户和路由元数据中的角色进行比较,如果一直就通过,给开放相应的功能,不通过就不开放相应的功能
我们需要从@nestjs/core导入一个Reflector,它能够将路由元数据反射出来,通过constructor构造函数将类注入进去后便可以使用
import { Reflector } from '@nestjs/core';
在守卫(Guard)中, 对象是执行上下文的一个实例,提供了许多有用的方法和属性来访问请求、响应和执行的处理程序信息。其中, getHandler()方法是 对象的一个方法,用于获取当前路由处理程序的引用。我们可以看到返回的是gethello这个函数,也就是我们用于Guard的这个路由方法
通过reflector的get方法能够将路由身上的元数据读取出来
接着做逻辑处理
首先获取http请求对象,获取他的角色属性,而后自己封装了一个函数matchRoles来比较角色身份
我们来做一个小例子来验证一下
在controller中定义一个post请求,只有身份是admin的才可以访问,否则没有权限
我们发现报的403没有权限异常, 这是因为 当权限不足的用户请求端点时,Nest 会自动返回以下响应
如果我们要自己设置异常,Guard(守卫)引发的任何异常都将由异常层(全局异常过滤器和应用于当前上下文的异常过滤器)处理。
当我们请求的对象是admin的时候就可以放行了
总结
Guard在nestjs中还是很重要的,应用场景也很多,这里只拿出简简单单的一个例子帮助大家掌握Guard,写作不易,希望多多支持!