【发布时间】:2018-02-04 17:08:52
【问题描述】:
您好,我正在尝试编写一个小的 Rest 客户端来访问我们的云服务器(Rest Webservices)。连接由 SSL 客户端证书保护,如果我理解正确,该证书未由任何证书颁发机构签名,并且存在问题。
我知道证书可以正常工作,因为我可以在其他编程语言(例如 C#、PHP 等)中使用它,也因为我正在使用 Postman 测试 API,但是我无法真正理解如何在 Java 中执行此操作.
我尝试过使用 P12 证书文件,我也有 .key 和 .crt 文件,但仍然没有任何改变。我使用 keytool.exe 创建的 .JKS 文件,我认为它是正确的(据我所知)。
这是我正在使用的代码:
String keyPassphrase = certPwd;
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(new FileInputStream("C:\\Test\\Certificate\\idscertificate.jks"), keyPassphrase.toCharArray());
SSLContext sslContext = SSLContexts.custom()
.loadKeyMaterial(keyStore, certPwd.toCharArray())
.build();
HttpClient httpClient = HttpClients.custom().setSslcontext(sslContext).build();
HttpResponse response = httpClient.execute(new HttpGet(
"https://url_that_I_am_using_to_call_my_rest_web_service"));
但每次我启动它时都会出错:
“无法找到到所请求目标的有效认证路径”。
据我所知,这是因为我没有要指定的证书颁发机构,对吗? 谁能帮我解决这个问题?
谢谢大家的帮助
托马索
/************************ 这就是我将 P12 导入密钥库的方式。我尝试了不同的方法,我尝试的最后一个是:
首先创建了 JKS: keytool -genkey -alias myName -keystore c:\Test\Certificate\mykeystoreName.jks
然后“清理: keytool -delete -alias myName -keystore c:\Test\Certificate\myKeystoreName.jks
然后使用以下命令导入 P12 文件: keytool -v -importkeystore -srckeystore c:\Test\Certificate\idscertificate.p12 -srcstoretype PKCS12 -destkeystore c:\Test\Certificate\myKeystoreName.jks -deststoretype JKS
获得的结果: 已成功导入别名 idsclientcertificate 条目。 导入命令完成:1 个条目成功导入,0 个条目失败或取消
如果我检查密钥库的内容,我会找到我导入的证书。 尽管如此,我仍然遇到同样的错误。
感谢您的帮助。
/**************************** 2 月 8 日更新 *************** ****
好吧,我什么都试过了,但真的什么都试了,现在慢慢放弃了……情况如下:
目前使用以下代码:
SSLContextBuilder sslContext = new SSLContextBuilder();
sslContext.loadKeyMaterial(readKeyStore(), userPwd.toCharArray());
//sslContext.loadTrustMaterial(readKeyStore(), new TrustSelfSignedStrategy());
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
sslContext.build());
CloseableHttpClient client = HttpClients.custom()
.setSSLSocketFactory(sslsf)
.setSSLHostnameVerifier(new NoopHostnameVerifier())
.build();
HttpGet httpGet = new HttpGet("https://myhost.com/myrest/status");
httpGet.addHeader("Accept", "application/json;charset=UTF8");
httpGet.addHeader("Cookie", "sessionids=INeedThis");
String encoded = Base64.getEncoder().encodeToString((userName+":"+userPwd).getBytes(StandardCharsets.UTF_8));
httpGet.addHeader("Authorization", "Basic "+encoded);
httpGet.addHeader("Cache-Control", "no-cache");
HttpResponse response = client.execute(httpGet);
不幸的是仍然无法正常工作。我尝试了以下方法: - 在默认的 java cacerts 中包含我的证书, - 指定别名作为我的主机名, - 创建一个新的 jks, - 加载 p12 文件,仍然没有,同样的错误。 我得到的错误信息是:
javax.net.ssl.SSLHandshakeException:sun.security.validator.ValidatorException:PKIX 路径构建失败:sun.security.provider.certpath.SunCertPathBuilderException:无法找到请求目标的有效证书路径
如果我不使用证书,我会收到另一个错误,表明证书丢失,因此证书已加载(我也在我的 IDE 中看到它)。
如果我使用来自另一个平台(c# 或使用浏览器)的完全相同的证书文件,我会得到正确的响应和对象(因此证书/密码是有效的)
有什么方法可以停止认证路径的验证?
【问题讨论】:
-
你是如何创建你的 jks 文件的,你能描述一下使用的命令吗?
-
您客户端的 truststore 不信任 服务器的 证书。
-
抱歉我的无知,但这到底是什么意思?如果我将它们包含在 C# 代码或 PHP 或 phyton 中而不是 Java 中,那么相同的证书如何工作?谢谢
-
Java 配置证书比较冗长,这里试试这个例子,按照hc.apache.org/httpcomponents-client-ga/httpclient/examples/org/…实现它
-
@KennedyOliveira 这不是 Java 的错,而是 Apache HttpClient 的错。
标签: java rest ssl certificate client