Javax.net.ssl.SSLHandshakeException एरर को कैसे हल करें?


101

मैं वीपीएन से जुड़ा था ताकि उत्पाद सूची प्राप्त करने के लिए इन्वेंट्री एपीआई को सेटअप किया जा सके और यह ठीक काम करे। एक बार जब मैं वेब-सेवा से परिणाम प्राप्त करता हूं और मैं यूआई से बांधता हूं। और जब मैं भुगतान के लिए एक कॉल करता हूँ तो मुझे अपने भुगतान के साथ पेपाल को एकीकृत करना पड़ता है जब मैं इस त्रुटि का सामना कर रहा हूं। मैं बैक-एंड प्रक्रिया के लिए सर्वलेट का उपयोग करता हूं। क्या कोई कह सकता है कि इस मुद्दे को कैसे ठीक किया जाए?

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

1
मैं यह जानना चाहूंगा कि उस सटीक मामले में कौन सा सटीक लक्ष्य था ... आपको एक अपवाद मिलता है, लेकिन आपको लक्ष्य के बारे में कोई जानकारी नहीं मिलती है, जो आप की अपेक्षा के भिन्न हो सकते हैं .. मेरे पास ऐसा मामला है, मुझे यकीन है कि मेरा लिंक प्रमाणपत्र है, और मुझे अभी भी यह अपवाद मिल रहा है
ante.sabo

जवाबों:


151

सबसे पहले, आपको उस सर्वर से सार्वजनिक प्रमाणपत्र प्राप्त करना होगा जिसे आप कनेक्ट करने का प्रयास कर रहे हैं। यह कई प्रकार से किया जा सकता है, जैसे कि सर्वर व्यवस्थापक से संपर्क करना और उसके लिए पूछना, OpenSSL का उपयोग करके इसे डाउनलोड करना , या, चूंकि यह एक HTTP सर्वर प्रतीत होता है, इसे किसी भी ब्राउज़र से कनेक्ट करना, पृष्ठ की सुरक्षा जानकारी को देखना। , और प्रमाण पत्र की एक प्रति सहेजना। (Google आपको यह बताने में सक्षम होना चाहिए कि आपके विशिष्ट ब्राउज़र के लिए क्या करना है।)

अब जब आपके पास एक फ़ाइल में सहेजा गया प्रमाण पत्र है, तो आपको इसे अपने जेवीएम के ट्रस्ट स्टोर में जोड़ना होगा। पर $JAVA_HOME/jre/lib/security/JREs के लिए या $JAVA_HOME/lib/securityJDKs के लिए, वहाँ नाम की एक फ़ाइल है cacertsजो जावा के साथ आता है और अच्छी तरह से ज्ञात प्रमाणन प्राधिकरण की सार्वजनिक प्रमाण पत्र होता है,। नए प्रमाणपत्र को आयात करने के लिए, एक उपयोगकर्ता के रूप में कीटल को चलाएं जिसके पास कैसर्ट में लिखने की अनुमति है:

keytool -import -file <the cert file> -alias <some meaningful name> -keystore <path to cacerts file>

यह सबसे अधिक संभावना है कि आपसे पासवर्ड मांगेगा। जावा के साथ भेज दिया गया डिफ़ॉल्ट पासवर्ड है changeit। लगभग कोई भी इसे बदलता नहीं है। इन अपेक्षाकृत सरल चरणों को पूरा करने के बाद, आप सुरक्षित रूप से और इस आश्वासन के साथ संवाद करेंगे कि आप सही सर्वर और केवल सही सर्वर से बात कर रहे हैं (जब तक कि वे अपनी निजी कुंजी नहीं खो देते)।


12
मुझे "काम नहीं करने" की तुलना में थोड़ा अधिक विस्तार की आवश्यकता होगी। आपने जो प्रयास किया है और कुछ त्रुटि आउटपुट के साथ अपने प्रश्न को अपडेट करने का प्रयास करें। दुर्भाग्य से, यह मेरे सोते समय का रास्ता है, इसलिए शायद कोई और आपके सवालों का जवाब देने में सक्षम होगा। यह भी एक बहुत ही सामान्य स्थिति है। आप ऑनलाइन इस पर बहुत सारी जानकारी पा सकते हैं, जिसमें कीटोल डॉक्स भी शामिल हैं
रयान स्टीवर्ट

