Nestjs自定义注解实现接口权限控制详解

下面我将详细讲解一下 “Nestjs自定义注解实现接口权限控制”的完整攻略。

1. 背景

在开发过程中,接口权限控制是一个非常重要的问题,通常实现的方式有基于角色、基于路由等等,但是这些方式灵活性较差,不够便捷。本攻略将详细介绍如何使用 Nestjs 自定义注解实现接口权限控制。

2. 环境准备

在开始之前,需要确保已经安装 nestjsreflect-metadata,安装方式如下:

npm i --save @nestjs/core reflect-metadata

3. 自定义注解实现接口权限控制

在 Nestjs 中,使用自定义注解实现接口权限控制的方式如下:

3.1. 编写权限功能代码

在权限功能代码中,我们需要实现如下逻辑:

  1. 定义注解:使用 Reflect Metadata 定义一个自定义注解,在注解中定义该接口需要的权限。
  2. 获取用户信息:获取当前用户的信息,通常是从用户的 token 中获取。这里我们假设我们从请求头中获取了用户的 token。
  3. 判断用户是否拥有权限:根据用户信息和权限注解,判断用户是否拥有权限。

代码如下:

import { createParamDecorator, ExecutionContext } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { AuthFailedException } from './exceptions/auth-failed.exception';

const reflector = new Reflector();

interface User {
  id: number;
  name: string;
  roles: string[];
}

export const CurrentUser = createParamDecorator(
  (data: unknown, ctx: ExecutionContext) => {
    const req = ctx.switchToHttp().getRequest();
    const token = req.headers['authorization']?.split(' ')[1];
    try {
      const user = parseToken(token);
      return user;
    } catch (error) {
      throw new AuthFailedException('Token 验证失败');
    }
  },
);

function parseToken(token: string): User {
  // 这里写具体的 token 解析逻辑,此处省略
  return {
    id: 1,
    name: 'foo',
    roles: ['admin'],
  };
}

export function Auth(role: string) {
  return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
    const originalMethod = descriptor.value;
    descriptor.value = function (...args: any[]) {
      const user = args[0];
      const roles = user.roles;
      if (!roles.includes(role)) {
        throw new AuthFailedException(`无权操作:需要角色 ${role}`);
      }

      return originalMethod.apply(this, args);
    };
    return descriptor;
  };
}

3.2. 在控制器中使用权限注解

在控制器中使用权限注解,只需要在需要权限控制的接口上添加 @Auth 注解即可,如下所示:

@Controller()
export class AppController {
  @Post('admin')
  @Auth('admin')
  createToken(@Body() body: CreateTokenDto) {
    return this.userService.createToken(body);
  }
}

在上面的例子中,createToken 方法需要具备 admin 权限。

4. 示例说明

下面给出两个示例,以便更好地理解如何使用自定义注解实现接口权限控制:

4.1. 示例 1

我们在开发一个权限管理的系统中,需要对用户进行管理,其中管理员用户能够对普通用户进行增、删、改、查的操作,而普通用户只有对自己进行增、删、改、查的权限。此时,我们可以使用自定义注解对 user 接口进行权限控制。

@Controller()
export class UserController {
  @Post('user')
  @Auth('normal')
  createUser(@Body() body: CreateUserDto) {
    // 创建用户
  }

  @Put('user/:id')
  @Auth('normal')
  updateUser(@Param('id') id: string, @Body() body: UpdateUserDto, @CurrentUser() user: User) {
    if (user.id !== id) {
      throw new AuthFailedException(`无权操作`);
    }
    // 更新用户
  }

  @Delete('user/:id')
  @Auth('normal')
  deleteUser(@Param('id') id: string, @CurrentUser() user: User) {
    if (user.id !== id) {
      throw new AuthFailedException(`无权操作`);
    }
    // 删除用户
  }

  @Get('users')
  @Auth('admin')
  getUsers() {
    // 获取所有用户
  }
}

在上面的例子中,createUser/updateUser/deleteUser 方法需要具备 normal 权限,getUsers 方法需要具备 admin 权限。

4.2. 示例 2

在开发一个博客系统中,需要对博客进行管理,其中管理员用户能够对自己的博客进行所有操作,而普通用户只能编辑自己的博客。此时,我们可以使用自定义注解对 blog 接口进行权限控制。

@Controller()
export class BlogController {
  @Post('blog')
  @Auth('normal')
  createBlog(@Body() body: CreateBlogDto, @CurrentUser() user: User) {
    // 创建博客
  }

  @Put('blog/:id')
  @Auth('normal')
  updateBlog(@Param('id') id: string, @Body() body: UpdateBlogDto, @CurrentUser() user: User) {
    const blog = await this.blogService.findOne(id);
    if (user.id !== blog.authorId) {
      throw new AuthFailedException(`无权操作`);
    }
    // 更新博客
  }

