返回顶部
首页 > 资讯 > 精选 >使用Nest.js怎么进行授权验证
  • 915
分享到

使用Nest.js怎么进行授权验证

2023-06-06 12:06:58 915人浏览 泡泡鱼
摘要

这篇文章主要介绍了使用Nest.js怎么进行授权验证,此处通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考价值,需要的朋友可以参考下:0x0 前言系统授权指的是登录用户执行操作过程,比如管理员可以对系统进行用户操作、网站帖

这篇文章主要介绍了使用Nest.js怎么进行授权验证,此处通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考价值,需要的朋友可以参考下:

0x0 前言

系统授权指的是登录用户执行操作过程,比如管理员可以对系统进行用户操作、网站帖子管理操作,非管理员可以进行授权阅读帖子等操作,所以实现需要对系统的授权需要身份验证机制,下面来实现最基本的基于角色的访问控制系统。

0x1 RBAC 实现

基于角色的访问控制(RBAC)是围绕角色的特权和定义的策略无关的访问控制机制,首先创建个代表系统角色枚举信息 role.enum.ts:

export enum Role { User = 'user', Admin = 'admin'}

如果是更复杂的系统,推荐角色信息存储到数据库更好管理。

然后创建装饰器和使用 @Roles() 来运行指定访问所需要的资源角色,创建roles.decorator.ts:

import { SetMetadata } from '@nestjs/common'import { Role } from './role.enum'export const ROLES_KEY = 'roles'export const Roles = (...roles: Role[]) => SetMetadata(ROLES_KEY, roles)

上述创建一个名叫 @Roles() 的装饰器,可以使用他来装饰任何一个路由控制器,比如用户创建:

@Post()@Roles(Role.Admin)create(@Body() createUserDto: CreateUserDto): Promise<UserEntity> { return this.userService.create(createUserDto)}

最后创建一个 RolesGuard 类,它会实现将分配给当前用户角色和当前路由控制器所需要角色进行比较,为了访问路由角色(自定义元数据),将使用 Reflector 工具类,新建 roles.guard.ts:

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

假设 request.user 包含 roles 属性:

class User { // ...other properties roles: Role[]}

然后 RolesGuard 在控制器全局注册:

providers: [ { provide: APP_GUARD, useClass: RolesGuard }]

当某个用户访问超出角色范畴内的请求出现:

{ "statusCode": 403, "message": "Forbidden resource", "error": "Forbidden"}

0x2 基于声明的授权

创建身份后,系统可以给身份分配一个或者多个声明权限,表示告诉当前用户可以做什么,而不是当前用户是什么,在 Nest 系统里实现基于声明授权,步骤和上面 RBAC 差不多,但有个区别是,需要比较权限,而不是判断特定角色,每个用户分配一组权限,比如定一个 @RequirePermissions() 装饰器,然后访问所需的权限属性:

@Post()@RequirePermissions(Permission.CREATE_USER)create(@Body() createUserDto: CreateUserDto): Promise<UserEntity> { return this.userService.create(createUserDto)}

Permission 表示类似 PRAC 中的 Role 枚举,包含其中系统可访问的权限组:

export enum Role { CREATE_USER = ['add', 'read', 'update', 'delete'], READ_USER = ['read']}

0x3 集成 CASL

CASL 是一个同构授权库,可以限制客户端访问的路由控制器资源,安装依赖:

yarn add @casl/ability

下面使用最简单的例子来实现 CASL 的机制,创建 User 和 Article 俩个实体类:

class User { id: number isAdmin: boolean}

User 实体类俩个属性,分别是用户编号和是否具有管理员权限。

class Article { id: number isPublished: boolean authorId: string}

Article 实体类有三个属性,分别是文章编号和文章状态(是否已经发布)以及撰写文章的作者编号。

根据上面俩个最简单的例子组成最简单的功能:

  • 具有管理员权限的用户可以管理所有实体(创建、读取、更新和删除)

  • 用户对所有内容只有只读访问权限

  • 用户可以更新自己撰写的文章 authorId === userId