मूल रूप से मुझे पेपैल प्रमाण पत्र शामिल करने की आवश्यकता है। मैंने आपके कदम उठाए और उपयुक्त स्थान पर प्रमाणित भी किया गया। तो मैं यह एक ही त्रुटि कहते हैं अनुप्रयोग चलाने के लिए?
बिकादुरई

वास्तव में यह बिना किसी समस्या के ब्राउज़र पर काम करता है और मैंने उस समय इन्वेंट्री लिस्ट प्राप्त करने के लिए वीपीएन को कनेक्ट किया था क्योंकि मैं पेपाल के साथ भुगतान करता हूं, यह एसएसएल त्रुटि कहता है लेकिन मैं ऑफ़लाइन डेटा या हॉट कोडेड डेटा का उपयोग करता हूं इसका मतलब है कि यह काम करता है।
बिकादुरई

4
@ सिलादुरई: आपको पेपाल के लिए एक प्रमाण पत्र आयात करने की आवश्यकता नहीं है। जब तक आपकी कैसर्ट फ़ाइल दूषित या संशोधित नहीं हुई है, तब तक उसमें सभी विश्वसनीय रूट सर्टिफिकेट होने चाहिए, और पेपाल के सर्टिफिकेट को उनमें से किसी एक में वापस करने में सक्षम होना चाहिए। हो सकता है कि आप कैचेस की एक प्रति प्राप्त करने की कोशिश करें जो आपको पता है कि अच्छा है और इसके बजाय आप कोशिश कर रहे हैं। यदि समस्या बनी रहती है, तो आप वास्तव में पेपैल से कनेक्ट नहीं हो सकते हैं।
रयान स्टीवर्ट

@RyanStewart क्या मुझे इसे किसी तरह से ग्लासफिश आयात करने की आवश्यकता है? क्योंकि मैंने अपने जावा होम डायरेक्टरी में अपने कैसर्ट में .cer फ़ाइल को जोड़ा था, लेकिन ग्लासफ़िश इसका उपयोग नहीं करता है इसलिए मुझे अभी भी त्रुटि हो रही है।
सेड जूल

15

अब मैंने इस मुद्दे को इस तरह हल किया,

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.OutputStream; 

// Create a trust manager that does not validate certificate chains like the default 

TrustManager[] trustAllCerts = new TrustManager[]{
        new X509TrustManager() {

            public java.security.cert.X509Certificate[] getAcceptedIssuers()
            {
                return null;
            }
            public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType)
            {
                //No need to implement.
            }
            public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType)
            {
                //No need to implement.
            }
        }
};

// Install the all-trusting trust manager
try 
{
    SSLContext sc = SSLContext.getInstance("SSL");
    sc.init(null, trustAllCerts, new java.security.SecureRandom());
    HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} 
catch (Exception e) 
{
    System.out.println(e);
}

बेशक यह समाधान केवल परिदृश्यों में उपयोग किया जाना चाहिए, जहां keytoolअस्थायी प्रमाण पत्र के साथ स्थानीय परीक्षण का उपयोग करके आवश्यक प्रमाण पत्र स्थापित करना संभव नहीं है ।


52
वाह, मैं एक "फिक्स" कॉल करने में संकोच करूंगा। आपने मूल रूप से सुरक्षा बंद कर दी है। हां, डेटा अभी भी एन्क्रिप्ट किया जाएगा, लेकिन आपके पास कोई गारंटी नहीं है कि आप जिस से बात कर रहे हैं उससे बात कर रहे हैं। सही समाधान यह है कि आप अपने लक्ष्य सर्वर की सार्वजनिक कुंजी प्राप्त करें और जेवीएम के ट्रस्ट स्टोर में कनेक्शन बनाकर आयात करें।
रयान स्टीवर्ट

1
एक उचित समाधान के लिए मेरा जवाब देखें
रयान स्टीवर्ट

किसका उदाहरण? मेरे उत्तर में आपके लिए आवश्यक सभी कदम होने चाहिए।
रयान स्टीवर्ट


3
यदि आप एक देव सर्वर के खिलाफ बहुत ही सरल परीक्षण लिख रहे हैं, तो यहां दिखाया गया कोड उपयोगी लगता है, मैं इस पर उत्पादन के लिए भरोसा नहीं करूंगा।
जेसन डी

12

जब भी हम URL से जुड़ने की कोशिश कर रहे हैं,

