Java: sun.security.provider.certpath.SunCertPathBuilderException: istenen hedefe yönelik geçerli sertifika yolu bulunamadı


250

Bir https sunucusundan bir dosya indirecek bir sınıf var . Ben çalıştırdığımda, birçok hata döndürür. Sertifikamla ilgili bir sorunum var gibi görünüyor. İstemci-sunucu kimlik doğrulamasını yok saymak mümkün mü? Öyleyse nasıl?

package com.da;

import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.CharBuffer;
import java.util.concurrent.Future;

import org.apache.http.HttpResponse;
import org.apache.http.client.utils.URIUtils;
import org.apache.http.impl.nio.client.DefaultHttpAsyncClient;
import org.apache.http.nio.IOControl;
import org.apache.http.nio.client.HttpAsyncClient;
import org.apache.http.nio.client.methods.AsyncCharConsumer;
import org.apache.http.nio.client.methods.HttpAsyncGet;
import org.apache.http.nio.client.methods.HttpAsyncPost;

public class RSDDownloadFile {
    static FileOutputStream fos;

    public void DownloadFile(String URI, String Request) throws Exception
    {
        java.net.URI uri = URIUtils.createURI("https", "176.66.3.69:6443", -1, "download.aspx",
                "Lang=EN&AuthToken=package", null);
        System.out.println("URI Query: " + uri.toString());

        HttpAsyncClient httpclient = new DefaultHttpAsyncClient();
        httpclient.start();
        try {
            Future<Boolean> future = httpclient.execute(
                    new HttpAsyncGet(uri),
                    new ResponseCallback(), null);

            Boolean result = future.get();
            if (result != null && result.booleanValue()) {
                System.out.println("\nRequest successfully executed");
            } else {
                System.out.println("Request failed");
            }              
        } 
        catch(Exception e){
            System.out.println("[DownloadFile] Exception: " + e.getMessage());
        }
        finally {
            System.out.println("Shutting down");
            httpclient.shutdown();
        }
        System.out.println("Done");  

    }

    static class ResponseCallback extends AsyncCharConsumer<Boolean> {

        @Override
        protected void onResponseReceived(final HttpResponse response) {
             System.out.println("Response: " + response.getStatusLine());
             System.out.println("Header: " + response.toString());
             try {   
                 //if(response.getStatusLine().getStatusCode()==200)
                     fos = new FileOutputStream( "Response.html" );
             }catch(Exception e){
                 System.out.println("[onResponseReceived] Exception: " + e.getMessage());
             }
        }

        @Override
        protected void onCharReceived(final CharBuffer buf, final IOControl ioctrl) throws IOException {
            try
            {
                while (buf.hasRemaining()) 
                {
                    //System.out.print(buf.get());
                    fos.write(buf.get());
                }
            }catch(Exception e)
            {
                System.out.println("[onCharReceived] Exception: " + e.getMessage());
            }
        }

        @Override
        protected void onCleanup() {
            try
            {             
                if(fos!=null)
                    fos.close();
            }catch(Exception e){
                System.out.println("[onCleanup] Exception: " + e.getMessage());         
            }
             System.out.println("onCleanup()");
        }

        @Override
        protected Boolean buildResult() {
            return Boolean.TRUE;
        }

    }
}

Hatalar:

URI Query: https://176.66.3.69:6443/download.aspx?Lang=EN&AuthToken=package
Aug 2, 2011 3:47:57 PM org.apache.http.impl.nio.client.NHttpClientProtocolHandler exception
SEVERE: I/O error: General SSLEngine problem
javax.net.ssl.SSLHandshakeException: General SSLEngine problem
    at com.sun.net.ssl.internal.ssl.Handshaker.checkThrown(Unknown Source)
    at com.sun.net.ssl.internal.ssl.SSLEngineImpl.checkTaskThrown(Unknown Source)
    at com.sun.net.ssl.internal.ssl.SSLEngineImpl.writeAppRecord(Unknown Source)
    at com.sun.net.ssl.internal.ssl.SSLEngineImpl.wrap(Unknown Source)
    at javax.net.ssl.SSLEngine.wrap(Unknown Source)
    at org.apache.http.impl.nio.reactor.SSLIOSession.doHandshake(SSLIOSession.java:154)
    at org.apache.http.impl.nio.reactor.SSLIOSession.isAppInputReady(SSLIOSession.java:276)
    at org.apache.http.impl.nio.client.InternalClientEventDispatch.inputReady(InternalClientEventDispatch.java:79)
    at org.apache.http.impl.nio.reactor.BaseIOReactor.readable(BaseIOReactor.java:161)
    at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvent(AbstractIOReactor.java:335)
    at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvents(AbstractIOReactor.java:315)
    at org.apache.http.impl.nio.reactor.AbstractIOReactor.execute(AbstractIOReactor.java:275)
    at org.apache.http.impl.nio.reactor.BaseIOReactor.execute(BaseIOReactor.java:104)
    at org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor$Worker.run(AbstractMultiworkerIOReactor.java:542)
    at java.lang.Thread.run(Unknown Source)
