Не удалось создать путь PKIX: не удалось найти допустимый путь сертификации для запрошенной цели
Я вызываю некоторые веб-службы HTTPS, которые следующий Клиент:
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;
}
}
Тест:
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);
}
}
Я получил следующий вывод:
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
Нужен ли мне какой-либо сертификат для jdk/jre/lib/security???
Кроме того, у меня есть xxx_IE.crt и xxx_FX.crt(для Firefox и IE соответственно, и они не работают для вышеупомянутого Java-клиента, поэтому мне нужен специальный сертификат для клиента Java?
Спасибо.
Ответы
Ответ 1
Вам нужно установить сертификат, чтобы нажать этот URL-адрес. используйте ниже код для установки хранилища ключей:
System.setProperty("javax.net.ssl.trustStore","clientTrustStore.key");
System.setProperty("javax.net.ssl.trustStorePassword","qwerty");
Ответ 2
Java 8 Решение: у меня была эта проблема и она была решена, добавив сертификат удаленного сайта в хранилище ключей Java. Мое решение было основано на решении в блоге myshittycode, который был основан на предыдущее решение в блоге mykong. Эти статьи в блогах сводятся к загрузке программы под названием InstallCert, которая является классом Java, которую вы можете запустить из командной строки для получения сертификата, Затем переходите к установке сертификата в хранилище ключей Java.
InstallCert Readme отлично работал у меня. Вам просто нужно запустить следующие команды:
-
javac InstallCert.java
-
java InstallCert [host]:[port]
(Введите указанный номер списка сертификата, который вы хотите добавить в список, когда вы запустите команду - скорее всего, 1)
-
keytool -exportcert -alias [host]-1 -keystore jssecacerts -storepass changeit -file [host].cer
-
sudo keytool -importcert -alias [host] -keystore [path to system keystore] -storepass changeit -file [host].cer
При необходимости обратитесь к файлу README, указанному в качестве ссылки.
Ответ 3
Я столкнулся с этим несколько раз, и это было связано с тем, что цепочка сертификатов была неполной. Если вы используете стандартное хранилище доверия Java, у него может не быть сертификата, который необходим для завершения цепочки сертификатов, которая требуется для проверки сертификата подключенного сайта SSL.
Я столкнулся с этой проблемой с некоторыми сертификатами DigiCert и мне пришлось вручную добавить сертификат посредника.
Ответ 4
Вот решение, которое я использовал для установки публичного сертификата сайта в хранилище ключей системы для использования.
Загрузить сертификат со следующей командой:
unix, linux, mac
openssl s_client -connect [host]:[port|443] < /dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > [host].crt
окна
openssl s_client -connect [host]:[port|443] < NUL | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > [host].crt
Это создаст crt, который можно использовать для импорта в хранилище ключей.
Установите новый сертификат с помощью команды:
keytool -import -alias "[host]" -keystore [path to keystore] -file [host].crt
Это позволит вам импортировать новый сертификат с сайта, вызывающего исключение.
Ответ 5
Я ударил это, когда пытался запустить SOAP-запрос из Java-кода. Что для меня работало:
Копирование текста по ссылке, если эта ссылка затухает:
Все, что вам нужно сделать, чтобы исправить эту ошибку, - это добавить сертификат сервера к вашему надежному хранилищу ключей Java. Сначала вам нужно скачать документ с сервера.
После того, как у вас есть сертификат на жестком диске, вы можете импортировать его на хранилище доверия Java. Чтобы импортировать сертификат в доверенную Java key store, вы можете использовать инструмент java 'keytool'. В командной строке перейдите в папку JRE bin, в моем случае путь: C:\Program Файлы \Java\jdk1.7.0_75\jre\bin. Затем используйте команду keytool следующим образом для импорта сертификата в JRE.
keytool -import -alias _alias_name_ -keystore..\lib\security\cacerts -file _path_to_cer_file
Он запросит пароль. По умолчанию пароль "changeit". Если пароль отличается, вы не сможете импортировать сертификат.
Ответ 6
В Mac OS мне пришлось открыть серверный самозаверяющий сертификат с помощью инструмента "Keychain Access", импортировать его, доработать его, а затем выбрать "Всегда доверять" (хотя я и установил его в импортере).
До этого, конечно, я запустил Java-ключ, взятый с -importcert, чтобы импортировать тот же файл в хранилище cacert.
Ответ 7
Если вам не нужна защита SSL, вы можете отключить ее.
/**
* disable SSL
*/
private void disableSslVerification() {
try {
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[] {
new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs,
String authType) {
}
public void checkServerTrusted(X509Certificate[] certs,
String authType) {
}
} };
// Install the all-trusting trust manager
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
// Create all-trusting host name verifier
HostnameVerifier allHostsValid = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
// Install the all-trusting host verifier
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
}
Ответ 8
Для меня я столкнулся с этой ошибкой при вызове вызова webservice, убедитесь, что сайт имеет действительный ssl, то есть логотип на стороне URL-адреса проверен, в противном случае необходимо добавить сертификат в хранилище доверенных ключей в ваша машина
Ответ 9
Я также столкнулся с этим типом проблемы. Я использую tomcat-сервер, после чего я помещаю исправленную папку в tomcat, тогда его запуск работает. И также я заменил JDK1.6 на 1.7, а затем и его работу. Наконец-то я изучаю SSL, тогда я решил это тип проблем. Сначала вам нужно загрузить сертификаты с этого сервера servie-провайдера. Затем вы получите подтверждение.
1.Попробуйте положить одобренную папку на свой сервер.
Следующий путь
2.use jdk1.7
Далее
3. Попробуйте загрузить действительные сертификаты с помощью SSL