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

yizhihongxing

下面我将详细讲解一下 “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日

相关文章

  • node中的Express框架详解

    下面是关于“node中的Express框架详解”的攻略,包含了框架的基本概念,常用的组件,常用的操作和两条示例说明。 一、Express框架基本概念 1、Express框架概述 Express 是一个基于 Node.js 的 Web 应用开发框架,它提供了丰富的 HTTP 实用功能及插件,用于快速地搭建 Web 应用程序和移动应用程序。其主要特点是易于学习和…

    node js 2023年6月8日
    00
  • Windows环境下npm install 报错: operation not permitted, rename的解决方法

    当我们在Windows环境下使用npm进行包的安装时,有时候可能会遇到”operation not permitted, rename”的问题,这是因为Windows系统有时候会给文件锁定,从而导致文件重命名失败。下面我将为大家提供两种解决方法。 方法一:使用管理员权限打开命令行 打开命令行时,需要使用管理员权限。在Windows系统下有两种方法打开命令行。…

    node js 2023年6月8日
    00
  • 带你了解NodeJS事件循环

    带你了解NodeJS事件循环 NodeJS中的事件循环是NodeJS异步编程的核心,非常重要。了解NodeJS事件循环对于编写高效的NodeJS程序至关重要。下面,本文将带你深入了解NodeJS事件循环的完整攻略。 NodeJS事件循环的基本原理 NodeJS事件循环的核心概念是事件循环(Single-threaded Event Loop)。NodeJS基…

    node js 2023年6月8日
    00
  • Vue如何使用Element-ui表单发送数据与多张图片到后端详解

    Vue是一款现代的JavaScript框架,它被广泛地应用在前端开发中。而Element-ui是一个基于Vue框架的UI库,提供了很多便捷的组件。在实际开发中,我们常常需要使用Element-ui的表单组件来发送表单数据到后台,并且也常常需要上传图片等文件。下面我们就来详细讲解一下“Vue如何使用Element-ui表单发送数据与多张图片到后端”的攻略。 1…

    node js 2023年6月8日
    00
  • npm install报错unable to resolve dependency tree的解决办法

    当我们使用 npm install 安装依赖时,有时会遇到 unable to resolve dependency tree 的报错,这个错误表示在安装依赖时出现了依赖项的冲突或缺失。下面是解决这个问题的完整攻略: 步骤一:更新npm和node 在终端中执行以下命令可以更新 npm 和 node: npm install -g npm nvm instal…

    node js 2023年6月8日
    00
  • 详解如何使用nvm管理Node.js多版本

    当我们在使用 Node.js 进行开发时,有时候需要用到多个不同版本的 Node.js。这时候,我们可以使用 nvm 来方便地管理多个版本的 Node.js。 下面是使用 nvm 管理 Node.js 多个版本的完整攻略: 安装 nvm 首先,我们需要安装 nvm,可以在 https://github.com/nvm-sh/nvm 上找到最新的安装方法。在终…

    node js 2023年6月8日
    00
  • JSON基本语法及与JavaScript的异同实例分析

    JSON基本语法及与JavaScript的异同实例分析 什么是JSON JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,由Douglas Crockford在2001年提出。它基于JavaScript语法,但是是一种独立于语言的数据格式,可以被多种编程语言使用和解析。 JSON数据格式也易于人阅读和编写,这使得它成…

    node js 2023年6月8日
    00
  • npm报错:无法将”npm”项识别为cmdlet、函数、脚本文件或可运行程序的名称

    当我们在使用npm命令时,有时可能会遇到以下报错: 无法将"npm"项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径,请确保路径正确,然后再试一次。 这个错误是因为电脑没有安装npm或npm没有配置到环境变量中所致。 以下是解决这个问题的方法: 方法一:安装Node.js npm是随Node.js一…

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