设置特定端点时Google Pub/Sub API遇OAuth2认证失败求助
问题原因
当你指定区域Pub/Sub端点(如us-east1-pubsub.googleapis.com:443)时,默认生成的OAuth 2令牌的**受众(Audience)**是全局端点pubsub.googleapis.com,与区域端点不匹配,导致认证被拒绝。而连接全局端点时,令牌受众正好匹配,所以认证正常。
解决方案
你需要在创建GoogleCredentials时,手动指定令牌的受众为区域端点的主机名(不带端口),确保认证令牌与目标端点匹配。
代码修改示例
调整Credentials的创建逻辑,添加受众设置:
final String PROJECT_ID = "..."; final String TOPIC_NAME = "test-20221025-153636-7318"; final String ENDPOINT = "us-east1-pubsub.googleapis.com:443"; // 提取端点主机名用于设置受众 final String AUDIENCE = "https://" + ENDPOINT.split(":")[0]; final String CREDENTIALS = "{\n" // + " \"type\": \"service_account\",\n" // + " \"project_id\": \"" + PROJECT_ID + "\",\n" // + " \"private_key_id\": \"...\",\n" // + " \"private_key\": ...\"" // + " \"client_email\": \"...\",\n" // + " \"client_id\": \"...\",\n" // + ... + "}\n"; TopicName googleTopicName = ProjectTopicName.of(PROJECT_ID, TOPIC_NAME); // 修改Credentials创建逻辑,添加受众和权限范围 GoogleCredentials rawCredentials = GoogleCredentials.fromStream(new ByteArrayInputStream(CREDENTIALS.getBytes())); // 添加Pub/Sub所需的权限范围 GoogleCredentials scopedCredentials = rawCredentials.createScoped(List.of("https://www.googleapis.com/auth/pubsub")); // 设置令牌受众为区域端点 GoogleCredentials credentialsWithAudience = scopedCredentials.withAudience(AUDIENCE); CredentialsProvider credentialsProvider = FixedCredentialsProvider.create(credentialsWithAudience); // 创建publisher的逻辑不变 Publisher.Builder publisherBuilder = Publisher.newBuilder(googleTopicName); publisherBuilder.setCredentialsProvider(credentialsProvider); publisherBuilder.setEndpoint(ENDPOINT); publisherBuilder.setEnableMessageOrdering(true); Publisher publisher = publisherBuilder.build(); // 发布消息逻辑不变 PubsubMessage message = PubsubMessage.newBuilder().setMessageId("id") .setData(ByteString.copyFrom("data", Charset.defaultCharset())) .setOrderingKey("foo").build(); ApiFuture<String> future = publisher.publish(message); System.out.println("Publishing message returned: " + future.get());
额外检查点
- 确认你的服务账号已被授予
roles/pubsub.publisher角色(全局端点正常的话此条件大概率满足)。 - 如果使用的是较旧版本的Google Cloud Pub/Sub库,
withAudience方法可能不可用,此时可以强制转换为ServiceAccountCredentials并通过Builder设置:
ServiceAccountCredentials serviceAccountCreds = (ServiceAccountCredentials) rawCredentials; ServiceAccountCredentials updatedCreds = serviceAccountCreds.toBuilder() .setAudience(AUDIENCE) .build() .createScoped(List.of("https://www.googleapis.com/auth/pubsub")); CredentialsProvider credentialsProvider = FixedCredentialsProvider.create(updatedCreds);
内容的提问来源于stack exchange,提问作者Gray
相关产品推荐
相关产品推荐

