如何优化您的API端点:引入NestJS自定义...

作者:API传播员 · 2026-01-15 · 阅读时间:4分钟
本文介绍如何使用NestJS框架创建自定义装饰器和Guard来优化API端点的安全性,实现基于模块权限的访问控制机制,包括装饰器代码实现和Guard的动态权限验证。

优化您的 API 端点:引入 NestJS 自定义装饰器和 Guard

在本文中,我们将探讨如何通过创建自定义装饰器和 Guard 来优化 API 端点的安全性。具体来说,我们将使用 NestJS 框架实现一个基于模块权限的访问控制机制。


创建自定义装饰器

首先,我们需要创建一个自定义装饰器,用于将用户信息注入到请求中,并关联特定的模块权限。

使用 CLI 创建装饰器

通过 NestJS CLI,可以轻松生成装饰器文件。使用 --flat 选项可以避免生成额外的文件夹:

nest g decorator [your-architecture]/user-modules --flat

装饰器代码实现

以下是装饰器的代码实现,它使用了 SetMetadata 方法或 Reflector.createDecorator 方法来向控制器添加元数据,从而指定端点是否需要保护。

import { SetMetadata } from '@nestjs/common';
import { Reflector } from '@nestjs/core';

// 定义可用的模块类型export type UserModule = 'management' | 'subscriptions' | 'roles';// 创建装饰器
export const UserModules = (modules: UserModule | UserModule[]) => SetMetadata('user-modules', modules);// 另一种实现方式,功能相同
export const UserModules = (modules: UserModule | UserModule[]) =>
  Reflector.createDecorator('user-modules', modules);

通过以上代码,我们可以为控制器或端点指定需要的模块权限。


创建自定义 Guard

在创建了装饰器之后,我们需要实现一个 Guard,用于验证用户是否具有访问特定模块的权限。

使用 CLI 创建 Guard

同样可以通过 CLI 快速生成 Guard 文件,并使用 --no-spec 选项跳过测试文件(尽管建议为此类逻辑编写测试):

nest generate guard [your-architecture]/user-modules --no-spec --flat

Guard 代码实现

以下是 Guard 的核心代码,它会检索通过装饰器注入的模块权限,并验证当前用户是否具有访问权限:

import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { Reflector } from '@nestjs/core';

@Injectable()
export class UserModulesGuard implements CanActivate {
  constructor(private reflector: Reflector) {}  canActivate(context: ExecutionContext): boolean {
    // 获取模块元数据
    const modules = this.reflector.get('user-modules', context.getHandler());    // 如果没有模块元数据,默认允许访问
    if (!modules) {
      return true;
    }    const request = context.switchToHttp().getRequest();    const userModules = request.user?.modules || [];    // 验证用户是否具有访问权限
    return modules.some((module) => userModules.includes(module));
  }
}

通过以上代码,Guard 会根据用户的模块权限动态决定是否允许访问。


注册 Guard

创建完成后,需要将 Guard 注册到相关模块中。可以在控制器级别、方法级别或全局应用 Guard。

在控制器中应用 Guard

在控制器顶部添加 @UseGuards(UserModulesGuard)

import { Controller, UseGuards } from '@nestjs/common';
import { UserModulesGuard } from '[your-architecture]/user-modules.guard';

@UseGuards(UserModulesGuard)
@Controller('example')
export class ExampleController {
  // 控制器逻辑
}

全局应用 Guard

如果需要全局应用 Guard,可以在根模块中配置:

import { Module } from '@nestjs/common';
import { APP_GUARD } from '@nestjs/core';
import { UserModulesGuard } from '[your-architecture]/user-modules.guard';

@Module({
  providers: [
    {
      provide: APP_GUARD,
      useClass: UserModulesGuard,
    },
  ],
})
export class AppModule {}

使用装饰器定义模块权限

现在,我们可以使用自定义装饰器为特定端点定义访问权限。例如:

import { UserModules } from '[your-architecture]/user-modules.decorator';

@UserModules('subscriptions')
public getSubscriptionsList() {
  // 获取订阅列表的逻辑
}

通过上述代码,只有具有 subscriptions 模块权限的用户才能访问该端点。


总结

通过创建自定义装饰器和 Guard,我们可以轻松实现基于模块权限的访问控制。这种方法不仅提高了 API 的安全性,还能灵活地满足不同场景的需求。您可以根据具体需求调整代码逻辑,以适配不同的业务场景。

希望本文对您有所帮助!

原文链接: https://medium.com/@compte_94466/how-to-improve-your-api-endpoints-introducing-nestjs-custom-decorators-guards-5ddfb5ddffae