2011-08-19 18 views
14

का उपयोग कर कनेक्शन, एक एक सर्वलेट/बिलाव सर्वर है, और अन्य एक Android ऐप्लिकेशन है।एंड्रॉयड: HTTPS (SSL) 2 क्षुधा है HttpsURLConnection

मैं दोनों के बीच एक्सएमएल भेजने और प्राप्त करने के लिए HttpURLConnection का उपयोग करना चाहता हूं।

कोड:

private String sendPostRequest(String requeststring) { 

    DataInputStream dis = null; 
    StringBuffer messagebuffer = new StringBuffer(); 

    HttpURLConnection urlConnection = null; 

    try { 
     URL url = new URL(this.getServerURL()); 

     urlConnection = (HttpURLConnection) url.openConnection();   

     urlConnection.setDoOutput(true); 

     urlConnection.setRequestMethod("POST"); 

     OutputStream out = new BufferedOutputStream(urlConnection.getOutputStream()); 

     out.write(requeststring.getBytes()); 

     out.flush(); 

     InputStream in = new BufferedInputStream(urlConnection.getInputStream()); 

     dis = new DataInputStream(in); 

     int ch; 

     long len = urlConnection.getContentLength(); 

     if (len != -1) { 

      for (int i = 0; i < len; i++) 

       if ((ch = dis.read()) != -1) { 

        messagebuffer.append((char) ch); 
       } 
     } else { 

      while ((ch = dis.read()) != -1) 
       messagebuffer.append((char) ch); 
     } 

     dis.close(); 

    } catch (Exception e) { 

     e.printStackTrace(); 

    } finally { 

     urlConnection.disconnect(); 
    } 

    return messagebuffer.toString(); 
} 

अब, मैं सुरक्षा के लिए XMLs भेजने के लिए SSL का उपयोग करने की जरूरत है।

सबसे पहले, मैं .keystore फ़ाइल उत्पन्न करने के लिए जावा कीटोल का उपयोग करता हूं।

Keytool -keygen -alias tomcat -keyalg RSA 

तब मैं बिलाव के server.xml फ़ाइल पर एक्सएमएल कोड डाल तो एसएसएल

<Connector 
port="8443" protocol="HTTP/1.1" SSLEnabled="true" 
maxThreads="150" scheme="https" secure="true" 
keystoreFile="c:/Documents and Settings/MyUser/.keystore" 
keystorePass="password" 
clientAuth="false" sslProtocol="TLS" 
/> 

उपयोग करने के लिए, मैं इसे HttpsURLConnection

private String sendPostRequest(String requeststring) { 

    DataInputStream dis = null; 
    StringBuffer messagebuffer = new StringBuffer(); 

    HttpURLConnection urlConnection = null; 

    //Conexion por HTTPS 
    HttpsURLConnection urlHttpsConnection = null; 

    try { 
     URL url = new URL(this.getServerURL()); 

     //urlConnection = (HttpURLConnection) url.openConnection();   

     //Si necesito usar HTTPS 
     if (url.getProtocol().toLowerCase().equals("https")) { 

      trustAllHosts(); 

      //Creo la Conexion 
      urlHttpsConnection = (HttpsURLConnection) url.openConnection(); 

      //Seteo la verificacion para que NO verifique nada!! 
      urlHttpsConnection.setHostnameVerifier(DO_NOT_VERIFY); 

      //Asigno a la otra variable para usar simpre la mism 
      urlConnection = urlHttpsConnection; 

     } else { 

      urlConnection = (HttpURLConnection) url.openConnection(); 
     } 

//Do the same like up 

के लिए HttpURLConnection बदल सकते हैं और एक trustAllHosts जोड़ने प्रत्येक सर्वर पर भरोसा करने के लिए विधि (किसी प्रमाण पत्र की जांच न करें)

private static void trustAllHosts() { 

    X509TrustManager easyTrustManager = new X509TrustManager() { 

     public void checkClientTrusted(
       X509Certificate[] chain, 
       String authType) throws CertificateException { 
      // Oh, I am easy! 
     } 

     public void checkServerTrusted(
       X509Certificate[] chain, 
       String authType) throws CertificateException { 
      // Oh, I am easy! 
     } 

     public X509Certificate[] getAcceptedIssuers() { 
      return null; 
     } 

    }; 

    // Create a trust manager that does not validate certificate chains 
    TrustManager[] trustAllCerts = new TrustManager[] {easyTrustManager}; 

    // Install the all-trusting trust manager 
    try { 
     SSLContext sc = SSLContext.getInstance("TLS"); 

     sc.init(null, trustAllCerts, new java.security.SecureRandom()); 

     HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); 

    } catch (Exception e) { 
      e.printStackTrace(); 
    } 
} 

ये वे परिवर्तन बहुत अच्छा काम किया है, लेकिन मैं नहीं है हर सर्वर पर भरोसा करना चाहते हैं। मैं कनेक्शन को प्रमाणित करने और सही तरीके से SSL का उपयोग करने के लिए अपनी कीस्टोर फ़ाइल का उपयोग करना चाहता हूं। मैं इंटरनेट पर एक बहुत पढ़ सकते हैं और परीक्षण का एक बहुत बनाया, लेकिन मुझे समझ में नहीं कर सकते मैं क्या करना है और कैसे यह करने के लिए क्या।

किसी ने मुझसे मदद कर सकते हैं?

तुम मेरे गरीब अंग्रेज़ी

------------------------- अद्यतन 2011/08 लिए बहुत-बहुत

क्षमा करें धन्यवाद/24 ------------------------------------------------ -

ठीक है, मैं अभी भी इस पर काम कर रहा हूँ। मैं एक नई विधि बनाया KeyStore, InputStream, आदि

विधि इस तरह दिखता है स्थापित करने के लिए:

private static void trustIFNetServer() { 

    try { 
     TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); 

     KeyStore ks = KeyStore.getInstance("BKS"); 

     InputStream in = context.getResources().openRawResource(R.raw.mykeystore); 

     String keyPassword = "password"; 

     ks.load(in, keyPassword.toCharArray()); 

     in.close(); 

     tmf.init(ks); 

     TrustManager[] tms = tmf.getTrustManagers();  

     SSLContext sc = SSLContext.getInstance("TLS"); 

    sc.init(null, tms, new java.security.SecureRandom()); 

    } catch (Exception e) { 
    e.printStackTrace(); 
    } 
} 