Caused by: javax.net.ssl.SSLHandshakeException: General SSLEngine problem
    at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Unknown Source)
    at com.sun.net.ssl.internal.ssl.SSLEngineImpl.fatal(Unknown Source)
    at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source)
    at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(Unknown Source)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(Unknown Source)
    at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Unknown Source)
    at com.sun.net.ssl.internal.ssl.Handshaker$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.net.ssl.internal.ssl.Handshaker$DelegatedTask.run(Unknown Source)
    at org.apache.http.impl.nio.reactor.SSLIOSession.doHandshake(SSLIOSession.java:180)
    ... 9 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(Unknown Source)
    at sun.security.validator.PKIXValidator.engineValidate(Unknown Source)
    at sun.security.validator.Validator.validate(Unknown Source)
    at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source)
    at com.sun.net.ssl.internal.ssl.JsseX509TrustManager.checkServerTrusted(Unknown Source)
    ... 16 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(Unknown Source)
    at java.security.cert.CertPathBuilder.build(Unknown Source)
    ... 21 more
onCleanup()

[DownloadFile] Exception: javax.net.ssl.SSLHandshakeException: General SSLEngine problem
Shutting down
Done

2
Bir keresinde bu hatayı aldım ve güvenlik ekibimizle iletişime geçtim ve takımımız şirket tarafından sağlanan eski bir tanesini kullandığından, kullandığımız JAR'ı düzeltmek zorunda kaldım. Benzer bir durumda olabilecek herkes için sadece bir FYI.
kayleeFrye_onDeck

Yanıtlar:


215

Sorun, sunucunuzda kendinden imzalı bir sertifika olduğunda görünür. Bu sorunu çözmek için, bu sertifikayı JVM'nizin güvenilir sertifikalar listesine ekleyebilirsiniz.

Bu makalede yazar, sertifikanın tarayıcınızdan nasıl getirileceğini ve JVM'nizin cacerts dosyasına nasıl ekleneceğini açıklamaktadır. JAVA_HOME/jre/lib/security/cacertsDosyayı düzenleyebilir veya uygulamanızı -Djavax.net.ssl.trustStoreparametre ile çalıştırabilirsiniz . Hangi JDK / JRE'yi de kullandığınızı doğrulayın, çünkü bu genellikle bir karışıklık kaynağıdır.

Ayrıca bkz: SSL sertifika sunucusu adları nasıl çözülür / Tuş aracını kullanarak alternatif adlar ekleyebilir miyim? java.security.cert.CertificateException: No name matching localhost foundİstisna durumunda kalırsanız .


3
bu benim için işe yaramadı. Ben kök ve zincir sertifika yüklü var, ama Tomcat-7 hala "hata ayıklamak için herhangi bir şekilde geçerli sertifika yolu bulamıyor" neden validatorException rapor bu hata ayıklama?
Cheruvim

Sorun, başka biri tarafından imzalanmamış ve güvenilir olmayan bir sertifikada da ortaya çıkıyor.
Lorne Marquis

Harika! İşe yarıyor! Hem jre hem de jdk'ye sahip olabileceğinizi ve her ikisinin cacertsde güncellenmesi gerektiğini unutmayın
Dima Fomin

Benim durumumda, kök CA vardı ama sonraki CA aşağı değil. Bir sonraki CA'yı eklemek hile yaptı - teşekkürler.
java-addict301

1
Benim durumumda Netbeans + Apache Tomcat (entegre) kullanıyorum, bu yüzden Jdk / jre (C: \ Program Files \ Java \ jdk1.8.0_152 \ jre \ lib \ güven deposuna "cacerts" güvenlik) ve Jre (C: \ Program Files \ Java \ jre1.8.0_91 \ lib \ security) benim için çalışıyor
Jnn

149

İşte macOS'ta benim için güvenilir bir şekilde çalışıyor. Example.com ve 443'ü, bağlanmaya çalıştığınız gerçek ana bilgisayar adı ve bağlantı noktası ile değiştirdiğinizden emin olun ve özel bir takma ad verin. İlk komut, sağlanan sertifikayı uzak sunucudan indirir ve yerel olarak x509 biçiminde kaydeder. İkinci komut kaydedilen sertifikayı Java'nın SSL güven deposuna yükler.

openssl x509 -in <(openssl s_client -connect example.com:443 -prexit 2>/dev/null) -out ~/example.crt
sudo keytool -importcert -file ~/example.crt -alias example -keystore $(/usr/libexec/java_home)/jre/lib/security/cacerts -storepass changeit

3
Benim için neden çalışıyor? Bir açıklama sağlamanız gerekiyor.
Lorne Marquis

openssl x509 -in <(openssl s_client -connect example.com:443 -prexit 2> / dev / null) -out ~ / example.crt - komutta örnek.crt nedir, vermem gereken bir .pem sertifikası var burada ??
Vishnu Ranganathan

3
.crt ve .pem aynı dosya biçimi için yaygın olarak kullanılan dosya uzantılarıdır. Dosyaya zaten sahipseniz, sadece ikinci komutu çalıştırın ve -file argümanına iletin.
Gabe Martin-Dempesy