  • 已发布的文章无法删除 article.isPublished === true

针对上面功能可以创建 Action 枚举,来表示用户对实体的操作:

export enum Action { Manage = 'manage', Create = 'create', Read = 'read', Update = 'update', Delete = 'delete',}

manage 是 CASL 中的特殊关键字,表示可以进行任何操作。

实现功能需要二次封装 CASL 库,执行 nest-cli 进行创建需要业务:

nest g module caslnest g class casl/casl-ability.factory

定义 CaslAbilityFactory 的 createForUser() 方法,来未用户创建对象:

type Subjects = InferSubjects<typeof Article | typeof User> | 'all'export type AppAbility = Ability<[Action, Subjects]>@Injectable()export class CaslAbilityFactory { createForUser(user: User) { const { can, cannot, build } = new AbilityBuilder<  Ability<[Action, Subjects]> >(Ability as AbilityClass<AppAbility>); if (user.isAdmin) {  can(Action.Manage, 'all') // 允许任何读写操作 } else {  can(Action.Read, 'all') // 只读操作 } can(Action.Update, Article, { authorId: user.id }) cannot(Action.Delete, Article, { isPublished: true }) return build({  // 详细:https://casl.js.org/v5/en/guide/subject-type-detection#use-classes-as-subject-types  detectSubjectType: item => item.constructor as ExtractSubjectType<Subjects> }) }}

然后在 CaslModule 引入:

import { Module } from '@nestjs/common'import { CaslAbilityFactory } from './casl-ability.factory'@Module({ providers: [CaslAbilityFactory], exports: [CaslAbilityFactory]})export class CaslModule {}

然后在任何业务引入 CaslModule 然后在构造函数注入就可以使用了:

constructor(private caslAbilityFactory: CaslAbilityFactory) {}const ability = this.caslAbilityFactory.createForUser(user)if (ability.can(Action.Read, 'all')) { // "user" 对所有内容可以读写}

如果当前用户是普通权限非管理员用户,可以阅读文章,但不能创建新的文章和删除现有文章:

const user = new User()user.isAdmin = falseconst ability = this.caslAbilityFactory.createForUser(user)ability.can(Action.Read, Article) // trueability.can(Action.Delete, Article) // falseability.can(Action.Create, Article) // false

这样显然有问题,当前用户如果是文章的作者,应该可以对此进行操作:

const user = new User()user.id = 1const article = new Article()article.authorId = user.idconst ability = this.caslAbilityFactory.createForUser(user)ability.can(Action.Update, article) // truearticle.authorId = 2ability.can(Action.Update, article) // false

0x4 PoliceiesGuard

上述简单的实现,但在复杂的系统中还是不满足更复杂的需求,所以配合上一篇的身份验证文章来进行扩展类级别授权策略模式,在原有的 CaslAbilityFactory 类进行扩展:

import { AppAbility } from '../casl/casl-ability.factory'interface IPolicyHandler { handle(ability: AppAbility): boolean}type PolicyHandlerCallback = (ability: AppAbility) => booleanexport type PolicyHandler = IPolicyHandler | PolicyHandlerCallback

提供支持对象和函数对每个路由控制器进行策略检查:IPolicyHandler 和 PolicyHandlerCallback。

然后创建一个 @CheckPolicies() 装饰器来运行指定访问特定资源策略:

export const CHECK_POLICIES_KEY = 'check_policy'export const CheckPolicies = (...handlers: PolicyHandler[]) => SetMetadata(CHECK_POLICIES_KEY, handlers)

创建 PoliciesGuard 类来提取并且执行绑定路由控制器所有策略:

@Injectable()export class PoliciesGuard implements CanActivate { constructor( private reflector: Reflector, private caslAbilityFactory: CaslAbilityFactory, ) {} async canActivate(context: ExecutionContext): Promise<boolean> { const policyHandlers =  this.reflector.get<PolicyHandler[]>(  CHECK_POLICIES_KEY,  context.getHandler()  ) || [] const { user } = context.switchToHttp().getRequest() const ability = this.caslAbilityFactory.createForUser(user) return policyHandlers.every((handler) =>  this.execPolicyHandler(handler, ability) ) } private execPolicyHandler(handler: PolicyHandler, ability: AppAbility) { if (typeof handler === 'function') {  return handler(ability) } return handler.handle(ability) }}

假设 request.user 包含用户实例,policyHandlers 是通过装饰器 @CheckPolicies() 分配,使用 aslAbilityFactory#create 构造 Ability 对象方法,来验证用户是否具有足够的权限来执行特定的操作,然后将此对象传递给策略处理方法,该方法可以实现函数或者是类的实例 IPolicyHandler,并且公开 handle() 方法返回布尔值。

@Get()@UseGuards(PoliciesGuard)@CheckPolicies((ability: AppAbility) => ability.can(Action.Read, Article))findAll() { return this.articlesService.findAll()}

同样可以定义 IPolicyHandler 接口类:

export class ReadarticlePolicyHandler implements IPolicyHandler { handle(ability: AppAbility) { return ability.can(Action.Read, Article) }}

使用如下:

@Get()@UseGuards(PoliciesGuard)@CheckPolicies(new ReadArticlePolicyHandler())findAll() { return this.articlesService.findAll()}

到此这篇关于使用Nest.js怎么进行授权验证的文章就介绍到这了,更多相关内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: 使用Nest.js怎么进行授权验证

本文链接: https://lsjlt.com/news/246719.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 使用Nest.js怎么进行授权验证
    这篇文章主要介绍了使用Nest.js怎么进行授权验证,此处通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考价值,需要的朋友可以参考下:0x0 前言系统授权指的是登录用户执行操作过程,比如管理员可以对系统进行用户操作、网站帖...
    99+
    2023-06-06
  • redis未授权怎么验证
    redis 未授权验证是指在无密码情况下访问 redis 服务器。验证步骤包括:获取 redis 服务器地址和端口;使用 telnet 或 netcat 连接;检查是否显示 redis ...
    99+
    2024-06-03
    redis
  • 怎么用MyBatis进行数据权限验证
    本篇内容主要讲解“怎么用MyBatis进行数据权限验证”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么用MyBatis进行数据权限验证”吧!首先先创建表CRE...
    99+
    2024-04-02
  • SpringSecurity数据库进行认证和授权的使用
    目录一、准备工作1.1 导入相关依赖1.2 配置信息1.3 数据库准备1.4 实体类的创建1.5 Dao层的创建1.6 Service层的编写1.7 Security配置1.8 密码...
    99+
    2024-04-02
  • 如何在SQLServer中进行用户身份验证和授权管理
    在SQL Server中进行用户身份验证和授权管理是非常重要的,以确保数据库的安全性和数据的保护。以下是一些常见的方法来实现用户身份...
    99+
    2024-04-09
    SQLServer
  • Spring Security进行登录认证和授权
    一、Spring Security内部认证流程 用户首次登录提交用户名和密码后spring security 的UsernamePasswordAuthenticationFilter把用户名密码封...
    99+
    2023-09-02
    spring java spring boot
  • Postman怎么处理身份验证和授权
    在Postman中,处理身份验证和授权可以通过以下步骤进行: 打开Postman应用程序并创建一个新的请求。 在请求的Hea...
    99+
    2024-03-13
    Postman
  • mysql怎么使用权限验证
    使用 mysql 权限验证需要执行三个步骤:创建 mysql 用户、授予权限和刷新权限。具体步骤包括:1. 使用 create user 语句创建用户;2. 使用 grant 语句授予用...
    99+
    2024-05-30
    mysql 权限验证
  • Netdata是否支持通过LDAP或OAuth进行身份验证和授权
    目前,Netdata不直接支持通过LDAP或OAuth进行身份验证和授权。然而,您可以通过在反向代理或身份验证代理中设置LDAP或OAuth来实现对Netdata的身份验证和授权。您可以使用Nginx等反向代理来实现此功能。 Netdata...
    99+
    2024-06-04
    zabbix
  • 怎样进行Linux文件权限授权
    怎样进行Linux文件权限授权,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。Linux系统每个用户都用不同的权限,对于文件或者目录来说也有不同的权限,针对不同的群组设置不同...
    99+
    2023-06-28
  • 如何使用 PHP 进行用户验证?
    用户验证在 php 中至关重要,可以通过多种方式实现,包括依靠会话、使用数据库或利用第三方库。借助会话方法,可以通过检查 $_session 变量是否存在来验证用户是否已登录。使用数据库...
    99+
    2024-04-19
    php 用户验证 mysql laravel 敏感数据
  • Node.js 应用的磐石防御:身份验证与授权的进阶策略
    1. 多因素身份验证(MFA) MFA 为身份验证添加了一层额外的保护,要求用户在登录时提供除密码之外的第二种凭证。这可以是基于时间的一次性密码 (TOTP)、短信验证码或生物识别认证(如指纹或面部识别)。通过强制实施 MFA,即使攻击者...
    99+
    2024-04-02
  • 如何使用中间件进行授权 - gin gonic go
    问题内容 我正在学习使用带有 gin 框架的中间件,但我遇到了一个问题 我希望我的 test 函数 仅在满足我的 func tokenauthmiddleware 的要求时才显示在...
    99+
    2024-02-05
  • php证书授权失效怎么办
    本教程操作环境:windows7系统、PHP8.1版、Dell G3电脑。php证书授权失效怎么办?解决PHP环境(宝塔面板)提示SSL certificate problem: certificate has expired最近在帮客户排...
    99+
    2024-04-02
  • Swagger2怎么配置Security授权认证
    本篇内容主要讲解“Swagger2怎么配置Security授权认证”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Swagger2怎么配置Security授权认证”吧!Swagger2配置Secu...
    99+
    2023-07-05
  • 怎么使用PHP正则对表单数据进行验证
    这篇文章主要介绍了怎么使用PHP正则对表单数据进行验证,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。如何使用PHP正则对表单数据进行验证?首先,我们先布局我们的HTML的表单...
    99+
    2023-06-15
  • Javascript使用integrity属性进行安全验证
    目录一、script标签引入文件 1. 引入本地文件2. 引入远程文件二、integrity安全验证 1. 引入vue的cdn资源2. 验证是否正常一、script标签引入文件 在...
    99+
    2024-04-02
  • Zod进行TypeScript类型验证使用详解
    目录引言什么是类型验证,为什么需要它?为什么要使用zod?使用 Zod 进行类型验证的示例Primitives对象类型推断组合类型注意事项安全解析无法识别的Key被删除其他事项Zod...
    99+
    2024-04-02
  • ASP.NET Core使用JWT认证授权的方法
     demo地址: https://github.com/william0705/JWTS 名词解析 认证 : 识别用户是否合法 授权: 赋予用户权限 (能访问哪些资...
    99+
    2022-06-07
    net 授权 jwt ASP.NET 方法 core ASP
  • Django中怎么实现用户认证与授权
    在Django中,用户认证和授权可以通过内置的认证系统来实现。以下是实现用户认证和授权的步骤: 创建用户模型:Django提供了...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作