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 '{"username": "john", "password": "changeme"}' -H "Content-Type: application/json"
返回结果:
{"statusCode":401,"message":"Unauthorized"}
我已查阅相关资料但未解决问题,严格遵循文档实现仍出现该错误。运行环境为MacOS,Node版本从v18.6升级到v19.0.1后问题依然存在。
问题排查与解决方案
1. 修复curl命令的转义问题
MacOS终端中,单引号包裹的JSON不需要对双引号进行HTML转义,你命令中的"会导致请求体不是有效的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
相关产品推荐
相关产品推荐

