You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NestJS中/auth-status端点数字字符串验证错误求助

NestJS /users/auth-status端点验证错误:"Validation failed (numeric string is expected)"

向http://localhost:3000/users/auth-status发送请求时,收到以下400错误:

{
    "message": "Validation failed (numeric string is expected)",
    "error": "Bad Request",
    "statusCode": 400
}

相关代码配置

1. DTO类(CreatePostDto)

import { IsInt, IsNotEmpty, IsNumberString, IsOptional, IsString } from 'class-validator';

export class CreatePostDto {
  @IsNotEmpty()
  @IsString()
  title: string;

  @IsNotEmpty()
  @IsString()
  content: string;

  @IsOptional()
  @IsString()
  mainImageUrl: string;

  @IsInt()
  userId: number;

  @IsInt()
  categoryId?: number; // Optional field
}

2. 当前用户守卫(Current User Guard)

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

export class CurrentUserGuard extends AuthGuard('jwt') {
  handleRequest(err: any, user: any) {
    if (user) return user;
    return null;
  }
}

3. JWT策略(JWT Strategy)

import { Injectable, UnauthorizedException } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { ExtractJwt, Strategy } from 'passport-jwt';
import { Request } from 'express';
import { InjectRepository } from '@nestjs/typeorm';
import { User } from './entities/user.entity';
import { Repository } from 'typeorm';

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor(@InjectRepository(User) private readonly userRepo: Repository<User>) {
    super({
      jwtFromRequest: ExtractJwt.fromExtractors([(request: Request) => {
        return request?.cookies?.Authentication;
      }]),
      ignoreExpiration: false,
      secretOrKey: 'secretKey', // Use your own secret key here
    });
  }

  async validate(payload: any, req: Request) {
    if (!payload) {
      throw new UnauthorizedException('Invalid JWT payload');
    }

    const user = await this.userRepo.findOneBy({ username: payload.username });
    if (!user) {
      throw new UnauthorizedException();
    }
    req.user = user;
    return req.user;
  }
}

4. 当前用户装饰器及端点(Current User Decorator and Endpoint)

import { ExecutionContext, createParamDecorator } from "@nestjs/common";

export const CurrentUser = createParamDecorator(
  (data: unknown, context: ExecutionContext) => {
    const request = context.switchToHttp().getRequest();
    return request.user;
  }
);

@Get('auth-status')
@UseGuards(CurrentUserGuard)
@HttpCode(HttpStatus.OK)
authStatus(@CurrentUser() user: User) {
  console.log('Authenticated User:', user);
  return { status: !!user, user };
}

已尝试的操作

  • 验证DTO及装饰器的使用
  • 检查请求payload是否存在问题
  • 确保JWT策略配置正确

问题排查与解决方案

1. 全局验证管道误触发

如果应用配置了全局ValidationPipe,它会自动验证所有请求的对象,包括挂载在request.user上的用户实体。若User实体中的数字字段(如id)与验证器预期的类型不匹配,就会触发该错误。

解决方法:给auth-status端点添加@SkipValidation()装饰器,跳过该端点的自动验证:

import { SkipValidation } from '@nestjs/common';

@Get('auth-status')
@UseGuards(CurrentUserGuard)
@HttpCode(HttpStatus.OK)
@SkipValidation()
authStatus(@CurrentUser() user: User) {
  // ...
}

2. JWT payload与用户实体类型不匹配

若JWT payload中的数字字段是字符串类型,但User实体定义为数字类型,全局验证管道会因类型不匹配抛出错误。

解决方法:在JwtStrategy的validate方法中,确保从数据库查询到的user对象字段类型符合实体定义;或根据需求调整User实体的验证装饰器(比如用@IsNumberString()替代@IsInt(),如果需要兼容数字字符串)。

3. 隐藏的路由/查询参数验证

确认auth-status路由没有未声明的参数(如@Get('auth-status/:id')),若存在这类参数且传递值不符合数字字符串要求,也会触发错误。

4. 依赖版本冲突

确保class-validator和class-transformer版本与NestJS兼容,可尝试重新安装依赖:

npm install class-validator@latest class-transformer@latest

内容的提问来源于stack exchange,提问作者Tarek Ziad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 16:25:03