1
Harika şeyler. Tek şey şu ki: En son openssl 1.0.Xx'i herhangi bir nedenle kullanmak zorunda kaldım, eski 9.X.Xx çalışmadı.
zbstof

1
Bu SNI uç noktasıyla çalışmaz. Bu durumda eklemeniz gerekir: -servername example.com sertifikayı getirirken
Patrik Beck

46

Symantec'ten geçerli bir imzalı joker sertifika ile aynı sorunu yaşadım.

Öncelikle neler olduğunu görmek için java uygulamanızı -Djavax.net.debug = SSL ile çalıştırmayı deneyin .

I bitti ara sertifika içe sertifika zincirin kopmasına neden oldu.

Kayıp ara sertifikayı symantec'ten indirdim (ssl el sıkışma günlüğünde eksik sertifikaya indirme bağlantısını görebilirsiniz: http://svrintl-g3-aia.verisign.com/SVRIntlG3.cer benim durumumda).

Ve sertifikayı java anahtar deposuna aktardım. Ara sertifikayı içe aktardıktan sonra joker karakterim ssl sertifikam nihayet çalışmaya başladı:

keytool -import -keystore ../jre/lib/security/cacerts -trustcacerts -alias "VeriSign Class 3 International Server CA - G3" -file /pathto/SVRIntlG3.cer

Durum
buydu

2
Karışıklığı önlemek için, günlüklerde uzak "Sertifika zinciri" ni görmek için hata ayıklama parametreleriyle java (veya jcurl) komutunu çalıştırın, ardından truststore'daki "CN" yi (varsayılan yerine) açık bir şekilde geçirin, yoksa, eklemeniz gerekir. ssllabs.com/ssltest/analyze.html , sunucu tarafı sertifikalarının zincirinin tamamlanıp tamamlanmadığını gösterir ve eklenmesi gereken ara sertifika yolu sertifikaları içerir. -Djavax.net.debug=ssl,handshake -Djavax.net.ssl.keyStoreType=PKCS12 -Djavax.net.ssl.keyStore=our-client-certs -Djavax.net.ssl.trustStoreType=jks -Djavax.net.ssl.trustStore=their-server-certs
kisna


Aynı sorunu yaşadım, bu çok yararlı, ama benim durumumda sadece sunucu sertifikasını JDK sürümünün cacerts dosyasına eklemeniz gerekiyordu
Pigritia

Cacert dosyasını (sertifika deposu) açabilen ve sertifikayı kolayca içe aktarabilen portecle adında başka bir araç olduğunu lütfen unutmayın. Daha sonra cacert dosyasını kaydetmeyi unutmayın.
will824

41
  1. SSL sertifikasını Firefox kullanarak dışa aktarın. Tarayıcıdaki URL'ye basarak dışa aktarabilir ve ardından sertifikayı dışa aktarma seçeneğini belirleyebilirsiniz. Sertifika dosya adının sizin .ssl.server.name.crt olduğunu varsayalım.
  2. Adresine gidin JRE_HOME/binveyaJDK/JRE/bin
  3. Komutu yazın
  4. keytool -keystore ..\lib\security\cacerts -import -alias your.ssl.server.name -file .\relative-path-to-cert-file\your.ssl.server.name.crt
  5. Java işleminizi yeniden başlatın

13
Parola istenirse, varsayılan cacerts anahtar deposu parolasını kullanın changeit( stackoverflow.com/a/22782035/1304830 ). Ayrıca cmd'yi yönetici olarak çalıştırdığınızdan emin olun.
Fr4nz

22

@Gabe Martin-Dempesy'nin cevabı bana yardımcı oldu. Ve bununla ilgili küçük bir senaryo yazdım. Kullanımı çok basit.

Ana bilgisayardan bir sertifika yükleyin:

> sudo ./java-cert-importer.sh example.com

Yüklü sertifikayı kaldırın.

> sudo ./java-cert-importer.sh example.com --delete

java-cert-importer.sh

#!/usr/bin/env bash

# Exit on error
set -e

# Ensure script is running as root
if [ "$EUID" -ne 0 ]
  then echo "WARN: Please run as root (sudo)"
  exit 1
fi

# Check required commands
command -v openssl >/dev/null 2>&1 || { echo "Required command 'openssl' not installed. Aborting." >&2; exit 1; }
command -v keytool >/dev/null 2>&1 || { echo "Required command 'keytool' not installed. Aborting." >&2; exit 1; }

# Get command line args
host=$1; port=${2:-443}; deleteCmd=${3:-${2}}

# Check host argument
if [ ! ${host} ]; then
cat << EOF
Please enter required parameter(s)

usage:  ./java-cert-importer.sh <host> [ <port> | default=443 ] [ -d | --delete ]

EOF
exit 1
fi;

if [ "$JAVA_HOME" ]; then
    javahome=${JAVA_HOME}
elif [[ "$OSTYPE" == "linux-gnu" ]]; then # Linux
    javahome=$(readlink -f $(which java) | sed "s:bin/java::")