सबसे पहले मैं कुंजी और प्रमाणपत्र के साथ समस्याओं का एक बहुत कुछ था, लेकिन अब यह काम कर रहा है (मुझे ऐसा लगता है)

मेरी समस्या अभी एक टाइमऑट अपवाद है। मुझे नहीं पता कि यह क्यों उत्पन्न होता है। मुझे लगता है कि यह डेटा लिखने के साथ कुछ है, लेकिन मैं अभी तक हल नहीं कर सकता।

कोई आइडिया?

+0

आप एक प्रमाण पत्र एक प्रसिद्ध प्रमाणन प्राधिकारी के हस्ताक्षर का उपयोग कर रहे हैं या आप एक स्व-हस्ताक्षरित प्रमाणपत्र का उपयोग कर रहे हैं? –

उत्तर

6

आपको here वर्णित अनुसार अपने स्वयं के हस्ताक्षरित प्रमाणपत्र के लिए ट्रस्ट स्टोर फ़ाइल बनाने की आवश्यकता है। अपने सर्वर से कनेक्ट करने के लिए क्लाइंट साइड पर इसका इस्तेमाल करें। यह वास्तव में कोई फर्क नहीं पड़ता कि आप जेकेएस या किसी अन्य प्रारूप का उपयोग करते हैं, मैं अब जेकेएस मानूंगा।

क्या आपके मन में है आप एक अलग TrustManager की जरूरत है, स्पष्ट रूप से पूरा करने के लिए। आप TrustManagerFactory का उपयोग कर सकते हैं और अपने नए बनाए गए ट्रस्ट स्टोर के साथ अपनी ट्रस्ट सेटिंग खिला सकते हैं।

TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX"); 
KeyStore ks = KeyStore.getInstance("JKS"); 
FileInputStream in = new FileInputStream("<path to your key store>"); 
ks.load(in, "password".toCharArray()); 
in.close(); 
tmf.init(ks); 
TrustManager[] tms = tmf.getTrustManagers(); 

उपयोग tms init करने के लिए अपने SSLContext नया विश्वास सेटिंग बजाय के लिए अपने SSL/TLS कनेक्शन के लिए प्रयोग की जाने वाली।

आपको यह भी सुनिश्चित करना चाहिए कि सर्वर का CN हिस्सा TLS प्रमाणपत्र आपके सर्वर के FQDN (पूरी तरह से योग्य डोमेन नाम) के बराबर है, उदा। यदि आपके सर्वर आधार URL 'https://www.example.com' है, तो प्रमाण पत्र की CN होना चाहिए 'www.example.com'। होस्ट नाम सत्यापन के लिए यह आवश्यक है, एक ऐसी सुविधा जो मनुष्य-में-मध्य-हमलों को रोकती है। आप इसे अक्षम कर सकते हैं, लेकिन केवल यह उपयोग करते समय आपका कनेक्शन वास्तव में सुरक्षित होगा।

+0

मैं वह एंड्रॉयड ग्राहक की truststore ठीक से कॉन्फ़िगर करने की आवश्यकता है, नहीं सर्वर की। –

+0

आप बिल्कुल सही हैं - मैं इसे बदल दूंगा, धन्यवाद! – emboss

+0

सहायता के लिए धन्यवाद। मैं ये सब समझने और कुछ परीक्षण करने की कोशिश करूंगा। आपका बहुत बहुत धन्यवाद! –

0

अपनी ट्रस्ट स्टोर बनाएं, एक संपत्ति के रूप में स्टोर करें और इसका उपयोग इस SocketFactory को प्रारंभ करें। फिर अपने स्वयं के 'ट्रस्ट सबको' के बजाए कारखाने का उपयोग करें।

+0

धन्यवाद, क्या आपके पास कुछ उदाहरण है? –

+0

नहीं एक पूर्ण उदाहरण के लिए, लेकिन एक बार आप भरी हुई है आप की दुकान पर भरोसा (जो सर्वर प्रमाणपत्र शामिल हैं), बस पासवर्ड के साथ निर्माता के लिए इसे पारित। फिर आप परिणामस्वरूप 'सॉकेट फैक्ट्री' उदाहरण को 'HttpsURLConnection.setDefaultSSLSocketFactory() 'में पास कर सकते हैं। –

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