【NestJS】权限控制方案

有两种方案:

  • ACL (Access Control List)权限控制
  • RBAC(Role Based Access Control)权限控制

ACL (Access Control List)权限控制

这种记录每个用户有什么权限的方式,叫做访问控制表(Access Control List)。

介绍

  • 特点是用户直接和权限关联。
  • 用户和权限是多对多关系,在数据库中会存在用户表、权限表、用户权限中间表。
  • 登录的时候,把用户信息查出来,放到 session 或者 jwt 返回。
  • 然后访问接口的时候,在 Guard 里判断是否登录,是否有权限,没有就返回 401,有的话才会继续处理请求。

使用

添加创建 user 模块:

sql 复制代码
nest g resource user

添加 User 和 Permission 的 Entity:

js 复制代码
import { Column, CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn } from "typeorm";

@Entity()
export class User {
    @PrimaryGeneratedColumn()
    id: number;

    @Column({
        length: 50
    })
    username: string;

    @Column({
        length: 50
    })
    password: string;

    @CreateDateColumn()
    createTime: Date;

    @UpdateDateColumn()
    updateTime: Date;
}

User 有 id、username、password、createTime、updateTime 5 个字段。

js 复制代码
import { Column, CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn } from "typeorm";

@Entity()
export class Permission {
    @PrimaryGeneratedColumn()
    id: number;

    @Column({
        length: 50
    })
    name: string;
    
    @Column({
        length: 100,
        nullable: true
    })
    desc: string;

    @CreateDateColumn()
    createTime: Date;

    @UpdateDateColumn()
    updateTime: Date;
}

permission 有 id、name、desc、createTime、updateTime 5 个字段,desc 字段可以为空。

然后在 User 里加入和 Permission 的关系,也就是多对多:

js 复制代码
@ManyToMany(() => Permission)
@JoinTable({
    name: 'user_permission_relation'
})
permissions: Permission[] 

通过 @ManyToMany 声明和 Permisssion 的多对多关系。

多对多是需要中间表的,通过 @JoinTable 声明,指定中间表的名字。

然后在 TypeOrm.forRoot 的 entities 数组加入 entity UserPermission:

把 Nest 服务跑起来试试:

arduino 复制代码
npm run start:dev

可以看到生成了 user、permission、user_permission_relation 这 3 个表。

并且中间表 user_permission_relation 还有 userId、permissionId 两个外键。

RBAC(Role Based Access Control)权限控制

这种记录每个用户有什么权限的方式,叫做访问控制表(Access Control List)。

介绍

  • 相比于 ACL (access control list)的方式,多了一层角色,给用户分配角色而不是直接分配权限。
  • 检查权限的时候还是要把角色的权限合并之后再检查是否有需要的权限的。
  • 通过 jwt 实现了登录,把用户和角色信息放到 token 里返回。
  • 添加了 LoginGuard 来做登录状态的检查。
  • 然后添加了 PermissionGuard 来做权限的检查。
  • LoginGuard 里从 jwt 取出 user 信息放入 request,PermissionGuard 从数据库取出角色对应的权限,检查目标 handler 和 controller 上声明的所需权限是否满足。
  • LoginGuard 和 PermissionGuard 需要注入一些 provider,所以通过在 AppModule 里声明 APP_GUARD 为 token 的 provider 来注册的全局 Guard。
  • 然后在 controller 和 handler 上添加 metadata 来声明是否需要登录,需要什么权限,之后在 Guard 里取出来做检查。

使用

添加创建 user 模块:

sql 复制代码
nest g resource user

添加 User、Role、Permission 的 Entity: 用户、角色、权限都是多对多的关系。

js 复制代码
import { Column, CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn } from "typeorm";

@Entity()
export class User {
    @PrimaryGeneratedColumn()
    id: number;

    @Column({
        length: 50
    })
    username: string;

    @Column({
        length: 50
    })
    password: string;

    @CreateDateColumn()
    createTime: Date;

    @UpdateDateColumn()
    updateTime: Date;
    
    @ManyToMany(() => Role)
    @JoinTable({
        name: 'user_role_relation'
    })
    roles: Role[] 
}

User 有 id、username、password、createTime、updateTime 5 个字段。

通过 @ManyToMany 映射和 Role 的多对多关系,并指定中间表的名字。

然后创建 Role 的 entity:

js 复制代码
import { Column, CreateDateColumn, Entity,PrimaryGeneratedColumn, UpdateDateColumn } from "typeorm";

@Entity()
export class Role {
    @PrimaryGeneratedColumn()
    id: number;

    @Column({
        length: 20
    })
    name: string;

    @CreateDateColumn()
    createTime: Date;

    @UpdateDateColumn()
    updateTime: Date;
    
    @ManyToMany(() => Permission)
    @JoinTable({
        name: 'role_permission_relation'
    })
    permissions: Permission[] 
}

Role 有 id、name、createTime、updateTime 4 个字段。

通过 @ManyToMany 映射和 Permission 的多对多关系,并指定中间表的名字。

js 复制代码
import { Column, CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn } from "typeorm";

@Entity()
export class Permission {
    @PrimaryGeneratedColumn()
    id: number;

    @Column({
        length: 50
    })
    name: string;
    
    @Column({
        length: 100,
        nullable: true
    })
    desc: string;

    @CreateDateColumn()
    createTime: Date;

    @UpdateDateColumn()
    updateTime: Date;
}

Permission 有 id、name、createTime、updateTime 4 个字段。

然后在 TypeOrm.forRoot 的 entities 数组加入这三个 entity:

把 Nest 服务跑起来试试:

arduino 复制代码
npm run start:dev

可以看到生成了 user、role、permission 这 3 个表,还有 user_roole_relation、role_permission_relation 这 2 个中间表。

相关推荐
Spirited_Away4 天前
Nest世界中的AOP
前端·node.js·nestjs
Eric_见嘉11 天前
NestJS 🧑‍🍳 厨子必修课(六):Prisma 集成(下)
前端·后端·nestjs
kongxx1 个月前
NestJS中使用Guard实现路由保护
nestjs
白雾茫茫丶1 个月前
Nest.js 实战 (十二):优雅地使用事件发布/订阅模块 Event Emitter
nestjs·nest.js·发布订阅·event emitter
lph65822 个月前
比起上传资源更应该懂得如何资源回收
node.js·nestjs
gsls2008082 个月前
将nestjs项目迁移到阿里云函数
阿里云·云计算·nestjs·云函数
d3126975102 个月前
在Nestjs使用mysql和typeorm
mysql·express·nestjs·typeorm
剪刀石头布啊2 个月前
nestjs-版本控制
nestjs
潇洒哥gg3 个月前
重生之我在NestJS中使用jwt鉴权
前端·javascript·nestjs
huangkaihao3 个月前
【NestJS学习笔记】 之 自定义装饰器
前端·node.js·nestjs