2012-08-23 23 views
13

अपाचे HttpClient 4.2.1 का उपयोग करना। प्रपत्र आधारित प्रवेश उदाहरणअपाचे HTTP क्लाइंट SSLPeerUnverifiedException

http://hc.apache.org/httpcomponents-client-ga/examples.html

जब एक SSL संरक्षित लॉगिन प्रपत्र तक पहुँचने मैं एक अपवाद मिल से नकल कोड का उपयोग करना:

Getting library items from https://appserver.gtportalbase.com/agileBase/AppController.servlet?return=blank 
javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated 
Closing http connection 
at sun.security.ssl.SSLSessionImpl.getPeerCertificates(SSLSessionImpl.java:397) 
at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:128) 
at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:572) 
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:180) 
at org.apache.http.impl.conn.ManagedClientConnectionImpl.open(ManagedClientConnectionImpl.java:294) 
at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:640) 
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:479) 
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906) 
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:805) 
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:784) 

प्रमाणपत्र जहाँ तक मैं बता सकता हूँ ठीक है (देखें स्टैक ट्रेस से पहले यूआरएल), समाप्त नहीं हुआ - ब्राउज़र शिकायत नहीं करते हैं।

मैं अपने कुंजीस्टोर एक ला

How to handle invalid SSL certificates with Apache HttpClient?

कोई परिवर्तन नहीं होता

में प्रमाणपत्र आयात करने की कोशिश की है। मेरा मानना ​​है कि आप त्रुटि को अनदेखा करने के लिए जावा को मजबूर करने के लिए एक कस्टम SSLContext बना सकते हैं, लेकिन मैं मूल कारण को ठीक करना चाहता हूं क्योंकि मैं कोई सुरक्षा छेद खोलना नहीं चाहता हूं।

कोई विचार?

उत्तर

20

EDIT मुझे एहसास है कि यह उत्तर बहुत समय पहले स्वीकार किया गया था और इसे 3 बार भी बढ़ा दिया गया है, लेकिन यह (कम से कम आंशिक रूप से) गलत था, इसलिए यहां इस अपवाद के बारे में कुछ और है। असुविधा के लिए क्षमा याचना।

javax.net.ssl.SSLPeerUnverifiedException:

यह आमतौर पर एक अपवाद फेंका जब दूरस्थ सर्वर ने ऐसा प्रमाणपत्र बिल्कुल नहीं भेजा है प्रमाणीकृत नहीं सहकर्मी। हालांकि, एक एज केस है, जिसे अपाचे HTTP क्लाइंट का उपयोग करते समय सामना किया जाता है, जिस तरह से इसे इस संस्करण में लागू किया गया था, और जिस तरह से sun.security. ssl.SSLSocketImpl.getSession() लागू किया गया था।

अपाचे HTTP क्लाइंट का उपयोग करते समय, यह अपवाद भी फेंक दिया जाएगा जब रिमोट प्रमाणपत्र विश्वसनीय नहीं है, जो अक्सर "sun.security.validator.ValidatorException: PKIX path building failed" फेंक देगा।

ऐसा होने का कारण यह है क्योंकि अपाचे HTTP क्लाइंट SSLSession और कुछ और करने से पहले सहकर्मी प्रमाणपत्र प्राप्त करने का प्रयास करता है।

बस एक चेतावनी के रूप में, वहाँ 3 ways of initiating the handshake with an SSLSocket हैं:

  • startHandshake जो स्पष्ट रूप से हाथ मिलाने शुरू होता है, या
  • किसी भी इस सॉकेट एक अंतर्निहित हाथ मिलाना का कारण बनता है पर आवेदन डेटा पढ़ने या लिखने का प्रयास बुला, या
  • प्राप्त करने के लिए कॉल सत्र सत्र स्थापित करने का प्रयास करता है यदि वर्तमान में कोई वैध सत्र नहीं है, और एक निहित हैंडशेक किया जाता है।

यहाँ 3 उदाहरण हैं, कि सभी विश्वसनीय नहीं है एक प्रमाण पत्र के साथ एक मेजबान के खिलाफ हैं (javax.net.ssl.SSLSocketFactory का उपयोग कर, नहीं अपाचे एक)।

उदाहरण 1:

SSLSocketFactory ssf = (SSLSocketFactory) sslContext.getSocketFactory(); 
    SSLSocket sslSocket = (SSLSocket) ssf.createSocket("untrusted.host.example", 
      443); 
    sslSocket.startHandshake(); 

यह (उम्मीद के रूप में) फेंकता "javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed"।

उदाहरण 2:

SSLSocketFactory ssf = (SSLSocketFactory) sslContext.getSocketFactory(); 
    SSLSocket sslSocket = (SSLSocket) ssf.createSocket("untrusted.host.example", 
      443); 
    sslSocket.getInputStream().read(); 

यह भी (उम्मीद के रूप में) फेंकता "javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed"।

उदाहरण 3:

SSLSocketFactory ssf = (SSLSocketFactory) sslContext.getSocketFactory(); 
    SSLSocket sslSocket = (SSLSocket) ssf.createSocket("untrusted.host.example", 
      443); 
    SSLSession sslSession = sslSocket.getSession(); 
    sslSession.getPeerCertificates(); 

लेकिन यह फेंकता javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated

यह तर्क Apache HTTP Client's AbstractVerifier में लागू किया गया है जो संस्करण 4.2.1 में org.apache.http.conn.ssl.SSLSocketFactory द्वारा उपयोग किया गया है। issue HTTPCLIENT-1346 में रिपोर्ट के आधार पर बाद के संस्करण make an explicit call to startHandshake()

