gpt4 book ai didi

jax-rs - 是否可以为 javax.ws.rs 重用 Java 可信证书(Resteasy 实现)?

转载 作者:行者123 更新时间:2023-12-02 06:38:16 24 4
gpt4 key购买 nike

假设我们需要信任自签名的 SSL 证书。例如,让我们使用 https://self-signed.badssl.com/ .

由于签名者不是“适当的”权威,Java 不信任它并拒绝连接到该服务器。然而,之后

$ cd $JAVA_HOME/jre/lib/security
$ keytool -import -trustcacerts -alias ... -file ... -keystore cacerts

并重新启动应用程序,以下代码有效:

new URL ("https://self-signed.badssl.com/").openConnection ().getResponseCode ()

并返回 200(OK),不抛出异常。 IE。现在可以使用基本的 Java 方式打开 HTTPS 连接,因为证书现在是受信任的。

但是,这对 javax.ws.rs Client 没有任何明显的影响(至少在 Resteasy 中实现),并且我仍然遇到异常:

javax.ws.rs.ProcessingException: Unable to invoke request
at org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient4Engine.invoke(ApacheHttpClient4Engine.java:287)
at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.invoke(ClientInvocation.java:407)
at org.jboss.resteasy.client.jaxrs.internal.ClientInvocationBuilder.method(ClientInvocationBuilder.java:273)
[...]
Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1506)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:979)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:914)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:535)
at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:403)
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:177)
at org.apache.http.impl.conn.ManagedClientConnectionImpl.open(ManagedClientConnectionImpl.java:304)
at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:611)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:446)
at org.apache.http.impl.client.AbstractHttpClient.doExecute(AbstractHttpClient.java:863)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:57)
at org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient4Engine.invoke(ApacheHttpClient4Engine.java:283)
... 90 more
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:387)
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292)
at sun.security.validator.Validator.validate(Validator.java:260)
at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324)
at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229)
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1488)
... 107 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:146)
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:131)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382)
... 113 more

Resteasy 似乎没有考虑“标准” keystore 。但我宁愿有一个中央(特定于机器)位置来存放额外的受信任 key ,而不用担心应用程序如何使用 URL.openConnection 或 javax.ws.rs。

问题是否可以使 javax.ws.rs Client 使用与“正常”Java HTTPS 连接机制相同的 keystore ?

最佳答案

创建 Client 实例时设置 SSL 上下文

ClientBuilder API有一个method允许您设置 SSLContext :

public abstract ClientBuilder sslContext(SSLContext sslContext)

Set the SSL context that will be used when creating secured transport connections to server endpoints from web targets created by the client instance that is using this SSL context. The SSL context is expected to have all the security infrastructure initialized, including the key and trust managers.

Setting a SSL context instance resets any key store or trust store values previously specified.

Parameters:

sslContext - secure socket protocol implementation which acts as a factory for secure socket factories or SSL engines. Must not be null.

Returns:

an updated client builder instance.

Throws:

NullPointerException - in case the sslContext parameter is null.

假设您已将证书添加到 cacerts 信任存储中,则可以使用默认的 SSLContext创建 Client 时实例。

Client client = ClientBuilder.newBuilder().sslContext(SSLContext.getDefault()).build();

应该足够了。然而,由于某种原因,上面的代码不能与 RESTEasy 一起使用,但可以与 Jersey 一起使用。这很可能是 RESTEasy 的错误。

标准解决方案不适用于 RESTEasy。我该怎么办?

RESTEasy documentation声明如下:

Network communication between the client and server is handled in RESTEasy, by default, by HttpClient (4.x) from the Apache HttpComponents project. [...]

RESTEasy and HttpClient make reasonable default decisions so that it is possible to use the client framework without ever referencing HttpClient, but for some applications it may be necessary to drill down into the HttpClient details. [...]

自定义HttpClient由 RESTEeasy 使用,执行以下操作:

HttpClient httpClient = HttpClientBuilder.create()
.setSslcontext(SSLContext.getDefault())
.build();

ApacheHttpClient4Engine engine = new ApacheHttpClient4Engine(httpClient);
Client client = new ResteasyClientBuilder().httpEngine(engine).build();

然后您可以执行请求:

Response response = client.target("https://self-signed.badssl.com/").request().get();
System.out.println(response.getStatus());

SSL 上下文有其他替代方案吗?

而不是使用 SSLContext创建 Client 时,您可以加载 KeyStore 。要加载 cacerts 信任存储区,您可以执行以下操作:

String filename = System.getProperty("java.home") + 
"/lib/security/cacerts".replace('/', File.separatorChar);
FileInputStream is = new FileInputStream(filename);
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
String password = "changeit";
keystore.load(is, password.toCharArray());

cacerts的默认密码是changeit

然后创建您的Client使用以下方法之一的实例:

Client client = ClientBuilder.newBuilder().trustStore(keystore).build();
Client client = ClientBuilder.newBuilder().keyStore(keystore, password).build();

问题是它不能与 RESTEasy 配合使用,但可以与 Jersey 配合使用。

<小时/>

上述解决方案针对以下 JAX-RS 客户端 API 实现进行了测试:

关于jax-rs - 是否可以为 javax.ws.rs 重用 Java 可信证书(Resteasy 实现)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38505294/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com