我将使用Nest.js结合GraphQL和Passport来创建认证处理

在Nest.js中使用Passport作为认证库的方法在官方文档中有介绍,并以在GraphQL中的实现作为参考。
但是,在GraphQL中的实现仅仅是作为参考,不能单独运行。
本次实现将致力于在GraphQL中实际实现基于用户名和密码的认证。

1. 创建基础项目

使用以下命令创建一个Nest.js项目。

$ npm i -g @nestjs/cli
$ nest new passport-sample
$ cd passport-sample

项目创建后,根据身份验证需求的步骤安装所需的库。

2. 创建模块

根据实施Passport策略,创建必要的护照样本模块并进行示例实现各种逻辑。
在这里将创建以下文件。

    • users/users.service.ts

 

    • users/users.module.ts

 

    • auth/auth.service.ts

 

    auth/auth.module.ts

3. 创建本地策略

根据Passport local的实现,我们将实现一个执行验证的LocalStrategy来进行认证。
LocalStrategy的实现如下所示。

import { Strategy } from 'passport-local';
import { PassportStrategy } from '@nestjs/passport';
import { Injectable, UnauthorizedException } from '@nestjs/common';
import { AuthService } from './auth.service';

@Injectable()
export class LocalStrategy extends PassportStrategy(Strategy) {
  constructor(private authService: AuthService) {
    super();
  }

  async validate(username: string, password: string): Promise<any> {
    const user = await this.authService.validateUser(username, password);
    if (!user) {
      throw new UnauthorizedException();
    }
    return user;
  }
}

按照步骤,也更新AuthModule。

4. 创建本地身份验证保护(LocalAuthGuard)。

在公式文档中,LocalAuthGuard是这样的:

import { Injectable } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';

@Injectable()
export class LocalAuthGuard extends AuthGuard('local') {}

然而,由于此实施方式无法正确地将从GraphQL传递的参数传递给LocalStrategy,因此认证会失败。
因此,要在GraphQL中实现该LocalAuthGuard,需要使用getRequest方法将参数映射如下。

import { Injectable, ExecutionContext } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { GqlExecutionContext } from '@nestjs/graphql';

@Injectable()
export class LocalAuthGuard extends AuthGuard('local') {
  getRequest(context: ExecutionContext) {
    const ctx = GqlExecutionContext.create(context);
    const gqlReq = ctx.getContext().req;

    if (gqlReq) {
      gqlReq.body = ctx.getArgs();
      return gqlReq;
    }
    return context.switchToHttp().getRequest();
  }
}

5. 将Mutaion设为LocalAuthGuard.

首先,我们要定义一个用于返回用户信息的模型。


import { Field, Int, ObjectType } from '@nestjs/graphql';

@ObjectType()
export class User {
  @Field(type => Int)
  userId: number;

  @Field()
  username: string;
}

在app.resolver.ts中创建一个名为login的Mutation,并设置LocalAuthGuard。

import { UseGuards, UseInterceptors } from '@nestjs/common';
import { Resolver, Mutation, Args } from '@nestjs/graphql';

import { LocalAuthGuard } from './auth/local-auth.guard';
import { User } from './users/models/user.model';

@Resolver()
export class AppResolver {
  @UseGuards(LocalAuthGuard)
  @Mutation(() => User)
  async login(
    @Request() req,
    @Args({ name: 'username', type: () => Int }) _: number,
    @Args({ name: 'password' }) _: string
  ): Promise<User> {
    return req.user
  }
}

用这个方法,你可以在GraphQl中使用Passport进行身份验证。

广告
将在 10 秒后关闭
bannerAds