当前位置: 首页 > 工具软件 > nestjs-rbac > 使用案例 >

Nest JS 权限控制 rabc 0 的一种实现

叶展
2023-12-01

文章更多的是在于记录。有看不懂的评论

2.1 RBAC 0 https://juejin.cn/post/6844904109863075853#heading-3

最简单的用户、角色、权限模型。这里面又包含了2种:

  • 用户和角色是多对一关系,即:一个用户只充当一种角色,一种角色可以有多个用户担当。
  • 用户和角色是多对多关系,即:一个用户可同时充当多种角色,一种角色可以有多个用户担当。

jwt

依赖包

@nestjs/jwt passport-jwt

  1. 构建 jwt 策略

这是用来对 token 进行处理的。他会在 request

jwt.strategy.ts

import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { PassportStrategy } from '@nestjs/passport';
import { ExtractJwt, Strategy } from 'passport-jwt';
import { IJwtData } from 'src/types/user';

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
    constructor(private configService: ConfigService) {
        super({
            jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
            secretOrKey: configService.get('jwtSecret'),
        });
    }

    validate(data: IJwtData) {
        return data;
    }
}
  1. 生成 auth 模块
nest g res auth

auth.module.ts

import { Module } from '@nestjs/common';
import { AuthService } from './auth.service';
import { AuthController } from './auth.controller';
import { JwtModule } from '@nestjs/jwt';
import { ConfigService } from '@nestjs/config';
import { JwtStrategy } from 'src/strategy/jwt.strategy';

@Module({
    imports: [
        JwtModule.registerAsync({
            inject: [ConfigService],
            useFactory: (configService: ConfigService) => {
                return {
                    secret: configService.get('jwtSecret'),
                    signOptions: {
                        expiresIn: '4h',
                    },
                };
            },
        }),
    ],
    controllers: [AuthController],
    providers: [AuthService, JwtStrategy],
    exports: [AuthService],
})
export class AuthModule {}

auth.service.ts

import { InjectRedis } from '@liaoliaots/nestjs-redis';
import { Injectable, UnauthorizedException } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import Redis from 'ioredis';
import { IJwtData } from 'src/types/user';

@Injectable()
export class AuthService {
    constructor(
        @InjectRedis()
        private readonly redis: Redis,
        private jwtService: JwtService,
    ) {}

    createToken(data: IJwtData) {
        const token = this.jwtService.sign(data);
        this.redis.hset('dialogua:token', token, 1);
        return token;
    }

    async validate(token?: string) {
        if (!token) throw new UnauthorizedException();
        const exit = await this.redis.hexists('dialogua:token', token);
        if (!exit) throw new UnauthorizedException();
    }
}

全局守卫

auth.guard.ts

import { InjectRedis } from '@liaoliaots/nestjs-redis';
import { ExecutionContext, Injectable, UnauthorizedException } from '@nestjs/common';
import Redis from 'ioredis';
import { AuthGuard } from '@nestjs/passport';
import { ExtractJwt } from 'passport-jwt';
import { Reflector } from '@nestjs/core';
import { AuthService } from 'src/modules/auth/auth.service';

@Injectable()
export class RbacAuthGuard extends AuthGuard('jwt') {
    constructor(
        @InjectRedis() private readonly redis: Redis,
        private authService: AuthService,
        private reflector: Reflector,
    ) {
        super();
    }
    async canActivate(context: ExecutionContext): Promise<any> {
        const isPublic = this.reflector.get<boolean>('isPublic', context.getHandler());
        if (isPublic) return true;

        const request = context.switchToHttp().getRequest();
        const token = ExtractJwt.fromAuthHeaderAsBearerToken()(request);
        await this.authService.validate(token);

        return super.canActivate(context);
    }
}

挂载

app.module.ts

在这个文件里挂载是因为 guard 有依赖。 如果用 globalGuard. 无法自动注入依赖

import { RedisModule } from '@liaoliaots/nestjs-redis';
import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { APP_GUARD } from '@nestjs/core';
import { JwtService } from '@nestjs/jwt';
import { TypeOrmModule } from '@nestjs/typeorm';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import config from './config';
import { RbacAuthGuard } from './guards/auth.guard';
import modules from './modules';

@Module({
    imports: [
        ...modules,
    ],
    controllers: [AppController],
    providers: [
    // 这里。 
        {
            provide: APP_GUARD,
            useClass: RbacAuthGuard,
        },
    ],
})
export class AppModule {}
 类似资料: