Java HttpClient 与 TLS/SSLContext 通过代理
Java HttpClient with TLS/SSLContext through proxy
我想对使用 TLS 进行身份验证的服务器进行 HTTP 调用。此外,服务器需要将我的 IP 列入白名单,因此对于 AWS Lambda,我需要使用代理。我想要实现的是通过代理进行 TLS 的 HTTP POST 请求。
为了实现 TLS 协议,我使用 KeyStore
加载证书和私钥。
在没有代理的情况下进行调用(从本地白名单 IP)是有效的,所以我假设 keyStore
配置正确。
这是我构建 httpClient
的方式(它是 java.net.http.HttpClient
):
var keyManagerFactory = KeyManagerFactory.getInstance("PKIX");
keyManagerFactory.init(keyStore, null);
var trustManagerFactory = TrustManagerFactory.getInstance("PKIX");
trustManagerFactory.init(keyStore, null);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);
URI proxyUri = config.getProxyUri(); // this is injected object with preloaded config parameters
HttpClient httpClient = HttpClient.newBuilder()
.sslContext(sslContext)
.proxy(
ProxySelector.of(
InetSocketAddress.createUnresolved(proxyUri.getHost(), proxyUri.getPort())))
.build();
现在提出请求:
String body = createRequestBody(); // creates string with JSON
HttpRequest request = HttpRequest.newBuilder()
.uri(config.getServiceUri()) // same config as in example above
.header("Content-Type", "application/json")
.POST(BodyPublishers.ofString(body))
.build();
HttpResponse<String> response = httpClient.send(request, BodyHandlers.ofString());
调用.send(...)
导致
java.io.IOException: Tunnel failed, got: 403
# java.net.http/jdk.internal.net.http.HttpClientImpl.send(Unknown Source)
# java.net.http/jdk.internal.net.http.HttpClientFacade.send(Unknown Source)
# (method we are in above example)
Proxy 不需要任何身份验证,在其他 AWS Lambda 中,我已经看到此代理仅使用 .proxy(...)
方法与构建器一起工作,就像上面的示例一样。所以唯一不同的是这个 .sslContext(...)
.
我需要更多 sslContext
配置吗?我一直在通过代理搜索 TLS 的一些示例,但我没有设法找到任何东西。
HttpClient.Builder Docs 也没有说明使用 sslContext 的代理。
感谢帮助!
正如丹尼尔在评论中所写
It would seem that you have insufficient permission to access the service you're trying to use
原来是代理配置阻止了到该特定主机和端口的流量。
上面的代码没有任何问题。更改代理设置后,它会按预期工作。
感谢帮助!
我想对使用 TLS 进行身份验证的服务器进行 HTTP 调用。此外,服务器需要将我的 IP 列入白名单,因此对于 AWS Lambda,我需要使用代理。我想要实现的是通过代理进行 TLS 的 HTTP POST 请求。
为了实现 TLS 协议,我使用 KeyStore
加载证书和私钥。
在没有代理的情况下进行调用(从本地白名单 IP)是有效的,所以我假设 keyStore
配置正确。
这是我构建 httpClient
的方式(它是 java.net.http.HttpClient
):
var keyManagerFactory = KeyManagerFactory.getInstance("PKIX");
keyManagerFactory.init(keyStore, null);
var trustManagerFactory = TrustManagerFactory.getInstance("PKIX");
trustManagerFactory.init(keyStore, null);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);
URI proxyUri = config.getProxyUri(); // this is injected object with preloaded config parameters
HttpClient httpClient = HttpClient.newBuilder()
.sslContext(sslContext)
.proxy(
ProxySelector.of(
InetSocketAddress.createUnresolved(proxyUri.getHost(), proxyUri.getPort())))
.build();
现在提出请求:
String body = createRequestBody(); // creates string with JSON
HttpRequest request = HttpRequest.newBuilder()
.uri(config.getServiceUri()) // same config as in example above
.header("Content-Type", "application/json")
.POST(BodyPublishers.ofString(body))
.build();
HttpResponse<String> response = httpClient.send(request, BodyHandlers.ofString());
调用.send(...)
导致
java.io.IOException: Tunnel failed, got: 403
# java.net.http/jdk.internal.net.http.HttpClientImpl.send(Unknown Source)
# java.net.http/jdk.internal.net.http.HttpClientFacade.send(Unknown Source)
# (method we are in above example)
Proxy 不需要任何身份验证,在其他 AWS Lambda 中,我已经看到此代理仅使用 .proxy(...)
方法与构建器一起工作,就像上面的示例一样。所以唯一不同的是这个 .sslContext(...)
.
我需要更多 sslContext
配置吗?我一直在通过代理搜索 TLS 的一些示例,但我没有设法找到任何东西。
HttpClient.Builder Docs 也没有说明使用 sslContext 的代理。
感谢帮助!
正如丹尼尔在评论中所写
It would seem that you have insufficient permission to access the service you're trying to use
原来是代理配置阻止了到该特定主机和端口的流量。 上面的代码没有任何问题。更改代理设置后,它会按预期工作。
感谢帮助!