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

NestJS本地认证返回401 Unauthorized问题求助

NestJS本地认证返回401未授权问题

我按照NestJS官方文档实现认证功能,以下是我的代码:

user.service.ts

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

// This should be a real class/interface representing a user entity
export type User = any;

@Injectable()
export class UsersService {
  private readonly users = [
    {
      userId: 1,
      username: 'john',
      password: 'changeme',
    },
    {
      userId: 2,
      username: 'maria',
      password: 'guess',
    },
  ];

  async findOne(username: string): Promise<User | undefined> {
    return this.users.find(user => user.username === username);
  }
}

user.module.ts

import { Module } from '@nestjs/common';
import { UsersService } from './users.service';

@Module({
  providers: [UsersService],
  exports: [UsersService],
})
export class UsersModule {}

auth.service.ts

import { Injectable } from '@nestjs/common';
import { UsersService } from '../users/users.service';

@Injectable()
export class AuthService {
  constructor(private usersService: UsersService) {}

  async validateUser(username: string, pass: string): Promise<any> {
    const user = await this.usersService.findOne(username);
    if (user && user.password === pass) {
      const { password, ...result } = user;
      return result;
    }
    return null;
  }
}

auth.module.ts(初始版本)

import { Module } from '@nestjs/common';
import { AuthService } from './auth.service';
import { UsersModule } from '../users/users.module';

@Module({
  imports: [UsersModule],
  providers: [AuthService],
})
export class AuthModule {}

随后我使用Passport-local实现了本地认证策略:

local.strategy.ts

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;
  }
}

更新后的auth.module.ts

import { Module } from '@nestjs/common';
import { AuthService } from './auth.service';
import { UsersModule } from '../users/users.module';
import { PassportModule } from '@nestjs/passport';
import { LocalStrategy } from './local.strategy';

@Module({
  imports: [UsersModule, PassportModule],
  providers: [AuthService, LocalStrategy],
})
export class AuthModule {}

app.controller.ts

import { Controller, Request, Post, UseGuards } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';

@Controller()
export class AppController {
  @UseGuards(AuthGuard('local'))
  @Post('auth/login')
  async login(@Request() req) {
    return req.user;
  }
}

执行以下测试命令:

$ curl -X POST http://localhost:3000/auth/login -d '{&quot;username&quot;: &quot;john&quot;, &quot;password&quot;: &quot;changeme&quot;}' -H "Content-Type: application/json"

返回结果:

{"statusCode":401,"message":"Unauthorized"}

我已查阅相关资料但未解决问题,严格遵循文档实现仍出现该错误。运行环境为MacOS,Node版本从v18.6升级到v19.0.1后问题依然存在。


问题排查与解决方案

1. 修复curl命令的转义问题

MacOS终端中,单引号包裹的JSON不需要对双引号进行HTML转义,你命令中的&quot;会导致请求体不是有效的JSON。正确的测试命令应为:

$ curl -X POST http://localhost:3000/auth/login -d '{"username": "john", "password": "changeme"}' -H "Content-Type: application/json"

2. 确认JSON请求体解析正常

NestJS默认会配置JSON解析中间件,但如果手动修改过中间件可能导致解析失败。可以在main.ts中显式启用JSON解析:

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { json } from 'express';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.use(json());
  await app.listen(3000);
}
bootstrap();

3. 显式指定LocalStrategy字段配置

虽然默认字段是username和password,但显式配置可以排除字段匹配问题:

// local.strategy.ts
constructor(private authService: AuthService) {
  super({ usernameField: 'username', passwordField: 'password' });
}

4. 添加调试日志定位问题

在AuthService和LocalStrategy中添加日志,确认验证流程哪一步出错:

// auth.service.ts
async validateUser(username: string, pass: string): Promise<any> {
  console.log('接收的用户名:', username, '密码:', pass);
  const user = await this.usersService.findOne(username);
  console.log('查询到的用户:', user);
  if (user && user.password === pass) {
    const { password, ...result } = user;
    return result;
  }
  return null;
}

启动服务后执行测试命令,查看终端日志,确认参数接收、用户查询是否正常。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 15:15:40