elif [[ "$OSTYPE" == "darwin"* ]]; then # Mac OS X
    javahome="$(/usr/libexec/java_home)/jre"
fi

if [ ! "$javahome" ]; then
    echo "WARN: Java home cannot be found."
    exit 1
elif [ ! -d "$javahome" ]; then
    echo "WARN: Detected Java home does not exists: $javahome"
    exit 1
fi

echo "Detected Java Home: $javahome"

# Set cacerts file path
cacertspath=${javahome}/lib/security/cacerts
cacertsbackup="${cacertspath}.$$.backup"

if ( [ "$deleteCmd" == "-d" ] || [ "$deleteCmd" == "--delete" ] ); then
    sudo keytool -delete -alias ${host} -keystore ${cacertspath} -storepass changeit
    echo "Certificate is deleted for ${host}"
    exit 0
fi

# Get host info from user
#read -p "Enter server host (E.g. example.com) : " host
#read -p "Enter server port (Default 443) : " port

# create temp file
tmpfile="/tmp/${host}.$$.crt"

# Create java cacerts backup file
cp ${cacertspath} ${cacertsbackup}

echo "Java CaCerts Backup: ${cacertsbackup}"

# Get certificate from speficied host
openssl x509 -in <(openssl s_client -connect ${host}:${port} -prexit 2>/dev/null) -out ${tmpfile}

# Import certificate into java cacerts file
sudo keytool -importcert -file ${tmpfile} -alias ${host} -keystore ${cacertspath} -storepass changeit

# Remove temp certificate file
rm ${tmpfile}

# Check certificate alias name (same with host) that imported successfully
result=$(keytool -list -v -keystore ${cacertspath} -storepass changeit | grep "Alias name: ${host}")

# Show results to user
if [ "$result" ]; then
    echo "Success: Certificate is imported to java cacerts for ${host}";
else
    echo "Error: Something went wrong";
fi;

Kusursuz çalışır. İyi iş! . Bu şekilde çalışır: SSL hizmetinizi başlatın (çalışmıyorsa) ve açıklandığı gibi komutu yürütün (örn. ./java-cert-importer.sh example.com 1234). Bu kadar.
lepe

1
Harika çalışıyor. Ben onun sertifikasını değiştirir ve builts başarısız bir harici API bağlanma Jenkins sunucu hatası alıyordum. Bu sorunumu çözdü
user9869932

Oracle her şeyden önce böyle bir şey sağlamış olmalı ya da her biri kendi korkunç SSL çözümünü yaratmamıştı. SSL sertifikası işleme bir işletim sisteminin işi olmalıdır.
Wolfgang Fahl

17

Artık 'istenen hedefe geçerli sertifika yolu bulamıyor' ifadesinden alıntı yapılıyor

JSSE kullanarak bir ana bilgisayara SSL bağlantısı açmaya çalışırken. Bunun genellikle anlamı, sunucunun Verisign veya GoDaddy gibi iyi bilinen bir ticari Sertifika Yetkilisi'nden bir sertifika yerine bir test sertifikası (muhtemelen keytool kullanılarak oluşturulmuş) kullanmasıdır. Web tarayıcıları bu durumda uyarı iletişim kutuları görüntüler, ancak JSSE etkileşimli bir kullanıcının var olduğunu varsayamayacağından, varsayılan olarak bir istisna atar.

Sertifika doğrulaması SSL güvenliğinin çok önemli bir parçasıdır, ancak ayrıntıları açıklamak için bu girişi yazmıyorum. İlgileniyorsanız, Wikipedia bulanıklığını okuyarak başlayabilirsiniz. Bu girişi, gerçekten istiyorsanız, test sertifikasıyla o ana bilgisayarla konuşmanın basit bir yolunu göstermek için yazıyorum.

Temel olarak, güvenilir sertifikalarınızla sunucunun sertifikasını KeyStore'a eklemek istersiniz

Orada verilen kodu deneyin. O yardımcı olabilir.


5
"Sertifika doğrulaması SSL güvenliğinin çok önemli bir parçasıdır" ile ilgili bölüm her zaman doğru değildir. SSL size iki güvence verir: (1) iletişiminizin özel olduğu ve (2) NSA tarafından bilinen bir sunucu ile konuştuğunuz. (:-) Bazen yalnızca konuşmanın gizliliğini önemsiyorsunuz ve kendinden imzalı sertifika iyidir. Bkz. Social-biz.org/2011/10/16/the-anti-ssl-conspiracy
AgilePro

@AgilePro SSL size dört güvence verir : kimlik doğrulama, gizlilik, bütünlük ve yetkilendirme olasılığı. O mu değil size NSA tarafından bilinen bir sunucuya bahsediyoruz herhangi bir güvence verir. Sadece kimlik doğrulaması olmadan mahremiyetle ilgilenmek, terimler açısından bir çelişkidir.
Lorne Marquis

