1. 概述

本文将探讨 ALTS(应用层传输安全)在 gRPC 应用中的作用。在分布式架构中,确保认证和数据安全既困难又至关重要,而 ALTS 提供了一种简洁高效的解决方案。

ALTS 是 Google 专有的双向认证和传输加密方案,仅在 Google 云基础设施中可用。它简化了 gRPC 服务间的认证和数据加密,只需极少的代码改动即可启用,让开发者能更专注于业务逻辑开发。

2. ALTS 与 TLS 的核心差异

ALTS 与 TLS 相似,但采用了针对 Google 基础设施优化的信任模型。以下是它们的关键区别:

特性 ALTS TLS
信任模型 基于 GCP IAM 服务账户的身份验证 基于证书,需管理证书生命周期(续期/撤销)
设计复杂度 简单粗暴 复杂
使用场景 保护 Google 数据中心内的 gRPC 服务 保护 HTTPS、邮件、即时通讯、VoIP 等
消息序列化 使用 Protocol Buffers 使用 ASN.1 编码的 X.509 证书
性能 通用设计 针对 Google 数据中心的低延迟、高吞吐量通信优化

⚠️ 踩坑提示:ALTS 仅在 GCP 环境中有效,跨云部署需改用 TLS。

3. 使用 ALTS 的示例应用

ALTS 在 Google Cloud Platform (GCP) 上默认启用,通过 GCP 服务账户保护 gRPC 服务间的 RPC 调用。该功能运行在 Google 基础设施内的 Compute Engine 或 Kubernetes Engine (GKE) 上。

以医院手术室(OT)预约系统为例,包含前端和后端服务:

gcp grpc 架构图

系统包含两个运行在 GCP 上的服务:

  • 前端服务调用后端服务的 RPC 接口
  • 使用 gRPC 框架开发
  • 通过内置 ALTS 功能实现数据传输的认证与加密

首先定义 protobuf 文件 ot_booking.proto

syntax = "proto3";

package otbooking;

option java_multiple_files = true;
option java_package = "com.baeldung.grpc.alts.otbooking";

service OtBookingService {
  rpc getBookingInfo(BookingRequest) returns (BookingResponse) {}
}

message BookingRequest {
  string patientID = 1;
  string doctorID = 2;
  string description = 3;
}

message BookingResponse {
  string bookingDate = 1;
  string condition = 2;
}

核心类结构如下:

OtBooking 类图

Maven 插件编译 protobuf 后自动生成:

  • OtBookingServiceGrpc
  • OtBookingServiceImplBase
  • BookingRequest
  • BookingResponse

客户端关键实现

  • 使用 AltsChannelBuilder 创建启用 ALTS 的 ManagedChannel
  • 通过 OtBookingServiceGrpc 生成阻塞式存根调用服务端接口

服务端关键实现

  • 使用 AltsServerBuilder 启用 ALTS
  • 注册 ClientAuthInterceptor 进行客户端认证
  • 将服务注册到 io.grpc.Server 并启动

4. 基于 ALTS 的应用实现

4.1. 前置条件

ALTS 是 GCP 内置功能,需先准备云资源:

  1. 创建 IAM 服务账户

    • 前端服务账户:prod-ot-booking-client-svc
    • 后端服务账户:prod-ot-booking-svc

    GCP 服务账户配置

  2. 创建虚拟机

    • 前端虚拟机:prod-booking-client-vm 关联 prod-ot-booking-client-svc
    • 后端虚拟机:prod-booking-service-vm 关联 prod-ot-booking-svc

    虚拟机与服务账户关联

服务账户作为服务器身份标识,ALTS 使用它们进行授权和加密。

4.2. 代码实现

Maven 依赖

<dependency>
    <groupId>io.grpc</groupId>
    <artifactId>grpc-alts</artifactId>
    <version>1.63.0</version>
</dependency>

服务端实现