अगर दूसरी साइट पर सर्वर https प्रोटोकॉल पर चल रहा है और यह अनिवार्य कर रहा है कि हमें प्रमाणपत्र में दी गई जानकारी के माध्यम से संवाद करना चाहिए तो हमारे पास निम्नलिखित विकल्प हैं:

1) प्रमाणपत्र के लिए पूछें (प्रमाण पत्र डाउनलोड करें), इस प्रमाण पत्र को ट्रस्टोर में आयात करें। डिफ़ॉल्ट भरोसेमंद जावा का उपयोग \ Java \ jdk1.6.0_29 \ jre \ lib \ Security \ cacerts में पाया जा सकता है, अगर हम URL कनेक्शन से जुड़ने के लिए पुन: प्रयास करेंगे तो स्वीकार कर लिया जाएगा।

2) सामान्य व्यावसायिक मामलों में, हम संगठनों में आंतरिक URLS से जुड़ सकते हैं और हम जानते हैं कि वे सही हैं। ऐसे मामलों में, आप भरोसा करते हैं कि यह सही URL है, ऊपर दिए गए ऐसे मामलों में, कोड का उपयोग किया जा सकता है, जो विशेष URL से जुड़ने के लिए प्रमाणपत्र को संग्रहीत करने के लिए अनिवार्य नहीं होगा।

बिंदु नंबर 2 के लिए हमें निम्न चरणों का पालन करना होगा:

1) नीचे विधि लिखें जो HttpsURLConnection के लिए HostnameVerifier सेट करता है जो सभी मामलों के लिए सही है जिसका अर्थ है कि हम ट्रस्टस्टोर पर भरोसा कर रहे हैं।

  // trusting all certificate 
 public void doTrustToCertificates() throws Exception {
        Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
        TrustManager[] trustAllCerts = new TrustManager[]{
                new X509TrustManager() {
                    public X509Certificate[] getAcceptedIssuers() {
                        return null;
                    }

                    public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException {
                        return;
                    }

                    public void checkClientTrusted(X509Certificate[] certs, String authType) throws CertificateException {
                        return;
                    }
                }
        };

        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, new SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
        HostnameVerifier hv = new HostnameVerifier() {
            public boolean verify(String urlHostName, SSLSession session) {
                if (!urlHostName.equalsIgnoreCase(session.getPeerHost())) {
                    System.out.println("Warning: URL host '" + urlHostName + "' is different to SSLSession host '" + session.getPeerHost() + "'.");
                }
                return true;
            }
        };
        HttpsURLConnection.setDefaultHostnameVerifier(hv);
    }

2) नीचे विधि लिखें, जो URL से कनेक्ट करने का प्रयास करने से पहले doTrustToCert प्रमाणपत्र कहता है

    // connecting to URL
    public void connectToUrl(){
     doTrustToCertificates();//  
     URL url = new URL("https://www.example.com");
     HttpURLConnection conn = (HttpURLConnection)url.openConnection(); 
     System.out.println("ResponseCode ="+conn.getResponseCode());
   }

यह कॉल प्रतिक्रिया कोड = 200 का अर्थ है कि कनेक्शन सफल है।

अधिक विवरण और नमूना उदाहरण के लिए आप URL का उल्लेख कर सकते हैं ।


1
Google Play स्टोर इसे अस्वीकार कर देगा। वे देखेंगे कि आप एपीके स्कैन के दौरान एक्स 509 सर्टिफिकेट को नजरअंदाज कर रहे हैं।
ओलिवर डिक्सन

0

मेरा मानना ​​है कि आप SSL का उपयोग करते हुए कुछ से कनेक्ट करने का प्रयास कर रहे हैं, लेकिन कुछ ऐसा प्रमाणपत्र प्रदान कर रहा है जो रूट प्रमाणीकरण अधिकारियों द्वारा सत्यापित नहीं है जैसे कि सत्यापन। .. डिफ़ॉल्ट रूप से सुरक्षित कनेक्शन द्वारा केवल तभी स्थापित किया जा सकता है जब व्यक्ति कनेक्ट करने का प्रयास कर रहा हो समकक्षों की चाबियां या कुछ अन्य बरामदे जैसे कि सत्यापन में कदम रख सकते हैं और कह सकते हैं कि प्रदान की जा रही सार्वजनिक कुंजी वास्तव में सही है ..

