下面我将详细讲解一下 “Nestjs自定义注解实现接口权限控制”的完整攻略。
1. 背景
在开发过程中,接口权限控制是一个非常重要的问题,通常实现的方式有基于角色、基于路由等等,但是这些方式灵活性较差,不够便捷。本攻略将详细介绍如何使用 Nestjs 自定义注解实现接口权限控制。
2. 环境准备
在开始之前,需要确保已经安装 nestjs
和 reflect-metadata
,安装方式如下:
npm i --save @nestjs/core reflect-metadata
3. 自定义注解实现接口权限控制
在 Nestjs 中,使用自定义注解实现接口权限控制的方式如下:
3.1. 编写权限功能代码
在权限功能代码中,我们需要实现如下逻辑:
- 定义注解:使用 Reflect Metadata 定义一个自定义注解,在注解中定义该接口需要的权限。
- 获取用户信息:获取当前用户的信息,通常是从用户的 token 中获取。这里我们假设我们从请求头中获取了用户的 token。
- 判断用户是否拥有权限:根据用户信息和权限注解,判断用户是否拥有权限。
代码如下:
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技术站