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

NestJS gRPC微服务RPC授权咨询:grpc.Metadata传递位置疑问

NestJS gRPC微服务RPC授权实现方案

我之前在做NestJS gRPC微服务授权的时候刚好踩过这个坑,给你详细讲下具体实现,重点把grpc.Metadata的传递位置和验证逻辑说清楚:

一、gRPC客户端附加Token(Metadata传递位置)

在NestJS里调用gRPC服务时,Metadata是作为调用方法的第二个参数传递的(如果你用的是@ClientGrpc生成的客户端),或者在ClientProxy的send方法的第三个参数里配置。

1. 使用@ClientGrpc生成的客户端

import { Injectable, OnModuleInit } from '@nestjs/common';
import { Client, ClientGrpc, Transport } from '@nestjs/microservices';
import { join } from 'path';
import { Metadata } from '@grpc/grpc-js';

// 定义gRPC服务的类型(根据你的proto文件生成)
interface YourServiceClient {
  yourRpcMethod(data: any, metadata: Metadata): Observable<any>;
}

@Injectable()
export class AppService implements OnModuleInit {
  @Client({
    transport: Transport.GRPC,
    options: {
      package: 'user_service', // 对应proto里的package
      protoPath: join(__dirname, '../proto/user.proto'), // proto文件路径
    },
  })
  private client: ClientGrpc;

  private yourService: YourServiceClient;

  onModuleInit() {
    // 获取gRPC服务实例
    this.yourService = this.client.getService<YourServiceClient>('UserService');
  }

  async fetchUser(userId: string) {
    // 1. 创建Metadata对象,添加Token
    const metadata = new Metadata();
    metadata.add('authorization', `Bearer ${process.env.USER_SERVICE_TOKEN}`);

    // 2. 调用gRPC方法时,第二个参数就是Metadata
    return this.yourService.getUser({ id: userId }, metadata).toPromise();
  }
}

2. 使用ClientProxy客户端代理

如果是用ClientProxy来调用gRPC服务,需要在send方法的第三个参数里传入metadata:

import { Injectable } from '@nestjs/common';
import { ClientProxy, Client, Transport } from '@nestjs/microservices';
import { Metadata } from '@grpc/grpc-js';
import { join } from 'path';

@Injectable()
export class AppService {
  @Client({
    transport: Transport.GRPC,
    options: {
      package: 'user_service',
      protoPath: join(__dirname, '../proto/user.proto'),
    },
  })
  private clientProxy: ClientProxy;

  async fetchUser(userId: string) {
    const metadata = new Metadata();
    metadata.add('authorization', `Bearer ${process.env.USER_SERVICE_TOKEN}`);

    // 第三个参数传入包含metadata的配置对象
    return this.clientProxy.send('getUser', { id: userId }, { metadata }).toPromise();
  }
}

二、gRPC服务端验证Token

服务端我们可以通过**自定义守卫(Guard)**来拦截gRPC请求,从Metadata中取出Token并验证。

1. 实现AuthGuard

import { Injectable, CanActivate, ExecutionContext, UnauthorizedException } from '@nestjs/common';
import { Metadata } from '@grpc/grpc-js';
import { verify } from 'jsonwebtoken';

@Injectable()
export class GrpcAuthGuard implements CanActivate {
  canActivate(context: ExecutionContext): boolean {
    // 获取gRPC上下文
    const grpcContext = context.switchToRpc().getContext();
    const metadata: Metadata = grpcContext.metadata;

    // 从Metadata中取出Authorization头
    const authHeader = metadata.get('authorization')?.[0];
    if (!authHeader) {
      throw new UnauthorizedException('Authorization token missing');
    }

    // 提取Token(去掉Bearer前缀)
    const token = authHeader.split(' ')[1];
    if (!token) {
      throw new UnauthorizedException('Invalid authorization format');
    }

    // 验证Token(这里用JWT示例,替换成你的实际验证逻辑)
    try {
      verify(token, process.env.JWT_SECRET);
      return true;
    } catch (err) {
      throw new UnauthorizedException('Invalid or expired token');
    }
  }
}

2. 在gRPC控制器中使用守卫

把守卫加到对应的gRPC方法或者整个控制器上:

import { Controller } from '@nestjs/common';
import { GrpcMethod, UseGuards } from '@nestjs/microservices';
import { GrpcAuthGuard } from './grpc-auth.guard';

@Controller()
export class UserController {
  // 给单个方法加守卫
  @UseGuards(GrpcAuthGuard)
  @GrpcMethod('UserService', 'getUser')
  async getUser(data: { id: string }) {
    // 你的业务逻辑
    return { id: data.id, name: 'John Doe' };
  }

  // 也可以给整个控制器加守卫
  // @UseGuards(GrpcAuthGuard)
  // @GrpcMethod('UserService', 'updateUser')
  // async updateUser(data: any) {
  //   // ...
  // }
}

注意事项

  • 确保客户端和服务端使用的Metadata键名一致(这里用的是authorization,你也可以自定义);
  • Token验证逻辑可以抽成公共服务,方便多个微服务复用;
  • 验证失败时要抛出合适的gRPC错误码(比如UNAUTHENTICATED),NestJS会自动转换成对应的gRPC状态码。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:53:45