@EJP Bir istemci sertifikası kullanırsanız, kimlik doğrulama yapabileceğinizi ve yetkilendirme olasılığını varsayalım ... ancak çoğu kullanımın bir istemci sertifikası olmadığını kabul edin. "Kendinden imzalı" sertifika ile imza yetkilisinden alınan sertifika arasındaki farka ne denir? İmza yetkisi "bütünlük" veriyor mu? NSA hakkındaki şakam, tüm imza yetkililerinin her şeyden bağımsızlığı olumlu bir şekilde garanti edememesidir. Bu paranoyak değil, ama asıl mesele, sertifikanızın SADECE imza yetkilisinin yapabileceği kadar gizli olmasıdır. Kendinden imzalı daha gizli olabilir.
AgilePro

@AgilePro Sunucu sertifikası kullanmak sunucunun kimliğini doğrular ve RFC 2246'da belirtildiği gibi SSL'yi güvenli hale getirmek gerekir . Sertifikalar hiç gizli değildir: bu nedenle yorumunuzun geri kalanı mantıklı değildir.
Lorne Marquis

6

Bu benim sorunumu çözdü,

Sertifikayı yerel java'ya aktarmamız gerekiyor. Değilse, aşağıdaki istisnayı alabiliriz.

    javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX yolu oluşturma başarısız oldu: sun.security.provider.certpath.SunCertPathBuilderException: istenen hedefe geçerli sertifika yolu bulunamadı
        sun.security.ssl.Alerts.getSSLException adresinde (Alerts.java:192)
        sun.security.ssl.SSLSocketImpl.fatal (SSLSocketImpl.java:1949) adresinde
        sun.security.ssl.Handshaker.fatalSE (Handshaker.java:302)

SSLPOKE , yerel makinenizden https bağlantısını test edebileceğiniz bir araçtır.

Bağlantıyı test etme komutu:

"%JAVA_HOME%/bin/java" SSLPoke <hostname> 443
    sun.security.validator.ValidatorException: PKIX yolu oluşturma başarısız oldu: 
    sun.security.provider.certpath.SunCertPathBuilderException: istenen hedefe yönelik geçerli sertifika yolu bulunamadı
        sun.security.validator.PKIXValidator.doBuild (PKIXValidator.java:387)
        sun.security.validator.PKIXValidator.engineValidate (PKIXValidator.java:292)
        sun.security.validator.Validator.validate (Validator.java:260)
        sun.security.ssl.X509TrustManagerImpl.validate adresinde (X509TrustManagerImpl.java:324)
        sun.security.ssl.X509TrustManagerImpl.checkTrusted'da (X509TrustManagerImpl.java:229)
        sun.security.ssl.X509TrustManagerImpl.checkServerTrusted (X509TrustManagerImpl.java:124)
        sun.security.ssl.ClientHandshaker.serverCertificate'de (ClientHandshaker.java:1496)
        sun.security.ssl.ClientHandshaker.processMessage (ClientHandshaker.java:216)
        sun.security.ssl.Handshaker.processLoop (Handshaker.java:1026)
        sun.security.ssl.Handshaker.process_record adresinde (Handshaker.java:961)
        sun.security.ssl.SSLSocketImpl.readRecord'da (SSLSocketImpl.java:1062)
        sun.security.ssl.SSLSocketImpl.performInitialHandshake (SSLSocketImpl.java:1375)
        sun.security.ssl.SSLSocketImpl.writeRecord'da (SSLSocketImpl.java:747)
        sun.security.ssl.AppOutputStream.write (AppOutputStream.java:123)
        sun.security.ssl.AppOutputStream.write (AppOutputStream.java:138)
        SSLPoke.main adresinde (SSLPoke.java:31)
    Nedeni: sun.security.provider.certpath.SunCertPathBuilderException: için geçerli sertifika yolu bulunamadı 
    istenen hedef
        sun.security.provider.certpath.SunCertPathBuilder.build (SunCertPathBuilder.java:141)
        sun.security.provider.certpath.SunCertPathBuilder.engineBuild (SunCertPathBuilder.java:126)
        java.security.cert.CertPathBuilder.build adresinde (CertPathBuilder.java:280)
        sun.security.validator.PKIXValidator.doBuild (PKIXValidator.java:382)
        ... 15 tane daha
keytool -import -alias <anyname> -keystore "%JAVA_HOME%/jre/lib/security/cacerts" -file <cert path>

ilk önce "anahtar deposu şifresini girin:" changeitvarsayılan şifre olur. ve son olarak "Bu sertifikaya güven? [hayır]:" istemi, sertifikayı anahtar deposuna eklemek için "evet" yazın.

doğrulaması ise:

C:\tools>"%JAVA_HOME%/bin/java" SSLPoke <hostname> 443
Successfully connected    

5

Ben sadece kod ile çalışma elde etmek mümkün, yani keytool kullanmaya gerek yok:

import com.netflix.config.DynamicBooleanProperty;
import com.netflix.config.DynamicIntProperty;
import com.netflix.config.DynamicPropertyFactory;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.conn.ssl.X509HostnameVerifier;
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import org.apache.http.impl.nio.client.HttpAsyncClients;
import org.apache.http.impl.nio.conn.PoolingNHttpClientConnectionManager;
import org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor;
import org.apache.http.impl.nio.reactor.IOReactorConfig;
import org.apache.http.nio.conn.NoopIOSessionStrategy;
import org.apache.http.nio.conn.SchemeIOSessionStrategy;
import org.apache.http.nio.conn.ssl.SSLIOSessionStrategy;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import java.io.IOException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

public class Test
{
    private static final DynamicIntProperty MAX_TOTAL_CONNECTIONS = DynamicPropertyFactory.getInstance().getIntProperty("X.total.connections", 40);
    private static final DynamicIntProperty ROUTE_CONNECTIONS = DynamicPropertyFactory.getInstance().getIntProperty("X.total.connections", 40);
    private static final DynamicIntProperty CONNECT_TIMEOUT = DynamicPropertyFactory.getInstance().getIntProperty("X.connect.timeout", 60000);
    private static final DynamicIntProperty SOCKET_TIMEOUT = DynamicPropertyFactory.getInstance().getIntProperty("X.socket.timeout", -1);
    private static final DynamicIntProperty CONNECTION_REQUEST_TIMEOUT = DynamicPropertyFactory.getInstance().getIntProperty("X.connectionrequest.timeout", 60000);
    private static final DynamicBooleanProperty STALE_CONNECTION_CHECK = DynamicPropertyFactory.getInstance().getBooleanProperty("X.checkconnection", true);

    public static void main(String[] args) throws Exception
    {

        SSLContext sslcontext = SSLContexts.custom()
                .useTLS()
                .loadTrustMaterial(null, new TrustStrategy()
                {
                    @Override
                    public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException
                    {
                        return true;
                    }
                })
                .build();
        SSLIOSessionStrategy sslSessionStrategy = new SSLIOSessionStrategy(sslcontext, new AllowAll());

        Registry<SchemeIOSessionStrategy> sessionStrategyRegistry = RegistryBuilder.<SchemeIOSessionStrategy>create()
                .register("http", NoopIOSessionStrategy.INSTANCE)
                .register("https", sslSessionStrategy)
                .build();

        DefaultConnectingIOReactor ioReactor = new DefaultConnectingIOReactor(IOReactorConfig.DEFAULT);
        PoolingNHttpClientConnectionManager connectionManager = new PoolingNHttpClientConnectionManager(ioReactor, sessionStrategyRegistry);
        connectionManager.setMaxTotal(MAX_TOTAL_CONNECTIONS.get());
        connectionManager.setDefaultMaxPerRoute(ROUTE_CONNECTIONS.get());

        RequestConfig requestConfig = RequestConfig.custom()
                .setSocketTimeout(SOCKET_TIMEOUT.get())
                .setConnectTimeout(CONNECT_TIMEOUT.get())
                .setConnectionRequestTimeout(CONNECTION_REQUEST_TIMEOUT.get())
                .setStaleConnectionCheckEnabled(STALE_CONNECTION_CHECK.get())
                .build();

        CloseableHttpAsyncClient httpClient = HttpAsyncClients.custom()
                .setSSLStrategy(sslSessionStrategy)
                .setConnectionManager(connectionManager)
                .setDefaultRequestConfig(requestConfig)
                .build();

        httpClient.start();

        // use httpClient...
    }

    private static class AllowAll implements X509HostnameVerifier
    {
        @Override
        public void verify(String s, SSLSocket sslSocket) throws IOException
        {}

        @Override
        public void verify(String s, X509Certificate x509Certificate) throws SSLException {}

        @Override
        public void verify(String s, String[] strings, String[] strings2) throws SSLException
        {}

        @Override
        public boolean verify(String s, SSLSession sslSession)
        {
            return true;
        }
    }
}

1
Btw, httpasyncclient kullanıyorum: 4.0.1
Jonas Bergström

Benzer bir şeye ihtiyacım vardı, @ JonasBergström, SSLContext ile çözümünüz çok yardımcı oldu.
EnterSB

8
Bu çözümün güvenli olmadığını unutmayın.
Lorne Marquis

Teşekkür ederim Jonas, çözümünüz sorunu çözdü. Ancak ilk bağlantıyı oluşturmanın çok uzun bir süreye (3 - 5s) mal olduğunu gördüm, bundan sonra her bağlantının sadece 300-400 ms'ye ihtiyacı var.
twcai

5

Apache 2.4 örneğimdeki (Comodo joker karakter sertifikası kullanarak) bu hatanın kaynağı, SHA-1 imzalı kök sertifikasının eksik bir yoluydu. Verilen sertifikada birden fazla zincir vardı ve bir SHA-1 kök sertifikasına giden zincirde bir ara sertifika eksikti . Modern tarayıcılar bunun nasıl yapılacağını bilir, ancak Java 7 bunu varsayılan olarak işlemez (buna rağmen kodda başarmak için bazı karmaşık yollar olsa da). Sonuç, kendinden imzalı sertifikalarla aynı görünen hata iletileridir:

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:196)
    at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:268)
    at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:380)
    ... 22 more