सभी OS का विश्वास मुट्ठी भर अधिकारियों और छोटे प्रमाणपत्र जारी करने वालों को प्रमाणित करने की एक बड़ी प्रमाणिकता प्रमाणित करने की आवश्यकता है, अगर आपको मेरा मतलब है ...

वैसे भी वापस आ रहा है .. मुझे एक जावा ऐपलेट और एक जावा सर्वर की प्रोग्रामिंग करते समय एक समस्या थी, (उम्मीद है कि किसी दिन मैं पूरी ब्लॉगपोस्ट लिखूंगा कि मुझे काम करने के लिए सारी सुरक्षा कैसे मिली :))

संक्षेप में मुझे जो करना था वह सर्वर से सार्वजनिक कुंजी निकालने और इसे अपने एप्लेट के अंदर एक कीस्टोर में संग्रहीत करना था और जब मैं सर्वर से जुड़ा तो मैंने एक ट्रस्ट फैक्टरी बनाने के लिए इस कुंजी स्टोर का उपयोग किया और एसएल बनाने के लिए ट्रस्ट फैक्टरी कनेक्शन। JVM के विश्वसनीय होस्ट में कुंजी जोड़ने और स्टार्ट अप पर डिफ़ॉल्ट ट्रस्ट स्टोर को संशोधित करने के साथ-साथ परिवर्तन प्रक्रियाएं भी हैं।

मैंने लगभग दो महीने पहले ऐसा किया था और अभी मुझ पर स्रोत कोड नहीं है .. Google का उपयोग करें और आपको इस समस्या को हल करने में सक्षम होना चाहिए। यदि आप मुझे वापस संदेश नहीं दे सकते हैं और मैं आपको प्रोजेक्ट के लिए रीलेवेंट स्रोत कोड प्रदान कर सकता हूं .. तो पता नहीं कि यह आपकी समस्या को हल करता है क्योंकि आपने कोड प्रदान किया था जो इन अपवादों का कारण बनता है। इसके अलावा मैं काम कर रहा था wiht एप्लेट्स सोचा कि मैं नहीं देख सकता कि यह सर्वर पर काम क्यों नहीं करेगा ...

PS I को सप्ताहांत से पहले स्रोत कोड नहीं मिल सकता क्योंकि बाहरी SSH मेरे कार्यालय में अक्षम है :(


1
PS मुझे अपने सर्वर की सार्वजनिक कुंजियों को निकालने और संग्रहीत करने के लिए इस जावा कोड को ऑनलाइन मिला, इसलिए googling रखें या रविवार तक प्रतीक्षा करें
ओसामा जावेद

0

SSLHandshakeException को 2 तरीकों से हल किया जा सकता है।

  1. एसएसएल को शामिल करना

    • एसएसएल प्राप्त करें (सोर्स सिस्टम एडमिनिस्ट्रेटर से पूछकर, ओपनसेल कमांड से भी डाउनलोड किया जा सकता है, या कोई भी ब्राउज़र सर्टिफिकेट डाउनलोड करता है)

    • JRE / lib / Security में स्थित Truststore (cacerts) में प्रमाणपत्र जोड़ें

    • vm तर्कों के रूप में ट्रस्टस्टोर स्थान प्रदान करें "-Djavax.net.ssl.trustStore ="

  2. एसएसएल की अनदेखी

    : इस # 2 के लिए, कृपया एक और stackoverflow वेबसाइट पर मेरे दूसरे जवाब पर जाएँ कैसे ingore एसएसएल सत्यापन करने पर ध्यान न दें जावा के साथ SSL प्रमाणपत्र त्रुटियाँ


-8

अब मैंने इस मुद्दे को इस तरह हल किया,

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.OutputStream;
// Create a trust manager that does not validate certificate chains like the 
default TrustManager[] trustAllCerts = new TrustManager[] {
    new X509TrustManager() {
        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return null;
        }
        public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) {
            //No need to implement. 
        }
        public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) {
            //No need to implement. 
        }
    }
};
// Install the all-trusting trust manager
try {
    SSLContext sc = SSLContext.getInstance("SSL");
    sc.init(null, trustAllCerts, new java.security.SecureRandom());
    HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (Exception e) {
    System.out.println(e);
}

4
'लागू करने की आवश्यकता नहीं' पूरी तरह से और पूरी तरह से गलत है। आपने अभी-अभी अपना SSL कनेक्शन असुरक्षित बनाया है। यह मत करो।
लोर्न
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.