  @Delete('blog/:id')
  @Auth('normal')
  deleteBlog(@Param('id') id: string, @CurrentUser() user: User) {
    const blog = await this.blogService.findOne(id);
    if (user.id !== blog.authorId) {
      throw new AuthFailedException(`无权操作`);
    }
    // 删除博客
  }

  @Get('blogs')
  @Auth('admin')
  getBlogs() {
    // 获取所有博客
  }
}

在上面的例子中,createBlog/updateBlog/deleteBlog 方法需要具备 normal 权限,getBlogs 方法需要具备 admin 权限。

5. 总结

本攻略介绍了如何使用自定义注解实现接口权限控制的方式,在应用程序中使用自定义注解,可以提高代码的可读性,可维护性和可重用性,加速开发流程。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Nestjs自定义注解实现接口权限控制详解 - Python技术站

(0)
上一篇 2023年6月8日
下一篇 2023年6月8日

相关文章

  • nodejs mysql 实现分页的方法

    接下来我会详细讲解“nodejs mysql 实现分页的方法”的完整攻略。 1. 实现分页的基本原理 在实现分页的过程中,其基本原理是:通过SQL语句获取总数据量和分页数据,从而计算出总页数,再通过LIMIT语句实现指定起始数据和每页数据量的数据获取。 示例SQL语句: SELECT COUNT(*) FROM table_name; // 获取总数据量 S…

    node js 2023年6月8日
    00
  • Nodejs如何搭建Web服务器

    下面是关于如何搭建Node.js Web服务器的完整攻略。 1. 安装Node.js 首先,你需要在你的计算机上安装Node.js。你可以从Node.js的官方网站 https://nodejs.org 下载安装程序,按照提示安装Node.js,安装完成后,你可以通过在命令行中输入以下命令来检查Node.js是否成功安装: node -v 如果你看到输出了N…

    node js 2023年6月8日
    00
  • nodejs实现范围请求的实现代码

    Node.js是一个基于Chrome V8引擎的JavaScript运行环境,它可以在服务器端运行JavaScript,实现了事件驱动、非阻塞I/O模型。 实现范围请求是指客户端请求服务器上的某个资源时,服务器返回部分资源内容而不是全部内容。这种请求方式可以优化网络传输,因为它仅仅请求资源的一部分,例如在视频播放时可以只请求当前播放时间点以后的视频数据。 N…

    node js 2023年6月8日
    00
  • 利用NodeJS的子进程(child_process)调用系统命令的方法分享

    当我们需要在NodeJS中执行一些系统命令时,可以使用NodeJS提供的子进程模块(child_process)。下面,我将演示如何使用这个模块来调用系统命令的方法。 调用系统命令的方法 使用child_process模块调用系统命令分为三种方法:spawn/exec/execFile。 spawn方法 spawn方法是一种处理较大数据量命令的方法,它启动一…

    node js 2023年6月8日
    00
  • nodejs实现发出蜂鸣声音(系统报警声)的方法

    实现发出蜂鸣声音的方法可以使用Node.js中的’Beeper’模块完成。该模块允许用户在Windows和Linux平台上发出Beep声音。 以下是实现’Beeper’模块的步骤: 步骤1 – 安装Beeper模块 npm install beeper 步骤2 – 引入Beeper模块 const beeper = require(‘beeper’); 步骤…

    node js 2023年6月8日
    00
  • node连接mysql数据库遇到的问题和解决方案

    当使用Node连接MySQL数据库时,可能会遇到以下问题: 1.无法连接到数据库2.查询时出现错误3.无法处理回调函数 接下来我将分享一些解决这些问题的方法: 问题1:无法连接到数据库 当使用Node连接MySQL数据库时,可能会遇到无法连接到数据库的问题。出现这种情况可能是由于以下原因: 1.数据库已关闭2.重复的连接3.防火墙阻止了连接 下面是一个示例,…

    node js 2023年6月8日
    00
  • Node.js 日志处理模块log4js

    Node.js 日志处理模块log4js是一个流行的日志库,可用于记录应用程序的日志。 下面是使用log4js的完整攻略: 1. 安装log4js 使用以下npm命令安装log4js:npm install log4js –save 2. 配置log4js 创建一个名为log4js.json的配置文件(或者是一个JavaScript模块),定义日志的输出和…

    node js 2023年6月8日
    00
  • 利用Node.js检测端口是否被占用的方法

    当我们要在Node.js中搭建服务时,常常会遇到端口被占用的问题,比如在调试时想要使用某个端口,但是发现该端口已被占用,这时我们就需要知道如何检测端口是否被占用。下面我将给出一个检测端口是否被占用的方法的攻略。 方法一:利用net模块检测 Node.js的内置模块net提供了一个API,可以用来检测端口是否被占用,具体代码如下所示: const net = …

    node js 2023年6月8日
    00
合作推广
合作推广
分享本页
返回顶部