除了authentication,通常会需要以role来管理页面权限。
昨天提到Guard中的canActivate会传入ExecutionContext,透过reflect metadata可以取得处理request的对应controller及方法,进一步我们希望在controller下对应的方法指定权限,如新增使用者需要admin权限,然而问题是AuthGuard要怎么从controller读取权限设定值?
nest.js还提供可以被注入@ReflectMetadata decorator,动态取得bind在method上的参数,如下
app.controller.ts
@Controller()
@UseGuards(AuthGuard)
@UseFilters(new HttpexceptionFilter())
export class AppController {
...
@Post()
@ReflectMetadata('roles', ['admin']) //@ReflectMeatadata提供key-value pair功能,之后可以在AuthGuard里面取的此metadata
@UsePipes(PlatformDTOValidationPipe)
create(@Body() platformDTO: PlatformDTO){
throw new HttpException('糟糕!您的要求有问题,请联系管理员', HttpStatus.BAD_REQUEST);
return `平台:${platformDTO.platformname}已建立`;
}
...
}
修改auth.guard.ts
import { Injectable, CanActivate, ExecutionContext, Logger } from '@nestjs/common';
import { Observable } from 'rxjs';
import { Reflector } from '@nestjs/core';
@Injectable()
export class AuthGuard implements CanActivate{ // 实现CanActive接口
constructor(private readonly reflector: Reflector) {} // 注入Reflector,存取相关metadata
canActivate(
context: ExecutionContext, // 可以取得对应controller及request/request信息
): boolean | Promise<boolean> | Observable<boolean> { // 回传boolean类型,支持非同步
// 验证逻辑
const req = context.switchToHttp().getRequest(); // 取得request对象
const ctrl = context.getClass();
const handler = context.getHandler(); // nest.js利用reflect metadata取得存取资源对应的方法
// 利用get取得'roles'的值
// 第二个參數是告诉reflector取得哪一个方法的metadata
const roles = this.reflector.get<string[]>('roles', handler);
Logger.log(`---允许的Roles有---`);
// 使用Logger來測試有沒有取得roles的對應的value
Logger.log(roles);
if (req.hostname === 'localhost'){
return true;
}
return false;
}
}
用postman测试并观察console output
推荐一下我的公众号: 【 geekjc 】,微信号: 【 c8706288 】一起学习交流编程知识,分享经验,各种有趣的事。