如何在传递给passportjs AuthGuard之前使用类验证器验证dto



在传递到passport AuthGuard之前,如何使用类验证器验证dto?我想使用类验证器来验证传入的dto,但我看到";未经授权的";而不是错误的请求异常,因为管道是在nestjs中的guard之后进行评估的。我如何改变这种行为,或者我必须在auth-guard中验证dto?

您可以实现自己的保护。让我们看一个本地策略的例子:

在保护文件中,使用class-validator库手动验证请求主体:

// src/auth/local-auth.guard.ts
import { ExecutionContext, HttpStatus, Injectable } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { Request, Response } from 'express';
import { LogInUserDto } from '../users/dto/log-in-user.dto';
import { plainToClass } from 'class-transformer';
import { validate } from 'class-validator';
@Injectable()
export class LocalAuthGuard extends AuthGuard('local') {
async canActivate(context: ExecutionContext) {
const request = context.switchToHttp().getRequest<Request>();
const response = context.switchToHttp().getResponse<Response>();
// transform the request object to class instance
const body = plainToClass(LogInUserDto, request.body);
// get a list of errors
const errors = await validate(body);
// extract error messages from the errors array
const errorMessages = errors.flatMap(({ constraints }) =>
Object.values(constraints),
);
if (errorMessages.length > 0) {
// return bad request if validation fails
response.status(HttpStatus.BAD_REQUEST).send({
statusCode: HttpStatus.BAD_REQUEST,
error: 'Bad Request',
message: errorMessages,
});
}
return super.canActivate(context) as boolean | Promise<boolean>;
}
}

这是将用于保护中验证的DTO类:

// src/users/dto/log-in-user.dto.ts
import { IsEmail, IsNotEmpty, IsString } from 'class-validator';
export class LogInUserDto {
@IsEmail()
email: string;
@IsNotEmpty()
@IsString()
password: string;
}

本地策略文件如下所示:

// src/auth/local.strategy.ts
import { PassportStrategy } from '@nestjs/passport';
import { Strategy } from 'passport-local';
import { AuthService } from './auth.service';
import { Injectable } from '@nestjs/common';
@Injectable()
export class LocalStrategy extends PassportStrategy(Strategy) {
constructor(private readonly authService: AuthService) {
super({ usernameField: 'email' });
}
async validate(email: string, password: string) {
const user = await this.authService.validateUser(email, password);
return user;
}
}

这就是如何将本地策略应用于您的路线:

// src/auth/auth.controller.ts
import { Controller, Post, UseGuards, Req } from '@nestjs/common';
import { LocalAuthGuard } from './local-auth.guard';
import { User } from '../users/entities/user.entity';
@Controller('auth')
export class AuthController {
constructor(private readonly authService: AuthService) {}
@UseGuards(LocalAuthGuard)
@Post('/login')
async logIn(
@Req()
request: {
user: User;
},
) {
return await this.authService.logIn(request.user);
}
}

您可以查看有关护照库的官方nestJS文档以了解更多信息。

这不是很像NestJS的方式,但可能唯一可以使用的选项是验证DTO内部策略,您的警卫正在使用:

import { PassportStrategy } from '@nestjs/passport';
import { Strategy } from 'passport-strategy';
import { validate } from 'class-validator';
import { BadRequestException } from '@nestjs/common'; 
class YourStrategy extends PassportStrategy(Strategy) {
authenticate(req, options) {
const errors = validate(req.body);
if (errors) {
throw new BadRequestException({ errors });
}
super.authenticate(req, options);
}
}

最新更新