简体   繁体   English

Java `https.proxyHost` 和 `https.proxyPort` 在使用 google-cloud-storage 时成功然后失败

[英]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.proxyHosthttps.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.

相关问题 Java https代理(使用https.proxyPort和https.proxyHost) - Java https proxy (using https.proxyPort and https.proxyHost) 如何为单个 HttpsURLConnections 设置 https.proxyHost 和 https.proxyPort? - How can I set https.proxyHost and https.proxyPort for individual HttpsURLConnections? 如何删除 JVM 属性“https.proxyHost”? - How to remove JVM property “https.proxyHost”? Java/Spring 使用 Google Cloud firebase-admin 与 google-cloud-storage 冲突 - Java/Spring using Google Cloud firebase-admin conflicts with google-cloud-storage Java Web Start和proxyPort / proxyHost - Java Web Start & proxyPort/proxyHost 为什么运行我的 Java 应用程序时 proxyHost/proxyPort 不起作用? - Why don't proxyHost/proxyPort work when running my Java application? Java系统属性重置http.proxyHost和ProxyPort - Java System Properties reset http.proxyHost and ProxyPort 通过appengine上传到google-cloud-storage时如何向文件添加元数据 - how to add metadata to file when uploading to google-cloud-storage via appengine IntelliJ无法找到google-cloud-storage类 - IntelliJ can't find google-cloud-storage classes 如何在Apache Beam项目中直接使用google-cloud-storage - How to use google-cloud-storage directly in a Apache Beam project
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM