[英]Java `https.proxyHost` and `https.proxyPort` succeed then fail when using google-cloud-storage
I have some code that unit tests fine using https.proxyHost
and https.proxyPort
to access Google Cloud Storage Buckets on on a corporate network which needs to go via a proxy:我有一些代码可以使用
https.proxyHost
和https.proxyPort
在需要通过代理的企业网络上访问 Google Cloud Storage Buckets 进行单元测试:
log.info("resolving service....");
Storage storage = StorageOptions.newBuilder()
.setCredentials(
ServiceAccountCredentials.fromStream(
new FileInputStream(fullPath)))
.build()
.getService();
log.info("resolving bucket....");
bucket = storage.get(bucketName);
Yet when I run it in a larger app that starts a lot of other internal services (eg, RMI) the proxy settings stop working.然而,当我在启动许多其他内部服务(例如,RMI)的较大应用程序中运行它时,代理设置停止工作。
Running as:运行为:
java -Dhttps.proxyHost=googleapis-dev.gcp.cloud.corporate -Dhttps.proxyPort=3128 ...
When it tries to resolve a bucket with the unit tested code it hangs for ages then throws:当它尝试使用单元测试代码解析存储桶时,它会挂起很长时间然后抛出:
com.google.cloud.storage.StorageException: Error getting access token for service account: oauth2.googleapis.com
at com.google.cloud.storage.spi.v1.HttpStorageRpc.translate(HttpStorageRpc.java:231) ~[htu-gcs-plugin.jar:?]
...
Caused by: java.io.IOException: Error getting access token for service account: oauth2.googleapis.com
at com.google.auth.oauth2.ServiceAccountCredentials.refreshAccessToken(ServiceAccountCredentials.java:444) ~[?:?]
at com.google.auth.oauth2.OAuth2Credentials.refresh(OAuth2Credentials.java:157) ~[?:?]
...
Caused by: java.net.UnknownHostException: oauth2.googleapis.com
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:184) ~[?:1.8.0_231]
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172) ~[?:1.8.0_231]
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) ~[?:1.8.0_231]
at java.net.Socket.connect(Socket.java:606) ~[?:1.8.0_231]
at sun.security.ssl.SSLSocketImpl.connect(SSLSocketImpl.java:666) ~[?:1.8.0_231]
I can get exactly the same error without proxy settings by adding this to the top of the main method:通过将其添加到主要方法的顶部,我可以在没有代理设置的情况下获得完全相同的错误:
String hostname = "https://oauth2.googleapis.com";
HttpURLConnection con = (HttpURLConnection) new URL(hostname).openConnection();
int code = con.getResponseCode();
System.out.println("> https://oauth2.googleapis.com returned: "+code);
Yet if the proxy settings are pass that runs fine then later throws the java.net.UnknownHostException
as through the proxy settings are cleared.然而,如果代理设置通过运行良好,那么稍后会抛出
java.net.UnknownHostException
因为代理设置被清除。
To make things a bit more complex a custom URLClassLoader
is used to load the code in question.为了使事情变得更复杂,使用自定义
URLClassLoader
来加载有问题的代码。 Yet I have made a standalone app that uses the classloader and runs the code fine with the proxy settings passed as normal.然而,我已经制作了一个独立的应用程序,它使用类加载器并在正常传递代理设置的情况下正常运行代码。
So it appears that something in the larger app is messing with the proxy system settings.因此,大型应用程序中的某些内容似乎与代理系统设置有关。 Searching the codebase I can see no trace of that.
搜索代码库我看不到任何痕迹。
I have looked at https://googleapis.github.io/google-http-java-client/http-transport.html to see if there is way to plugin in a transport that has a proxy but cannot find a clear example.我查看了https://googleapis.github.io/google-http-java-client/http-transport.html以查看是否有办法在具有代理但找不到明确示例的传输中插入。
Is there a way to coerce the use of a proxy when using google-cloud-storage?使用 google-cloud-storage 时有没有办法强制使用代理?
To explicitly force a proxy to not rely upon the standard java System
properties add the client libraries:要明确强制代理不依赖于标准 java
System
属性,请添加客户端库:
<!-- https://mvnrepository.com/artifact/com.google.http-client/google-http-client-apache-v2 -->
<dependency>
<groupId>com.google.http-client</groupId>
<artifactId>google-http-client-apache-v2</artifactId>
<version>1.37.0</version>
</dependency>
Then you can create a custom HttpTransportFactory
with something like:然后,您可以使用以下内容创建自定义
HttpTransportFactory
:
public class ProxyAwareTransportFactory implements HttpTransportFactory {
public static SSLContext trustAllSSLContext() throws Exception {
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
sslContext.init(null, null, null);
return sslContext;
}
@Override
public HttpTransport create() {
InetSocketAddress socketAddress = new InetSocketAddress(this.host,this.port);
Proxy proxy = new Proxy(Proxy.Type.HTTP, socketAddress);
try {
return new NetHttpTransport.Builder()
.setProxy(proxy)
.setConnectionFactory(new DefaultConnectionFactory(proxy) )
.setSslSocketFactory(trustAllSSLContext().getSocketFactory())
.setHostnameVerifier(new DefaultHostnameVerifier())
.build();
} catch (Exception e) {
final String msg = "Could not build HttpTransport due to; " + e.getMessage();
log.error(msg, e);
throw new RuntimeException(e);
}
}
}
You can then use it using something like:然后,您可以使用以下方法使用它:
StorageOptions.Builder builder = StorageOptions.newBuilder();
if( useProxy ) {
HttpTransportFactory httpTransportFactory = new ProxyAwareTransportFactory(proxyHost, proxyPort);
HttpTransportOptions options = HttpTransportOptions.newBuilder().setHttpTransportFactory(httpTransportFactory).build();
builder.setTransportOptions(options);
}
Storage storage = builder
.setCredentials(
ServiceAccountCredentials.fromStream(
new FileInputStream(fullPath)))
.build()
.getService();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.