अंततः इसे आगे फेंक बिना, sun.security. ssl.SSLSocketImpl.getSession() के कार्यान्वयन, जो पकड़ता संभावित IOException रों फेंक दिया जब startHandshake(false) (आंतरिक विधि) को कॉल करने से आने के लिए लगता है। यह एक बग हो सकता है, हालांकि इसका कोई बड़ा सुरक्षा प्रभाव नहीं होना चाहिए, क्योंकि SSLSocket अभी भी बंद हो जाएगा।

उदाहरण 4:

SSLSocketFactory ssf = (SSLSocketFactory) sslContext.getSocketFactory(); 
    SSLSocket sslSocket = (SSLSocket) ssf.createSocket("untrusted.host.example", 
      443); 
    SSLSession sslSession = sslSocket.getSession(); 
    // sslSession.getPeerCertificates(); 
    sslSocket.getInputStream().read(); 

शुक्र है, यह अभी भी "javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed" जब भी आप वास्तव में उपयोग करने के लिए है कि SSLSocket (कोई उपाय बता सहकर्मी प्रमाण पत्र प्राप्त किए बिना सत्र हो रही द्वारा वहाँ) की कोशिश फेंक देंगे।


इस

प्रमाणपत्र के साथ किसी अन्य मुद्दा यह है कि भरोसा नहीं कर रहे हैं की तरह ठीक करने के लिए कैसे, यह (यकीन है कि विश्वास की दुकान आप उपयोग कर रहे आवश्यक विश्वास एंकर होता है बनाने के एक मामले यानी सीए है प्रमाण पत्र जो उस श्रृंखला को जारी करते हैं जिसे आप सत्यापित करने का प्रयास कर रहे हैं, या संभवतः असाधारण मामलों के लिए वास्तविक सर्वर प्रमाण पत्र)।

इसे ठीक करने के लिए, आपको अपने ट्रस्ट स्टोर में CA प्रमाणपत्र (या संभवतः सर्वर प्रमाणपत्र स्वयं) आयात करना चाहिए।

  • अपने JRE विश्वास की दुकान में आमतौर पर cacerts फ़ाइल (जरूरी है कि सबसे अच्छा नहीं है, क्योंकि है कि JRE का उपयोग कर सभी आवेदनों को प्रभावित करती है)
  • आपके विश्वास की दुकान की एक स्थानीय प्रति में,,: आप यह कर सकते हैं (जिसे आप -Djavax.net.ssl.trustStore=... विकल्पों का उपयोग करके कॉन्फ़िगर कर सकते हैं),
  • उस कनेक्शन के लिए विशिष्ट SSLContext बनाकर (जैसा कि this answer में वर्णित है)। (कुछ एक ट्रस्ट प्रबंधक है कि कुछ नहीं करता है का उपयोग करने के लिए सुझाव है, लेकिन इससे आपकी कनेक्शन MITM हमलों के लिए असुरक्षित हो जाएगा।)

प्रारंभिक जवाब

javax.net.ssl।SSLPeerUnverifiedException: प्रमाणीकृत सहकर्मी नहीं

यह भरोसा प्रमाण पत्र या आप एक कस्टम SSLContext बनाने के लिए होने के साथ कोई संबंध नहीं है: इस तथ्य यह है कि सर्वर किसी भी प्रमाण पत्र नहीं भेज रहा है के कारण है।

यह सर्वर स्पष्ट रूप से टीएलएस का समर्थन करने के लिए कॉन्फ़िगर नहीं किया गया है। यह विफल रहता है (यदि आप किसी दूरस्थ प्रमाण पत्र नहीं मिलेगा):

openssl s_client -tls1 -showcerts -connect appserver.gtportalbase.com:443 

हालांकि, SSLv3 काम करने के लिए लगता है:

openssl s_client -ssl3 -showcerts -connect appserver.gtportalbase.com:443 

क्या आप जानते हैं जो इस सर्वर चल रहा है, इस समस्या को ठीक करने के लिए उनसे संपर्क करने लायक होगा। सर्वर को कम से कम आजकल टीएलएसवी 1 का समर्थन करना चाहिए।

इस बीच, इस समस्या को ठीक करने का एक तरीका आपके org.apache.http.conn.ssl.SSLSocketFactory बनाना होगा और अपाचे एचटीपी क्लाइंट के साथ इस कनेक्शन के लिए इसका उपयोग करना होगा।

इस कारखाने को सामान्य रूप से SSLSocket बनाने की आवश्यकता होगी, उस सॉकेट को वापस करने से पहले sslSocket.setEnabledProtocols(new String[] {"SSLv3"}); का उपयोग करें, टीएलएस को अक्षम करने के लिए, जो अन्यथा डिफ़ॉल्ट रूप से सक्षम होगा।

+0

हम्म, मुझे दोनों के साथ एक दूरस्थ प्रमाणपत्र मिलता है। कुछ अलग-अलग ग्राहकों से प्रयास करेंगे –

+0

ओएसएक्स से, दोनों काम, लिनक्स से, केवल एसएसएल 3। सर्वर कॉन्फ़िगरेशन में देखेंगे। –

+0

यह सिफर सुइट्स के साथ कुछ करने के लिए हो सकता है। आपके ओएसएक्स क्लाइंट पर, क्या आपके लिनक्स क्लाइंट के रूप में 'openssl ciphers DEFAULT' में एक ही सिफर सुइट्स है? कुछ जो ओएसएक्स सूची में होंगे लेकिन लिनक्स पर नहीं? – Bruno

0

एक कस्टम संदर्भ बनाएं ताकि आप लॉग इन कर सकें कि प्रमाणपत्र क्यों अमान्य है। या बस इसमें डीबग करें।

संबंधित मुद्दे