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

如何在Java中无需JSON文件通过IAM认证连接GCP Pub/Sub服务

无JSON密钥文件连接GCP Pub/Sub的IAM认证实现

本地Java环境测试

本地场景下,可通过GCP应用默认凭据(ADC)的非密钥文件方式完成认证,无需手动放置.json密钥文件,以下是两种可行方案:

方案1:借助gcloud CLI获取临时本地凭据

  1. 安装并初始化gcloud CLI,完成账号登录:
    gcloud auth login
    
  2. 设置默认GCP项目:
    gcloud config set project YOUR_PROJECT_ID
    
  3. Java代码中直接调用默认凭据方法,ADC会自动读取gcloud登录后的本地缓存凭据,示例代码:
    import com.google.cloud.pubsub.v1.Publisher;
    import com.google.cloud.pubsub.v1.Subscriber;
    import com.google.pubsub.v1.ProjectTopicName;
    import com.google.pubsub.v1.ProjectSubscriptionName;
    import com.google.auth.oauth2.GoogleCredentials;
    import com.google.api.gax.core.FixedCredentialsProvider;
    
    public class PubSubLocalAuthDemo {
        public static void main(String[] args) throws Exception {
            // 自动获取本地缓存的凭据(来自gcloud登录,无json文件)
            GoogleCredentials credentials = GoogleCredentials.getApplicationDefault();
            // 绑定Pub/Sub所需权限范围
            credentials = credentials.createScoped("https://www.googleapis.com/auth/pubsub");
    
            // 初始化Pub/Sub Publisher
            ProjectTopicName topicName = ProjectTopicName.of("YOUR_PROJECT_ID", "YOUR_TOPIC_ID");
            Publisher publisher = Publisher.newBuilder(topicName)
                    .setCredentialsProvider(FixedCredentialsProvider.create(credentials))
                    .build();
    
            // 初始化Pub/Sub Subscriber
            ProjectSubscriptionName subscriptionName = ProjectSubscriptionName.of("YOUR_PROJECT_ID", "YOUR_SUBSCRIPTION_ID");
            Subscriber subscriber = Subscriber.newBuilder(subscriptionName, (message, consumer) -> {
                System.out.println("收到消息:" + message.getData().toStringUtf8());
                consumer.ack();
            })
                    .setCredentialsProvider(FixedCredentialsProvider.create(credentials))
                    .build();
    
            subscriber.startAsync().awaitRunning();
            Thread.sleep(60000); // 保持运行60秒,按需调整
            subscriber.stopAsync().awaitTerminated();
            publisher.shutdown();
        }
    }
    

方案2:服务账号模拟(Impersonation)

若需使用特定服务账号权限但不想下载其密钥文件,可通过当前用户账号模拟目标服务账号:

  1. 确保当前用户账号拥有roles/iam.serviceAccountTokenCreator权限(允许模拟目标服务账号)
  2. Java代码实现模拟逻辑:
    import com.google.auth.oauth2.GoogleCredentials;
    import com.google.auth.oauth2.ImpersonatedCredentials;
    import com.google.cloud.pubsub.v1.Publisher;
    import com.google.pubsub.v1.ProjectTopicName;
    import com.google.api.gax.core.FixedCredentialsProvider;
    
    public class PubSubImpersonationDemo {
        public static void main(String[] args) throws Exception {
            // 获取当前用户的本地凭据(来自gcloud登录)
            GoogleCredentials sourceCreds = GoogleCredentials.getApplicationDefault()
                    .createScoped("https://www.googleapis.com/auth/cloud-platform");
    
            // 模拟目标服务账号
            ImpersonatedCredentials targetCreds = ImpersonatedCredentials.newBuilder()
                    .setSourceCredentials(sourceCreds)
                    .setTargetPrincipal("TARGET_SERVICE_ACCOUNT@YOUR_PROJECT_ID.iam.gserviceaccount.com")
                    .setTargetScopes(new String[]{"https://www.googleapis.com/auth/pubsub"})
                    .setLifetime(3600) // 凭据有效期(秒)
                    .build();
    
            // 初始化Publisher(后续逻辑同方案1)
            ProjectTopicName topicName = ProjectTopicName.of("YOUR_PROJECT_ID", "YOUR_TOPIC_ID");
            Publisher publisher = Publisher.newBuilder(topicName)
                    .setCredentialsProvider(FixedCredentialsProvider.create(targetCreds))
                    .build();
    
            // 发布消息逻辑
            // ...
    
            publisher.shutdown();
        }
    }
    

GCP容器环境部署(GKE/Cloud Run)

容器环境下直接使用工作负载身份(Workload Identity),完全无需密钥文件,通过IAM绑定实现权限映射:

步骤1:配置工作负载身份(以GKE为例)

  1. 创建或选择一个GCP服务账号,为其分配Pub/Sub相关权限(如roles/pubsub.publisher、roles/pubsub.subscriber)
  2. 创建Kubernetes服务账号(KSA),并绑定到目标GCP服务账号(GSA):
    gcloud iam service-accounts add-iam-policy-binding GSA_NAME@PROJECT_ID.iam.gserviceaccount.com \
        --member="serviceAccount:PROJECT_ID.svc.id.goog[NAMESPACE/KSA_NAME]" \
        --role="roles/iam.workloadIdentityUser"
    
  3. 在K8s部署文件中指定Pod使用该KSA:
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: pubsub-app
    spec:
      template:
        spec:
          serviceAccountName: KSA_NAME
          containers:
          - name: pubsub-container
            image: YOUR_IMAGE_URL
    

步骤2:容器内Java代码

容器内无需特殊配置,直接调用默认凭据方法即可,ADC会自动通过工作负载身份获取凭据:

import com.google.cloud.pubsub.v1.Subscriber;
import com.google.pubsub.v1.ProjectSubscriptionName;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.api.gax.core.FixedCredentialsProvider;

public class PubSubContainerDemo {
    public static void main(String[] args) throws Exception {
        // 自动获取工作负载身份凭据
        GoogleCredentials credentials = GoogleCredentials.getApplicationDefault()
                .createScoped("https://www.googleapis.com/auth/pubsub");

        ProjectSubscriptionName subscriptionName = ProjectSubscriptionName.of("YOUR_PROJECT_ID", "YOUR_SUBSCRIPTION_ID");
        Subscriber subscriber = Subscriber.newBuilder(subscriptionName, (message, consumer) -> {
            System.out.println("容器内收到消息:" + message.getData().toStringUtf8());
            consumer.ack();
        })
                .setCredentialsProvider(FixedCredentialsProvider.create(credentials))
                .build();

        subscriber.startAsync().awaitRunning();
        Thread.sleep(60000);
        subscriber.stopAsync().awaitTerminated();
    }
}

若部署到Cloud Run,只需在部署时指定服务账号:

gcloud run deploy YOUR_SERVICE_NAME \
    --image YOUR_IMAGE_URL \
    --service-account GSA_NAME@PROJECT_ID.iam.gserviceaccount.com \
    --region YOUR_REGION

代码逻辑与上述容器示例一致。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 02:50:35