Muh*_*edy 40 java web-services certificate ssl-certificate
我正在调用以下客户端的一些HTTPS Web服务:
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.HttpURLConnection;
import java.net.URL;
import javax.net.ssl.HttpsURLConnection;
/**
* Handles http and https connections. It sends XML request over http (or https)
* to SOAP web service and receive the XML reply.
*
* @author mhewedy
* @date 30.10.2010
*/
public class HttpWSXmlClient
{
private final String ws_url;
private byte[] requestData;
public HttpWSXmlClient(String wsUrl)
{
this.ws_url = wsUrl;
}
public void readRequest(String xmlRequestFilePath)
{
try
{
InputStream istream = new FileInputStream(xmlRequestFilePath);
byte[] data = stream2Bytes(istream);
istream.close();
this.requestData = data;
} catch (Exception e)
{
throw new RuntimeException(e.getMessage());
}
}
/**
*
* @param ps
* PrintStream object to send the debugging info to.
* @return
* @throws IOException
*/
public byte[] sendAndRecieve(PrintStream ps) throws IOException
{
if (requestData == null)
throw new RuntimeException(
"the request data didn't initialized yet.");
if (ps != null)
ps.println("Request:\n" + new String(requestData));
URL url = new URL(ws_url);
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
// or HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestProperty("content-type", "text/xml");
connection.connect();
OutputStream os = connection.getOutputStream();
os.write(requestData);
InputStream is = connection.getInputStream();
byte[] rply = stream2Bytes(is);
if (ps != null)
ps.println("Response:\n" + new String(rply));
os.close();
is.close();
connection.disconnect();
return rply;
}
public byte[] sendAndRecieve() throws IOException
{
return sendAndRecieve(null);
}
private byte[] stream2Bytes(InputStream istream) throws IOException
{
ByteArrayOutputStream outstream = new ByteArrayOutputStream();
int c;
while ((c = istream.read()) != -1)
{
if (c != 0x0A && c != 0x0D) // prevent new line character from being
// written
{
if (c == 0x09)
c = 0x20; // prevent tab character from being written,
// instead write single space char
outstream.write(c);
}
}
byte[] ret = outstream.toByteArray();
outstream.close();
return ret;
}
}
Run Code Online (Sandbox Code Playgroud)
测试:
public class Test
{
private static final String WS_URL = "https://some_server/path/to/ws";
public static void main(String[] args) throws Exception
{
HttpWSXmlClient client = new HttpWSXmlClient(WS_URL);
client.readRequest("request.xml");
client.sendAndRecieve(System.out);
}
}
Run Code Online (Sandbox Code Playgroud)
我得到以下输出:
Exception in thread "Main Thread" 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 com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1591)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:187)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:181)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1035)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:124)
at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:516)
at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:454)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:884)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1096)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1123)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1107)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:415)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:166)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:133)
at com.se.swstest.HttpWSXmlClient.sendAndRecieve(HttpWSXmlClient.java:63)
at com.se.swstest.Test.main(Test.java:11)
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:285)
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:191)
at sun.security.validator.Validator.validate(Validator.java:218)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:126)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:209)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:249)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1014)
... 12 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:174)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:238)
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:280)
... 18 more
Run Code Online (Sandbox Code Playgroud)
我是否需要将任何证书放在jdk/jre/lib/security中?另外,我有一个xxx_IE.crt和xxx_FX.crt(分别用于Firefox和IE,它们不适用于上面的Java客户端,所以我需要Java客户端的特定证书吗?
谢谢.
小智 23
您需要设置证书才能点击此网址.使用下面的代码来设置密钥库:
System.setProperty("javax.net.ssl.trustStore","clientTrustStore.key");
System.setProperty("javax.net.ssl.trustStorePassword","qwerty");
Run Code Online (Sandbox Code Playgroud)
ent*_*erd 16
Java 8解决方案:我刚遇到这个问题并通过将远程站点的证书添加到我的Java密钥库来解决它.我的解决方案基于myshittycode博客的解决方案,该解决方案基于mykong博客中的先前解决方案.这些博客文章解决方案归结为下载名为InstallCert的程序,该程序是一个Java类,您可以从命令行运行以获取证书.然后,继续在Java的密钥库中安装证书.
该InstallCert自述工作完美的我.您只需运行以下命令:
javac InstallCert.javajava InstallCert [host]:[port](在运行命令时输入要在列表中添加的证书的给定列表编号 - 可能只是1)keytool -exportcert -alias [host]-1 -keystore jssecacerts -storepass changeit -file [host].cersudo keytool -importcert -alias [host] -keystore [path to system keystore] -storepass changeit -file [host].cer如果需要,请参阅引用的README文件以获取示例.
小智 6
如果服务器仅发送其叶证书而不将构建信任链所需的所有链证书发送到根 CA,也可能会发生此错误。不幸的是,这是服务器的常见错误配置。
如果大多数浏览器已经从之前的访问中知道了丢失的链证书,或者如果叶证书包含权威信息访问 (AIA)中 CA 颁发者的 URL,则可能会下载丢失的证书,大多数浏览器都会解决此问题。但这种行为通常仅限于桌面浏览器,其他工具只会失败,因为它们无法构建信任链。
com.sun.security.enableAIAcaIssuers您可以通过设置使 JRE 自动下载中间证书true
要验证服务器是否正在发送所有链证书,您可以在以下 SSL 证书验证工具中输入主机https://www.digicert.com/help/
我已经碰到了几次这是因为证书链不完整.如果您使用的是标准Java信任库,则可能没有完成证书链所需的证书,而证书链是验证要连接的SSL站点的证书所必需的.
我用一些DigiCert证书遇到了这个问题,不得不自己手动添加中间证书.
这是我用于将站点的公共证书安装到系统密钥库中以供使用的解决方案。
使用以下命令下载证书:
Unix、Linux、Mac
openssl s_client -connect [host]:[port|443] < /dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > [host].crt
Run Code Online (Sandbox Code Playgroud)
视窗
openssl s_client -connect [host]:[port|443] < NUL | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > [host].crt
Run Code Online (Sandbox Code Playgroud)
这将创建一个可用于导入密钥库的 crt。
使用以下命令安装新证书:
keytool -import -alias "[host]" -keystore [path to keystore] -file [host].crt
Run Code Online (Sandbox Code Playgroud)
这将允许您从导致异常的站点导入新证书。
小智 5
我在尝试从 Java 代码发起 SOAP 请求时遇到了这个问题。对我有用的是:
通过点击浏览器中的 URL 获取服务器证书:http : //docs.bvstools.com/home/ssl-documentation/exporting-certificate-authorities-cas-from-a-website 此链接包含获取服务器的所有步骤证书
复制链接中的文本,以防此链接失效:
修复此错误所需要做的就是将服务器证书添加到受信任的 Java 密钥库。首先您需要从服务器下载文档。
一旦您的硬盘驱动器中有证书,您就可以将其导入 Java 信任存储。要将证书导入受信任的 Java 密钥库,您可以使用 java 'keytool' 工具。在命令提示符下导航到 JRE bin 文件夹,在我的情况下,路径是: C:\Program Files\Java\jdk1.7.0_75\jre\bin 。然后使用如下keytool命令将证书导入JRE。
keytool -import -alias _alias_name_ -keystore ..\lib\security\cacerts -file _path_to_cer_file
它会要求输入密码。默认密码是“changeit”。如果密码不同,您可能无法导入证书。
| 归档时间: |
|
| 查看次数: |
86907 次 |
| 最近记录: |