GCP Java SDK调用出现407代理认证错误求助
GCP存储桶Java SDK代理认证407错误排查与解决
问题概述
开发基于Java SDK的GCP存储桶应用,通过Access Credential JSON文件完成请求认证,但调用GCP接口时抛出代理认证错误:com.google.cloud.storage.StorageException: Unable to tunnel through proxy. Proxy returns "HTTP/1.1 407 Proxy Authentication Required"
异常堆栈
com.google.cloud.storage.StorageException: Unable to tunnel through proxy. Proxy returns "HTTP/1.1 407 Proxy Authentication Required" at com.google.cloud.storage.StorageException.translate(StorageException.java:170) at com.google.cloud.storage.spi.v1.HttpStorageRpc.translate(HttpStorageRpc.java:313) at com.google.cloud.storage.spi.v1.HttpStorageRpc.get(HttpStorageRpc.java:504) at com.google.cloud.storage.StorageImpl.lambda$internalBucketGet$65(StorageImpl.java:1589) at com.google.api.gax.retrying.DirectRetryingExecutor.submit(DirectRetryingExecutor.java:103) at com.google.cloud.RetryHelper.run(RetryHelper.java:76) at com.google.cloud.RetryHelper.runWithRetries(RetryHelper.java:50) at com.google.cloud.storage.Retrying.run(Retrying.java:65) at com.google.cloud.storage.StorageImpl.run(StorageImpl.java:1514) at com.google.cloud.storage.StorageImpl.internalBucketGet(StorageImpl.java:1587) at com.google.cloud.storage.StorageImpl.get(StorageImpl.java:316) at com.application.DataHandler.getData(DataHandler.java:310)
当前代码实现
import java.io.InputStream; import java.net.Authenticator; import java.net.PasswordAuthentication; import java.nio.channels.Channels; import org.apache.http.HttpHost; import org.apache.http.auth.AuthScope; import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.client.CredentialsProvider; import org.apache.http.client.HttpClient; import org.apache.http.conn.routing.HttpRoutePlanner; import org.apache.http.impl.client.BasicCredentialsProvider; import org.apache.http.impl.client.ProxyAuthenticationStrategy; import org.apache.http.impl.conn.DefaultProxyRoutePlanner; import com.google.api.client.http.HttpTransport; import com.google.api.client.http.apache.v2.ApacheHttpTransport; import com.google.auth.http.HttpTransportFactory; import com.google.auth.oauth2.GoogleCredentials; import com.google.cloud.storage.Bucket; import com.google.cloud.storage.Storage; private static void queryBucket(InputStream accessCredentialJson) { GoogleCredentials googleCredentials = GoogleCredentials.fromStream(accessCredentialJson, getHttpTransportFactory()); Storage storage = StorageOptions.newBuilder().setCredentials(googleCredentials).build().getService(); Bucket gcpBucketObj = storage.get("gcpBucket"); // --> 抛出407代理认证错误 } public HttpTransportFactory getHttpTransportFactory() { HttpHost proxyHostDetails = new HttpHost(PROXY_HOST, PROXY_PORT); HttpRoutePlanner httpRoutePlanner = new DefaultProxyRoutePlanner(proxyHostDetails); CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); credentialsProvider.setCredentials( new AuthScope(proxyHostDetails.getHostName(), proxyHostDetails.getPort()), new UsernamePasswordCredentials(PROXY_USERNAME, PROXY_PASSWORD) ); HttpClient httpClient = ApacheHttpTransport.newDefaultHttpClientBuilder() .setRoutePlanner(httpRoutePlanner) .setProxyAuthenticationStrategy(ProxyAuthenticationStrategy.INSTANCE) .setDefaultCredentialsProvider(credentialsProvider) .build(); final HttpTransport httpTransport = new ApacheHttpTransport(httpClient); return new HttpTransportFactory() { @Override public HttpTransport create() { return httpTransport; } }; }
已验证与尝试的方案
- 代理凭证有效:使用
curl携带代理凭证可正常连接谷歌服务器,仅GCP SDK请求报错 - 尝试设置系统代理属性:
无效果System.setProperty("https.proxyHost", PROXY_HOST); System.setProperty("https.proxyPort", PROXY_PORT);
使用的依赖版本
google-cloud-storage-2.29.1.jar google-cloud-core-2.21.0.jar google-cloud-core-http-2.21.0.jar google-auth-library-oauth2-http-1.19.0.jar google-auth-library-credentials-1.19.0.jar gax-2.31.0.jar guava-30.1-jre.jar gson-2.10.jar threetenbp-1.6.8.jar api-common-2.14.1.jar google-http-client-gson-1.42.3.jar google-http-client-1.42.3.jar google-http-client-apache-v2-1.43.3.jar google-http-client-appengine-1.43.3.jar google-http-client-jackson2-1.42.3.jar google-api-client-1.34.0.jar opencensus-api-0.31.1.jar opencensus-contrib-http-util-0.31.1.jar google-api-services-storage-v1-rev20231028-2.0.0.jar gax-httpjson-2.31.0.jar httpclient-4.5.14.jar
问题根源与解决建议
问题根源
当前仅为GoogleCredentials配置了自定义HttpTransportFactory,但GCP Storage SDK的底层请求(如Bucket查询)并未复用这个Transport,而是使用了StorageOptions默认初始化的HTTP客户端,导致代理配置未生效。
解决方案
1. 为StorageOptions直接配置自定义HttpTransport
修改queryBucket方法,将自定义Transport同时配置到StorageOptions中:
private static void queryBucket(InputStream accessCredentialJson) { HttpTransportFactory transportFactory = getHttpTransportFactory(); GoogleCredentials googleCredentials = GoogleCredentials.fromStream(accessCredentialJson, transportFactory); // 关键:为Storage SDK设置自定义HttpTransport Storage storage = StorageOptions.newBuilder() .setCredentials(googleCredentials) .setTransport(transportFactory.create()) .build() .getService(); Bucket gcpBucketObj = storage.get("gcpBucket"); }
2. 调整代理AuthScope范围
若代理认证存在Scope匹配问题,将AuthScope改为AuthScope.ANY以覆盖所有场景:
credentialsProvider.setCredentials( AuthScope.ANY, new UsernamePasswordCredentials(PROXY_USERNAME, PROXY_PASSWORD) );
3. 统一依赖版本
当前google-http-client-apache-v2(1.43.3)与google-http-client(1.42.3)版本不一致,可能导致HTTP客户端初始化异常,建议统一为相同版本(如1.43.3)。
4. 检查代理认证类型
若代理使用NTLM认证,需添加NTLM支持:
import org.apache.http.impl.auth.NTLMSchemeFactory; // 在构建HttpClient时添加NTLM认证支持 HttpClient httpClient = ApacheHttpTransport.newDefaultHttpClientBuilder() .setRoutePlanner(httpRoutePlanner) .setProxyAuthenticationStrategy(ProxyAuthenticationStrategy.INSTANCE) .setDefaultCredentialsProvider(credentialsProvider) .addAuthScheme("ntlm", new NTLMSchemeFactory()) .build();
内容的提问来源于stack exchange,提问作者Kumaran
相关产品推荐
相关产品推荐