Bu durumda, eksik ara sertifika nedeniyle "istenen hedefe geçerli sertifika yolu bulunamıyor" iletisi üretiliyor. Sunucuda SSL Labs testi kullanarak hangi sertifikanın eksik olduğunu kontrol edebilirsiniz . Uygun sertifikayı bulduktan sonra, sertifikayı indirin ve (sunucu denetiminizdeyse) sertifika paketine ekleyin. Alternatif olarak, eksik sertifikayı yerel olarak alabilirsiniz. Bu sorunu sunucuda barındırmak, soruna daha genel bir çözümdür.


ssllabs.com/ssltest bir kurtarıcı, sadece çalışan bir sertifika doğrulaması ile karşılaştırmak zorunda.
kisna

5

Yalnızca Windows için şu adımları izleyin:

  1. Chrome'da ayarlara gidin.
  2. Ayarlar'da gelişmiş ayarları göster'i tıklayın.
  3. HTTPS / SSL altında Sertifikaları Yönet'e tıklayın.
  4. Sertifikanızı Verme.
  5. Windows aramalarında (klavyede windows tuşuna basma) java yazın.
  6. Java Denetim Masası'nı açacak olan (Java'yı Yapılandır) Seçeneğini Seçin
  7. Java Denetim Masası'nda Güvenlik sekmesini seçin
  8. Sertifikaları Yönet'i seçin
  9. İçe Aktar'ı tıklayın
  10. (Kullanıcı) sekmesi altında seçili ve sertifika türü (Güvenilen Sertifikalar) olarak
  11. İçe aktar düğmesini tıklayın ve indirilen sertifikaya göz atın ve içe aktarın.

4

Debian ve hazır ambalajlı Java'yı sevenler için:

sudo mkdir /usr/share/ca-certificates/test/  # don't mess with other certs
sudo cp ~/tmp/test.loc.crt /usr/share/ca-certificates/test/
sudo dpkg-reconfigure --force ca-certificates  # check your cert in curses GUI!
sudo update-ca-certificates --fresh --verbose

Kontrol etmeyi unutmayın /etc/default/cacerts:

# enable/disable updates of the keystore /etc/ssl/certs/java/cacerts
cacerts_updates=yes

Sertifikayı kaldırmak için:

sudo rm /usr/share/ca-certificates/test/test.loc.crt
sudo rm /etc/ssl/certs/java/cacerts
sudo update-ca-certificates --fresh --verbose

2

Bunun nedeni SHA2 kullanılarak imzalanan Java 7 ile GoDaddy sertifikalarının kullanılması olabilir.

Chrome ve diğer tüm tarayıcılar, güvenli olmadığı için SHA1 kullanılarak imzalanan SSL sertifikalarını kullanımdan kaldırmaya başlıyor.

Sorunla ilgili daha fazla bilgiyi burada ve şimdi gerekirse sunucunuzda nasıl çözeceğinizi burada bulabilirsiniz .


2

Sertifika hatası ile aynı sorunu yaşadım ve SNI yüzünden oldu ve kullandığım http istemcisi SNI uygulanmadı. Bu yüzden bir sürüm güncellemesi işi yaptı

   <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.3.6</version>
    </dependency>

2

GÜNCELLEME: Bir yeniden başlatmanın yardımcı olması tesadüfî (umudum, yaşasın!). Sorunun asıl nedeni şuydu: Gradle belirli bir anahtar deposunu kullanmaya yönlendirildiğinde, bu anahtar deposu tüm resmi kök sertifikaları da içermelidir. Aksi takdirde kütüphanelere düzenli depolardan erişemez. Ne yapmam gerekiyordu:

Kendinden imzalı sertifikayı içeri aktarma:

keytool -import -trustcacerts -alias myselfsignedcert -file /Users/me/Desktop/selfsignedcert.crt -keystore ./privateKeystore.jks

Resmi kök sertifikaları ekleyin:

keytool -importkeystore -srckeystore <java-home>/lib/security/cacerts -destkeystore ./privateKeystore.jks

Belki Gradle daemon da yoluna çıktı. ./gradlew --statusİşler kasvetli görünmeye başlarsa, bulunan tüm çalışan cinleri öldürmeye değer olabilir.

ORİJİNAL POSTING:

Kimse buna inanmayacak, biliyorum. Yine de, her şey başarısız olursa, bir deneyin: Mac bilgisayarımı yeniden başlattıktan sonra sorun ortadan kalktı. Grrr.

Arka plan: ./gradlew kavanoz bana "istenen hedefe geçerli sertifika yolu bulamıyor" vermeye devam etti

PrivateKeystore.jks'e aktarılan, tarayıcıdan kaydedilmiş, kendinden imzalı bir sertifika ile sıkıştım. Daha sonra Gradle'a privateKeystore.jks ile çalışması talimatı verildi:

org.gradle.jvmargs=-Djavax.net.debug=SSL -Djavax.net.ssl.trustStore="/Users/me/IntelliJ/myproject/privateKeystore.jks"  -Djavax.net.ssl.trustStorePassword=changeit

