如何在NestJS中验证Laravel Passport签发的Bearer Token?
Laravel Passport Token 在 NestJS 微服务中的本地验证方案
方案可行性
完全可行。Laravel Passport 默认签发的是 RS256 算法签名的 JWT 格式 Bearer Token,只要拿到对应的公钥,就能在 NestJS 中直接本地验证,无需每次请求 Laravel API 做校验。
具体实现步骤
1. 从 Laravel 项目获取验证所需资源
- 公钥:在 Laravel 项目中,执行
php artisan passport:keys生成的公钥文件位于storage/oauth-public.key,将该文件复制到 NestJS 项目的配置目录(比如config/),或者复制文件内容用于后续配置。 - Issuer 地址:Laravel 项目
.env中的APP_URL(Token payload 中的iss字段值)。
2. 安装 NestJS 依赖包
执行以下命令安装 JWT 验证相关依赖:
npm install @nestjs/jwt @nestjs/passport passport-jwt npm install -D @types/passport-jwt
3. 实现 JWT 验证策略
创建 src/auth/jwt.strategy.ts 文件,编写验证逻辑:
import { Injectable } from '@nestjs/common'; import { PassportStrategy } from '@nestjs/passport'; import { ExtractJwt, Strategy } from 'passport-jwt'; import * as fs from 'fs'; import * as path from 'path'; @Injectable() export class JwtStrategy extends PassportStrategy(Strategy) { constructor() { super({ // 从请求头的 Authorization 中提取 Bearer Token jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), // 不忽略过期时间,过期 Token 直接拒绝 ignoreExpiration: false, // 加载 Laravel 公钥用于验证签名 secretOrKey: fs.readFileSync(path.join(__dirname, '../../config/oauth-public.key'), 'utf8'), // 指定 Token 的 issuer(需与 Laravel 的 APP_URL 一致) issuer: 'http://localhost:8000', // Laravel Passport 默认用 RS256 算法,必须指定 algorithms: ['RS256'], }); } // Token 验证通过后,解析 payload 并返回用户信息供接口使用 async validate(payload: any) { // 可根据业务需求从数据库查询用户详情,或直接返回 payload 中的字段 return { userId: payload.sub, email: payload.email }; } }
4. 注册 Auth 模块
创建 src/auth/auth.module.ts,将策略和 JWT 模块注册到 NestJS:
import { Module } from '@nestjs/common'; import { PassportModule } from '@nestjs/passport'; import { JwtModule } from '@nestjs/jwt'; import { JwtStrategy } from './jwt.strategy'; import * as fs from 'fs'; import * as path from 'path'; @Module({ imports: [ PassportModule, JwtModule.register({ secret: fs.readFileSync(path.join(__dirname, '../../config/oauth-public.key'), 'utf8'), signOptions: { issuer: 'http://localhost:8000', algorithm: 'RS256' }, }), ], providers: [JwtStrategy], exports: [JwtModule], }) export class AuthModule {}
5. 保护接口
在需要验证的控制器中,使用 @UseGuards(AuthGuard('jwt')) 装饰器保护接口:
import { Controller, Get, UseGuards, Request } from '@nestjs/common'; import { AuthGuard } from '@nestjs/passport'; @Controller('user') export class UserController { @Get('profile') @UseGuards(AuthGuard('jwt')) getProfile(@Request() req) { return { message: '获取用户信息成功', user: req.user }; } }
常见验证失败排查点
- 算法不匹配:必须指定
algorithms: ['RS256'],Laravel Passport 不使用 HS256 算法,用错会直接验证失败。 - 公钥错误:确保使用的是
oauth-public.key而不是私钥oauth-private.key,公钥内容必须完整(包含-----BEGIN PUBLIC KEY-----和-----END PUBLIC KEY-----)。 - Issuer 不匹配:NestJS 配置的
issuer必须和 Laravel 的APP_URL完全一致,包括协议(http/https)和端口。 - Token 格式问题:请求头必须是
Authorization: Bearer <token>,注意 Bearer 后有一个空格,Token 不能有多余的换行或空格。 - 公钥加载失败:如果用环境变量存储公钥,注意处理换行符转义问题,建议直接用文件读取方式加载公钥更可靠。
内容的提问来源于stack exchange,提问作者LY-92
相关产品推荐
相关产品推荐