public class AltsOtBookingServer {
    public static void main(String[] args) throws IOException, InterruptedException {
        final String CLIENT_SERVICE_ACCOUNT = args[0];
        Server server = AltsServerBuilder.forPort(8080)
          .intercept(new ClientAuthInterceptor(CLIENT_SERVICE_ACCOUNT))
          .addService(new OtBookingService())
          .build();
        server.start();
        server.awaitTermination();
    }
}

客户端认证拦截器:

public class ClientAuthInterceptor implements ServerInterceptor {
    String clientServiceAccount = null;
    public ClientAuthInterceptor(String clientServiceAccount) {
        this.clientServiceAccount = clientServiceAccount;
    }

    @Override
    public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(ServerCall<ReqT, RespT> serverCall, Metadata metadata,
        ServerCallHandler<ReqT, RespT> serverCallHandler) {
        Status status = AuthorizationUtil.clientAuthorizationCheck(serverCall,
            Lists.newArrayList(this.clientServiceAccount));
        if (!status.isOk()) {
            serverCall.close(status, new Metadata());
        }
        return serverCallHandler.startCall(serverCall, metadata);
    }
}

客户端实现

public class AltsOtBookingClient {
    public static void main(String[] args) {
        final String SERVER_ADDRESS = args[0];
        final String SERVER_ADDRESS_SERVICE_ACCOUNT = args[1];
        ManagedChannel managedChannel = AltsChannelBuilder.forTarget(SERVER_ADDRESS)
          .addTargetServiceAccount(SERVER_ADDRESS_SERVICE_ACCOUNT)
          .build();
        OtBookingServiceGrpc.OtBookingServiceBlockingStub OTBookingServiceStub = OtBookingServiceGrpc
          .newBlockingStub(managedChannel);
        BookingResponse bookingResponse = OTBookingServiceStub.getBookingInfo(BookingRequest.newBuilder()
          .setPatientID("PT-1204")
          .setDoctorID("DC-3904")
          .build());
        managedChannel.shutdown();
    }
}

优势:同一服务账户可关联多个虚拟机,便于服务水平扩展。

4.3. 在 Google Compute Engine 上运行

部署步骤

  1. 克隆代码库:

    git clone https://github.com/eugenp/tutorials.git
    
  2. 编译项目:

    cd tutorials/grpc
    mvn clean compile
    
  3. 启动后端服务(在 prod-booking-service-vm):

    mvn exec:java -Dexec.mainClass="com.baeldung.grpc.alts.server.AltsOtBookingServer" \
    -Dexec.arguments="prod-ot-booking-client-svc@grpc-alts-demo.iam.gserviceaccount.com"
    
  4. 前端发起 RPC 调用(在 prod-booking-client-vm):

    mvn exec:java -Dexec.mainClass="com.baeldung.grpc.alts.client.AltsOtBookingClient" \
    -Dexec.arguments="10.128.0.2:8080,prod-ot-booking-svc@grpc-alts-demo.iam.gserviceaccount.com"
    

成功响应示例服务调用成功

异常场景测试

  1. 禁用客户端服务账户禁用客户端服务账户

    • RPC 调用失败,状态码 UNAVAILABLE 调用失败示例
  2. 禁用服务端服务账户禁用服务端服务账户

    • 初次调用可能成功(ALTS 缓存导致)
    • 重启服务后调用失败,状态码 UNKNOWN 服务端重启后失败

⚠️ 踩坑提示:ALTS 会缓存服务账户状态,修改配置后需重启服务生效。

5. 总结

本文深入探讨了 gRPC Java 库对 ALTS 的支持。通过极简代码即可在 gRPC 服务中启用 ALTS,并借助 GCP IAM 服务账户灵活控制服务授权。

核心优势

  • ✅ 代码改动最小化
  • ✅ 与 GCP IAM 深度集成
  • ✅ 自动处理证书管理

局限性

  • ❌ 仅限 GCP 基础设施使用
  • ❌ 跨云部署需改用 TLS(需手动配置)

本文代码已托管在 GitHub


原始标题:gRPC Authentication in Java Using Application Layer Transport Security (ALTS) | Baeldung