Belirtildiği gibi, bu sadece bir yeniden başlatmadan sonra çalıştı.


2

AVG sürüm 18.1.3044 (Windows 10 ile) yerel Spring uygulamama müdahale ediyor.

Çözüm: "Web ve e-posta" adlı AVG bölümüne girin ve "e-posta korumasını" devre dışı bırakın. AVG site güvenli değilse sertifikayı engeller.



2

Bunu çözmenin birçok yolu var ...

Bunun bir yolu, bir anahtar deposu dosyasında TrustStore sertifikalarını ayarlamak ve uygulamanın yoluna koymak ve bu sistem özelliklerini ana yöntemde ayarlamaktır:

public static void main(String[] args) {
  System.setProperty("javax.net.ssl.trustStore", "trust-store.jks");
  System.setProperty("javax.net.ssl.trustStorePassword", "TrustStore");
  ...
}

Diğer yol, anahtar deposunu proje jar dosyasının içine kaynak dosyası olarak yerleştirip yüklemektir:

public static SSLContext createSSLContext(String resourcePath, String pass) throws NoSuchAlgorithmException, KeyStoreException, IOException, CertificateException, UnrecoverableKeyException, KeyManagementException {
  // initialise the keystore
  final char[] password = pass.toCharArray();
  KeyStore ks = KeyStore.getInstance("JKS");
  ks.load(ThisClass.class.getResourceAsStream(resourcePath
  ), password);

  // Setup the key manager factory.
  KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
  kmf.init(ks, password);

  // Setup the trust manager factory.
  TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
  tmf.init(ks);

  SSLContext sslc = SSLContext.getInstance("TLS");
  sslc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
  return sslc;
}

public static void main(String[] args) {
  SSLContext.setDefault(
    createSSLContext("/trust-store.jks", "TrustStore"));
  ...
}

Windows'da da bu çözümü deneyebilirsiniz: https://stackoverflow.com/a/59056537/980442


Anahtar deposu dosyasını bir Sertifika yetkilisi CA .crtdosyasından şu şekilde oluşturdum:

keytool -import -alias ca -keystore trust-store.jks -storepass TrustStore -trustcacerts -file ca.crt

Bilginize: https://docs.oracle.com/javadb/10.8.3.0/adminguide/cadminsslclient.html


1

İki seçeneğiniz vardır, otomatik olarak imzalanan sertifikayı, yazılımın çalışacağı her jvm için java'nın anahtar deposuna içe aktarın veya doğrulama yapmayan ssl fabrikasını deneyin:

jdbc:postgresql://myserver.com:5432/mydatabasename?ssl=true&sslfactory=org.postgresql.ssl.NonValidatingFactory

1

Bu görüntü gibi bir sorun vardı.

resim açıklamasını buraya girin

Birkaç çözüm denedim. Ama aynı proje olsa bile, diğerinin işyerinde olduğu zaman tamamen iyi olduğunu gördüm. Ek ayar gerekmez. Bu yüzden bir çevre sorunu olduğunu tahmin ettik. JDK sürümünü (IDE) değiştirmeyi denedik, ancak çalışmadı. en yüksek puan alan cevabı deneyene kadar yaklaşık 4 saat sürdü. Bu cevapta belirtilen hatayı bulamadım ama tarayıcımdan HTTP URL'si (kilit) hakkında Charles sertifikası olduğunu buldum. Sonra charles'ımın sürekli açık olduğunu fark ettim. Bunu kapattığım sürece, her şey yolunda gidiyor.

Bu yüzden davanız için yararlı olabilecek deneyimlerimi bıraktım.


0

Benim durumumda Java 1.6 ile MacOs High Sierra kullanıyorum. Cacert dosyası, Gabe Martin-Dempesy'nin cevabında yukarıda belirtilenden farklı bir konumda. Cacert dosyası zaten başka bir konuma da bağlanmıştı (/ Library / Internet Plug-Ins / JavaAppletPlugin.plugin / Contents / Home / lib / security / cacerts).

FireFox kullanarak, söz konusu web sitesinden sertifikayı "exportedCertFile.crt" adlı yerel bir dosyaya verdim. Oradan sertifikayı cacert dosyasına taşımak için keytool'u kullandım. Bu sorunu düzeltti.

bash-3.2# cd /Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/lib/security/
bash-3.2# keytool -importcert -file ~/exportedCertFile.crt -alias example -keystore cacerts -storepass changeit

0

önce ssl sertifikasını indirin, sonra java bin yolunuza gidip konsolda aşağıdaki komutu yürütebilirsiniz.

C:\java\JDK1.8.0_66-X64\bin>keytool -printcert -file C:\Users\lova\openapi.cer -keystore openapistore

-1

Benim durumumda hem anahtar deposu hem de truststore aynı sertifikaya sahipti, böylece truststore'un kaldırılması yardımcı oldu. Bazen birden fazla sertifika kopyanız varsa, sertifika zinciri bir sorun olabilir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.