权限与校验
权限与校验
Guards
守卫(Guards)是一个使用

守卫只有一个职责,就是决定请求是否需要被控制器处理。一般用在权限、角色的场景中。守卫和中间件的区别在于:中间件很简单,
绑定守卫
就像过滤器一样,守卫可以是控制器作用域的,也可以是方法作用域或者全局作用域。我们使用
@Controller("cats")
@UseGuards(RolesGuard)
export class CatsController {}
如果想引用到全局作用域可以调用
const app = await NestFactory.create(ApplicationModule);
app.useGlobalGuards(new RolesGuard());
由于我们在根模块外层引用了全局守卫,这时守卫无法注入依赖。所以我们还需要在要模块上引入。
import { Module } from "@nestjs/common";
import { APP_GUARD } from "@nestjs/core";
@Module({
providers: [
{
provide: APP_GUARD,
useClass: RolesGuard
}
]
})
export class ApplicationModule {}
授权守卫
@Injectable()
export class AuthGuard implements CanActivate {
canActivate(
context: ExecutionContext
): boolean | Promise<boolean> | Observable<boolean> {
const request = context.switchToHttp().getRequest();
return validateRequest(request);
}
}
执行上下文
export interface ExecutionContext extends ArgumentsHost {
getClass<T = any>(): Type<T>;
getHandler(): Function;
}
@Injectable()
export class RolesGuard implements CanActivate {
constructor(private readonly reflector: Reflector) {}
canActivate(context: ExecutionContext): boolean {
const roles = this.reflector.get<string[]>("roles", context.getHandler());
if (!roles) {
return true;
}
const request = context.switchToHttp().getRequest();
const user = request.user;
const hasRole = () => user.roles.some(role => roles.includes(role));
return user && user.roles && hasRole();
}
}
虽然现在已经有了守卫,但是它还没有执行上下文。
@Post()
@SetMetadata('roles', ['admin'])
async create(@Body() createCatDto: CreateCatDto) {
this.catsService.create(createCatDto);
}
上面的代码表示给
import { SetMetadata } from "@nestjs/common";
export const Roles = (...roles: string[]) => SetMetadata("roles", roles);
这样就可以用更简洁的方式来声明角色权限关系了:
@Post()
@Roles('admin')
async create(@Body() createCatDto: CreateCatDto) {
this.catsService.create(createCatDto);
}