2010-06-22 6 views
27

मैं जावा के साथ एसएसएल के माध्यम से अपने सर्वर में से किसी एक से कनेक्ट करने का प्रयास कर रहा हूं। मैंने कोशिश की विकल्पों में से एक बहुत यहाँ मेरी सबसे अच्छी कोशिश है:प्रमाणपत्र अपवाद: ssl.someUrl.de से मेल खाने वाला कोई नाम नहीं मिला

मैं उत्पन्न recommendet स्क्रिप्ट के साथ एक jssecacerts: http://blogs.oracle.com/andreas/resource/InstallCert.java कमांड के साथ : जावा InstallCert ssl.someUrl.de

मैं आदेश एक किया changeit इस के बाद दूसरी बार:

Loading KeyStore jssecacerts... 
Opening connection to ssl.someUrl.de:443... 
Starting SSL handshake... 

No errors, certificate is already trusted 

Server sent 1 certificate(s): 

1 Subject [email protected], CN=plesk, OU=Plesk, O=Parallels, L=Hernd 
on, ST=Virginia, C=US 
    Issuer [email protected], CN=plesk, OU=Plesk, O=Parallels, L=Hernd 
on, ST=Virginia, C=US 
    sha1 f1 0d 2c 54 05 e1 32 19 a0 52 5e e1 81 6c a3 a5 83 0d dd 67 
    md5  f0 b3 be 5e 5f 6e 90 d1 bc 57 7a b2 81 ce 7d 3d 

Enter certificate to add to trusted keystore or 'q' to quit: [1] 

मैं डिफ़ॉल्ट निर्देशिका पर फ़ाइल की प्रतिलिपि और मैं जावा trustStore में प्रमाण पत्र लोड

System.setProperty("javax.net.ssl.trustStore", "C:\\Program Files (x86)\\Java\\jre6\\lib\\security\\jssecacerts"); 
System.setProperty("javax.net.ssl.trustStorePassword","changeit"); 

तब मैं

URL url = new URL("https://ssl.someUrl.de/"); 
URLConnection conn = url.openConnection(); 
BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); 

कनेक्ट करने का प्रयास और मैं 3 लाइन पर त्रुटि मिलती है: (कोई नाम ssl.someUrl.de मिलान पाया)

javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No name matching ssl.someUrl.de found 

डिफ़ॉल्ट Plesk प्रमाण पत्र की इस कारण है या है कुछ और गलत है?

सेटअप: JRE 6.20, Netbeans 6.8, Windows 7 64 बिट

उत्तर

39

यह सर्वर आप अपने होस्ट नाम से मेल नहीं खाता से कनेक्ट करने की कोशिश कर रहे का प्रमाण पत्र की तरह दिखता है।

जब कोई HTTPS क्लाइंट किसी सर्वर से कनेक्ट होता है, तो यह सत्यापित करता है कि प्रमाणपत्र में होस्टनाम सर्वर के होस्टनाम से मेल खाता है। सर्टिफिकेट पर भरोसा करने के लिए पर्याप्त नहीं है, इसे उस सर्वर से मेल खाना पड़ेगा जिसे आप भी बात करना चाहते हैं। (एक समानता के रूप में, भले ही आप पासपोर्ट पर वैध होने पर भरोसा करते हैं, फिर भी आपको यह जांचना होगा कि वह व्यक्ति है जिसके लिए आप बात करना चाहते हैं, न केवल किसी भी पासपोर्ट पर आप वैध होने पर विश्वास करेंगे।)

इन HTTP, यह जांचकर किया जाता है कि:

  • प्रमाणपत्र में एक DNS विषय वैकल्पिक नाम (यह एक मानक विस्तार है) प्रविष्टि होस्टनाम से मेल खाता है;

  • विफल रहा है कि, आपके विषय का अंतिम सीएन विशिष्ट नाम (यह मुख्य नाम है यदि आप चाहते हैं) होस्टनाम से मेल खाता है। (RFC 2818. देखें)

यह बताने के लिए प्रमाण पत्र (होने हालांकि, अगर आप और आपके ब्राउज़र के साथ कनेक्ट और अधिक विवरण में अपनी सामग्री की जाँच करें, आप को देखने के लिए सक्षम होना चाहिए बिना क्या विषय वैकल्पिक नाम है मुश्किल है । यह) विषय विशिष्ट नाम हो रहा है:

[email protected], CN=plesk, OU=Plesk, O=Parallels, L=Herndon, ST=Virginia, C=US 

(यह इस प्रकार यदि आप के साथ एक विषय वैकल्पिक नाम नहीं है, सीएन = ssl.someUrl.de बजाय सीएन = Plesk करने की आवश्यकता होगी DNS: ssl.someUrl.de पहले से ही; मेरा अनुमान है कि आप नहीं करते हैं।)

आप HttpsURLConnection.setHostnameVerifier(..) का उपयोग कर होस्ट नाम सत्यापन को बाईपास करने में सक्षम हो सकते हैं। एक कस्टम होस्टनाम सत्यापनकर्ता लिखना बहुत कठिन नहीं होना चाहिए जो सत्यापन को बाध्य करता है, हालांकि मैं केवल तभी ऐसा करने का सुझाव दूंगा जब प्रमाण पत्र विशेष रूप से संबंधित है। आपको SSLSession तर्क और इसकी getPeerCertificates() विधि का उपयोग करके प्राप्त करने में सक्षम होना चाहिए।

