2017-07-05 14 views
5

के स्वचालित या उपयोगकर्ता चयन के साथ अनुरोध करें मैं एक हाइब्रिड कॉर्डोवा ऐप विकसित कर रहा हूं जो विभिन्न सर्वर से कनेक्ट हो सकता है। उनमें से कुछ को क्लाइंट प्रमाण पत्र की आवश्यकता होती है।उचित क्लाइंट प्रमाणपत्र

एंड्रॉइड मोबाइल पर संबंधित रूट प्रमाणपत्र + क्लाइंट प्रमाणपत्र स्थापित है।

क्रोम ब्राउज़र पर मुझे वेब कनेक्शन के लिए संबंधित क्लाइंट प्रमाणपत्र चुनने के लिए निम्न संवाद मिलता है।

Choose certificate on Chrome

कॉर्डोबा प्लगइन cordova-client-cert-authentication एक ही संवाद http (s) WebView भीतर अनुरोधों के लिए पॉप-अप होने के साथ

मेरे सवाल यह है कि स्पष्ट रूप से इसी क्लाइंट प्रमाणपत्र की घोषणा के बिना देशी Android मंच पर (रों) अनुरोध Http पर एक स्वत: प्रमाणपत्र चयन प्राप्त करने के लिए है। या क्या क्रोम पर लागू किए गए प्रमाणपत्र के उपयोगकर्ता चयन के समान कुछ है?

यह वर्तमान कार्यान्वयन है, जो एक हाथ मिलाना अपवाद फेंकता है:

try { 
    URL url = new URL(versionUrl); 
    HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection(); 

    urlConnection.setConnectTimeout(10000); 

    InputStream in = urlConnection.getInputStream(); 
} 
catch(Exception e) 
{ 
    //javax.net.ssl.SSLHandshakeException: Handshake failed 
} 
+1

क्या आप पहले एंड्रॉइड कीचेन (सिस्टम कुंजी स्टोर) में स्थापित प्रमाणपत्र का उपयोग करना चाहते हैं या आप सीधे 'HttpsURLConnection' को प्रमाण पत्र प्रदान करना चाहते हैं? – pedrofb

+0

मैं कुंजीChain से पहले स्थापित प्रमाणपत्र का उपयोग करना चाहता हूं। यह क्रेडेंशियल उपयोग "वीपीएन और ऐप्स" – kerosene

उत्तर

-1

अपने यूआरएल विकास के चरण (नहीं उत्पादन संस्करण), तो आप छोड़ सकते हैं उन एसएसएल/गैर-SSL प्रमाणपत्र का उपयोग करने के लिए स्थापित करने में अब भी कर रहे हैं यूआरएल

एसएसएल सत्यापन को छोड़ने का तरीका यहां दिया गया है: कॉल करें() या URL तक पहुंचने से पहले आपकी आवश्यकता कहां कॉल करें।

public static void skipSSLValidation() { 
     try { 
      TrustManager[] trustAllCerts = new TrustManager[]{ 
        new X509TrustManager() { 
         public X509Certificate[] getAcceptedIssuers() { 
        /* Create a new array with room for an additional trusted certificate. */ 
          return new X509Certificate[0]; 
         } 

         @Override 
         public void checkClientTrusted(X509Certificate[] certs, String authType) { 
         } 

         @Override 
         public void checkServerTrusted(X509Certificate[] certs, String authType) { 
         } 
        } 
      }; 

      SSLContext sc = SSLContext.getInstance("SSL"); 
      sc.init(null, trustAllCerts, new SecureRandom()); 
      HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); 
      HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() { 
       @Override 
       public boolean verify(String arg0, SSLSession arg1) { 
        return true; 
       } 
      }); 
     } catch (Exception e) { 
      // pass 
     } 
    } 

नोट: यदि आपके HTTPS URL मान्य हैं, तो आपको सर्वर से जेनरेट किए गए प्रमाणपत्रों का उपयोग करने की आवश्यकता नहीं होगी। आपको केवल इस विधि का परीक्षण/विकास के लिए उपयोग करना चाहिए। रिलीज/उत्पादन के लिए आपको इस विधि का उपयोग करने की आवश्यकता नहीं है।

+1

के साथ स्थापित किया गया था यह समाधान मान्य नहीं है। सर्वर प्रमाणपत्र का सत्यापन छोड़ने का अर्थ है कि क्लाइंट किसी प्रमाण पत्र पर भरोसा करेगा, लेकिन सर्वर को अभी भी आवश्यकता है कि क्लाइंट प्रमाणीकरण के लिए प्रमाण पत्र प्रस्तुत करता है। – pedrofb

3

आप कॉन्फ़िगर करने के लिए SSLContext द्वारा URLConnection

