【问题标题】:Authorization in Nestjs using graphql在 Nestjs 中使用 graphql 进行授权
【发布时间】:2021-06-09 07:49:59
【问题描述】:

我已经开始学习 Nestjs、express 和 graphql。 我在尝试授权使用 jwt 令牌进行身份验证的用户访问时遇到问题。 我按照教程在Nestjs website 上进行身份验证。 我能够获取当前用户,但是当我尝试实现basic role base access control 时,我无法在 canActivate 方法中访问当前用户。 我认为这是因为 Roles Guard 在 Graphql Guard 之前执行。

我会在这里发布代码

gql-auth.guard.ts

import { ExecutionContext } from "@nestjs/common";
import { GqlExecutionContext } from "@nestjs/graphql";
import { AuthGuard } from "@nestjs/passport";

export class GqlAuthGuard extends AuthGuard("jwt") {
    getRequest(context: ExecutionContext) {
        const ctx = GqlExecutionContext.create(context);
        console.log("gql simple context: ", context);
        console.log("gqlContext: ", ctx.getContext());
        return ctx.getContext().req;
    }
}

roles.guard.ts

import { CanActivate, ExecutionContext, Injectable } from "@nestjs/common";
import { Reflector } from "@nestjs/core";
import { GqlExecutionContext } from "@nestjs/graphql";

@Injectable()
export class RolesGuard implements CanActivate {
    constructor(private reflector: Reflector) {}

    canActivate(context: ExecutionContext) {
        const roles = this.reflector.get<string[]>("roles", context.getHandler());
        const ctx = GqlExecutionContext.create(context);
        console.log("roles: ", roles);
        console.log("context: ", context.switchToHttp().getRequest());
        console.log("gqlContext: ", ctx.getContext().req);

        return true;
    }
}

jwt.strategy.ts

import { Injectable } from "@nestjs/common";
import { PassportStrategy } from "@nestjs/passport";
import { ExtractJwt, Strategy } from "passport-jwt";
import { jwtConstants } from "../constants";

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
    constructor() {
        super({
            jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
            ignoreExpiration: false,
            secretOrKey: jwtConstants.secret,
        });
    }

    validate(payload: any) {
        console.log("payload: ", payload);

        return payload;
    }
}

解析器

@UseGuards(GqlAuthGuard)
@Roles("ADMIN")
@UseGuards(RolesGuard)
@Query((returns) => [Specialty], { nullable: "itemsAndList", name: "specialties" })
async getSpecialties(@Args() params: FindManySpecialtyArgs, @Info() info: GraphQLResolveInfo) {
    const select = new PrismaSelect(info).value;
    params = { ...params, ...select };
    return this.prismaService.specialty.findMany(params);
}

之前有没有人成功实现过这个?

【问题讨论】:

    标签: graphql nestjs nestjs-passport nestjs-jwt


    【解决方案1】:

    你应该在同一个 @UseGuards() 装饰器中使用这两个守卫。喜欢@UseGuards(GqlAuthGuard, RolesGuard)。 Nest 将毫无问题地按顺序运行这些。

    【讨论】:

    • 嗨,为什么要使用空的“@UseGuards()”?
    • 我提到了装饰器的全名。不要看太多
    【解决方案2】:
    export const Authorize = (roles?: string | string[]) =>
      applyDecorators(
        SetMetadata('roles', [roles].flat()),
        UseGuards(GqlAuthGuard, RolesGuard),
      );
    
    @Authorize("ADMIN")
    @Query((returns) => [Specialty], { nullable: "itemsAndList", name: "specialties" })
    async getSpecialties(@Args() params: FindManySpecialtyArgs, @Info() info: GraphQLResolveInfo) {
        const select = new PrismaSelect(info).value;
        params = { ...params, ...select };
        return this.prismaService.specialty.findMany(params);
    }
    
    

    【讨论】:

      【解决方案3】:

      完整的授权码Graphql和NestJs:

      @Injectable()
      export class RolesGuard_ implements CanActivate {
        constructor(private reflector: Reflector) {}
      
        canActivate(context: ExecutionContext): boolean {
          const ctx = GqlExecutionContext.create(context);
      
          const requiredRoles = this.reflector.getAllAndOverride<Role[]>(ROLES_KEY, [
            context.getHandler(),
            context.getClass(),
          ]);
      
          if (!requiredRoles) {
            return true;
          }
      
          const { user } = ctx.getContext().req;
          return requiredRoles.some((role) => user.role?.includes(role));
        }
      }
      

      【讨论】:

        猜你喜欢
        • 2022-01-24
        • 1970-01-01
        • 1970-01-01
        • 2017-11-22
        • 2022-01-16
        • 2017-09-28
        • 2020-12-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多