(इसके अलावा, आप javax.net.ssl ​​स्थापित करने के लिए जिस तरह से आप यह किया है, जब से तुम मूलभूत मूल्यों वैसे भी प्रयोग कर रहे हैं की आवश्यकता नहीं है। * गुण।)

वैकल्पिक रूप से, अगर आपके द्वारा कनेक्ट किए जा रहे सर्वर और उसके प्रमाणपत्र पर आपका नियंत्रण है, आप इसका प्रमाण पत्र बना सकते हैं जो ऊपर नामकरण नियमों से मेल खाता है (सीएन पर्याप्त होना चाहिए, हालांकि विषय वैकल्पिक नाम एक सुधार है)। यदि आपके द्वारा निर्दिष्ट नाम के लिए एक स्व-हस्ताक्षरित प्रमाणपत्र पर्याप्त है, तो सुनिश्चित करें कि उसका सामान्य नाम (सीएन) वह होस्ट नाम है जिसे आप बात करने का प्रयास कर रहे हैं (कोई पूरा यूआरएल नहीं, सिर्फ होस्टनाम)।

+0

thx मैंने इसे होस्टनाम सत्यापनकर्ता के साथ किया था। मुझे बस एक गुप्त कनेक्शन की जरूरत है। एक निश्चित एचटीटीएस: // एड्रेस के साथ केवल एक ग्राहक और एक सर्वर है। – fehrlich

+1

याद रखें कि सुरक्षा प्रदान करने के लिए आपको * एन्क्रिप्शन के पहचान सत्यापन के कुछ रूप की आवश्यकता है। अन्यथा, यह किसी ऐसे व्यक्ति के साथ रहस्यों का आदान-प्रदान करने जैसा है जिसे आप नहीं जानते: हालांकि गुप्त गोपनीयता विधि अच्छी है, जो वास्तव में आपकी रक्षा नहीं करती है। – Bruno

+0

लेकिन मुझे सर्वर और एकमात्र क्लाइंट (जो मेरे कंप्यूटर पर है) पता है और कोई भी डेटा की स्ट्रीम को पढ़ नहीं सकता है। और https पृष्ठ को एक सरल htaccess से भी संरक्षित किया जाता है। या क्या मुझे यह गलत लगता है? – fehrlich

3

मैं एक अच्छा संकल्प यहाँ मिल गया है: http://www.mkyong.com/webservices/jax-ws/java-security-cert-certificateexception-no-name-matching-localhost-found/

लेकिन मेरी समस्या थोड़ा अलग था और इसे दूसरे तरीके से हल किया।

वेब सेवा दूरस्थ होस्ट पर थी। उदाहरण के लिए: https://some.remote.host/MyWebService?wsdl

लेकिन यह केवल किसी भी ग्राहक के लिए आईपी द्वारा उपलब्ध था, लेकिन प्रमाणपत्र डोमेन के लिए बनाया गया था: some.remote.host (CN = some.remote.host)। और इस डोमेन को आईपी द्वारा हल नहीं किया जा सकता है क्योंकि यह DNS में प्रस्तुत नहीं किया गया है)।

तो वही समस्या दिखाई दी: यदि मैं एसएसएल द्वारा वेब सेवा से कनेक्ट करने के लिए आईपी का उपयोग करता हूं, तो यह प्रमाण पत्र सीएन = some.remote.host के रूप में नहीं पहुंचा जा सकता है और यह निर्दिष्ट होस्ट नाम के बराबर नहीं है (यानी मेजबान आईपी)।

मैंने इस होस्टनाम से आईपी/etc/hosts फ़ाइल में मिलान करके इसे हल किया है। समस्या तय की गई थी।

लेकिन जब स्थानीय सेवा स्थानीयहोस्ट ऐप सर्वर पर होस्ट की जाती है, तो ऐसा लगता है कि इसे अपने लेख में वर्णित मैकॉन्ग की तरह हल किया जाना चाहिए।

1

सर्वर नाम प्रथम/उपनाम है जो आप करते हुए प्रमाणपत्र बना दे के रूप में ही किया जाना चाहिए

15

जावा 8 में आप सर्वर नाम निम्न कोड के साथ की जाँच को छोड़ सकते हैं:

HttpsURLConnection.setDefaultHostnameVerifier ((hostname, session) -> true); 

हालांकि इस केवल विकास में इस्तेमाल किया जाना चाहिए!

+0

महान, धन्यवाद। यहां और अधिक सहायता: http://www.mkyong.com/webservices/jax-ws/java-security-cert-certificateexception-no-name-matching-localhost-found/ – OhadR

7

मैंने एक विधि fixUntrustCertificate() बनाया है, इसलिए जब मैं किसी ऐसे डोमेन से निपट रहा हूं जो विश्वसनीय CA में नहीं है, तो आप अनुरोध से पहले विधि का आह्वान कर सकते हैं। यह कोड java1.4 के बाद काम करेगा। यह विधि सभी होस्टों के लिए लागू होती है:

public void fixUntrustCertificate() throws KeyManagementException, NoSuchAlgorithmException{ 


     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) { 
       } 

      } 
     }; 

     SSLContext sc = SSLContext.getInstance("SSL"); 
     sc.init(null, trustAllCerts, new java.security.SecureRandom()); 
     HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); 

     HostnameVerifier allHostsValid = new HostnameVerifier() { 
      public boolean verify(String hostname, SSLSession session) { 
       return true; 
      } 
     }; 

     // set the allTrusting verifier 
     HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid); 
} 
संबंधित मुद्दे