प्रमाण पत्र एक उपनाम है कि आप की जरूरत द्वारा संदर्भित है इस्तेमाल किया पहले से एंड्रॉयड चाबी का गुच्छा (सिस्टम कुंजी संग्रह) में स्थापित एक प्रमाण पत्र X509ExtendedKeyManager का विस्तार कर सकते हैं। एक संवाद क्रोम उपयोग के लिए इसी तरह के साथ चयन के लिए उपयोगकर्ता संकेत करने के लिए:

KeyChain.choosePrivateKeyAlias(this, this, // Callback 
      new String[] {"RSA", "DSA"}, // Any key types. 
      null, // Any issuers. 
      null, // Any host 
      -1, // Any port 
      DEFAULT_ALIAS); 

यह एक कस्टम KeyManager का उपयोग कर SSL कनेक्शन कॉन्फ़िगर करने के लिए कोड है। यह डिफ़ॉल्ट TrustManager और HostnameVerifier का उपयोग करता है। यदि सर्वर एक आत्म हस्ताक्षरित प्रमाणपत्र एंड्रॉयड डिफ़ॉल्ट truststore में मौजूद नहीं है का उपयोग कर आप उन्हें कॉन्फ़िगर करने की आवश्यकता होगी (सभी प्रमाणपत्र पर भरोसा करने की सिफारिश की है नहीं)

//Configure trustManager if needed 
TrustManager[] trustManagers = null; 

//Configure keyManager to select the private key and the certificate chain from KeyChain 
KeyManager keyManager = KeyChainKeyManager.fromAlias(
      context, mClientCertAlias); 

//Configure SSLContext 
SSLContext sslContext = SSLContext.getInstance("TLS"); 
sslContext.init(new KeyManager[] {keyManager}, trustManagers, null); 


//Perform the connection 
URL url = new URL(versionUrl); 
HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection(); 
urlConnection.setSSLSocketFactory(sslContext.getSocketFactory()); 
//urlConnection.setHostnameVerifier(hostnameVerifier); //Configure hostnameVerifier if needed 
urlConnection.setConnectTimeout(10000); 
InputStream in = urlConnection.getInputStream(); 

अंत में यहाँ आप और कस्टम X509ExtendedKeyManager से निकाले का एक पूरा कार्यान्वयन here और here जो क्लाइंट प्रमाणपत्र का चयन करने का प्रभारी है। मैंने आवश्यक कोड निकाला है।

public static class KeyChainKeyManager extends X509ExtendedKeyManager { 
    private final String mClientAlias; 
    private final X509Certificate[] mCertificateChain; 
    private final PrivateKey mPrivateKey; 

     /** 
     * Builds an instance of a KeyChainKeyManager using the given certificate alias. 
     * If for any reason retrieval of the credentials from the system {@link android.security.KeyChain} fails, 
     * a {@code null} value will be returned. 
     */ 
     public static KeyChainKeyManager fromAlias(Context context, String alias) 
       throws CertificateException { 
      X509Certificate[] certificateChain; 
      try { 
       certificateChain = KeyChain.getCertificateChain(context, alias); 
      } catch (KeyChainException e) { 
       throw new CertificateException(e); 
      } catch (InterruptedException e) { 
       throw new CertificateException(e); 
      } 

      PrivateKey privateKey; 
      try { 
       privateKey = KeyChain.getPrivateKey(context, alias); 
      } catch (KeyChainException e) { 
       throw new CertificateException(e); 
      } catch (InterruptedException e) { 
       throw new CertificateException(e); 
      } 

      if (certificateChain == null || privateKey == null) { 
       throw new CertificateException("Can't access certificate from keystore"); 
      } 

      return new KeyChainKeyManager(alias, certificateChain, privateKey); 
     } 

     private KeyChainKeyManager(
       String clientAlias, X509Certificate[] certificateChain, PrivateKey privateKey) { 
      mClientAlias = clientAlias; 
      mCertificateChain = certificateChain; 
      mPrivateKey = privateKey; 
     } 


     @Override 
     public String chooseClientAlias(String[] keyTypes, Principal[] issuers, Socket socket) { 
      return mClientAlias; 
     } 

     @Override 
     public X509Certificate[] getCertificateChain(String alias) { 
      return mCertificateChain; 
     } 

     @Override 
     public PrivateKey getPrivateKey(String alias) { 
      return mPrivateKey; 
     } 

     @Override 
     public final String chooseServerAlias(String keyType, Principal[] issuers, Socket socket) { 
      // not a client SSLSocket callback 
      throw new UnsupportedOperationException(); 
     } 

     @Override 
     public final String[] getClientAliases(String keyType, Principal[] issuers) { 
      // not a client SSLSocket callback 
      throw new UnsupportedOperationException(); 
     } 

     @Override 
     public final String[] getServerAliases(String keyType, Principal[] issuers) { 
      // not a client SSLSocket callback 
      throw new UnsupportedOperationException(); 
     } 
    } 
} 

मैंने इसका परीक्षण नहीं किया। किसी भी त्रुटि की रिपोर्ट करें!

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