2013-10-17 2 views
9

J'ai une application android qui se connecte à un service Web SSL que nous hébergeons. Le serveur Web est apache et possède sa propre autorité de certification que nous avons créée et un certificat SSL auto-signé. J'ai importé notre certificat d'autorité de certification sur la tablette Android dans la section Certificats approuvés de l'utilisateur dans la section Sécurité.Android SSL HTTP Request utilisant le certificat auto-signé et CA

J'ai testé l'accès au serveur Web et peut confirmer que le certificat de service Web affiche comme valide (capture d'écran ci-dessous)

Valid certificate

Voici le certificat dans les paramètres de sécurité:

Trusted certificate Maintenant, lorsque j'essaie d'accéder au service Web dans mon application, l'exception "No Peer Certificate" est déclenchée.

Ceci est la mise en œuvre de SSL simplifiée:

public class MainActivity extends Activity { 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    // allows network on main thread (temp hack) 
    StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); 
    StrictMode.setThreadPolicy(policy); 

    SchemeRegistry schemeRegistry = new SchemeRegistry(); 
    //schemeRegistry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443)); 
    schemeRegistry.register(new Scheme("https", newSSLSocketFactory(), 443)); 


    HttpParams params = new BasicHttpParams(); 

    SingleClientConnManager mgr = new SingleClientConnManager(params, schemeRegistry); 

    HttpClient client = new DefaultHttpClient(mgr, params); 

    HttpPost httpRequest = new HttpPost("https://our-web-service.com"); 

    try { 
     client.execute(httpRequest); 
    } catch (Exception e) { 
     e.printStackTrace(); // 
    } 
} 

/* 
* Standard SSL CA Store Setup // 
*/ 
private SSLSocketFactory newSSLSocketFactory() { 

    KeyStore trusted; 

    try { 
     trusted = KeyStore.getInstance("AndroidCAStore"); 
     trusted.load(null, null); 
     Enumeration<String> aliases = trusted.aliases(); 

     while (aliases.hasMoreElements()) { 
      String alias = aliases.nextElement(); 
      X509Certificate cert = (X509Certificate) trusted.getCertificate(alias); 
      Log.d("", "Alias="+alias); 
      Log.d("", "Subject DN: " + cert.getSubjectDN().getName()); 
      Log.d("", "Issuer DN: " + cert.getIssuerDN().getName()); 
     }  

     SSLSocketFactory sf = new SSLSocketFactory(trusted); 
     sf.setHostnameVerifier(SSLSocketFactory.STRICT_HOSTNAME_VERIFIER); 

     return sf; 

    } catch (Exception e) { 
     // TODO Auto-generated catch block 
     throw new AssertionError(e); 
    } 
} 

} 

La boucle while juste recrache les certificats et je peux voir mon propre CA dans les journaux. Mais je reçois toujours l'exception "No Peer Certificate".

10-17 18: 29: 01,234: I/System.out (4006): Aucun certificat pairs

Dois-je charger manuellement mon certificat de CA en quelque sorte dans cette mise en œuvre?

+0

Avez-vous essayé de charger manuellement votre certificat CA dans cette mise en œuvre? – BON

+0

Vous pouvez obtenir un certificat SSL gratuit et approuvé pour votre domaine à partir de http://www.startssl.com/ (je les utilise pour certaines applications). Vous n'avez donc pas besoin d'ajouter votre autorité de certification dans chaque appareil. qui veut utiliser votre application. –

Répondre

4

résolu en utilisant: HttpsURLConnection

URLConnection conn = null; 
URL url = new URL(strURL); 
conn = url.openConnection(); 
HttpsURLConnection httpsConn = (HttpsURLConnection) conn; 

Cela semble fonctionner très bien avec les certificats de CA installées par l'utilisateur.

2

Vous pouvez accomplir la tâche à l'aide aussi DefaultHttpClient, même si here is suggested à:

Préférez HttpURLConnection pour le nouveau code

Faites attention également à l'importation ou l'ajout d'un certificat à votre demande puisque vous pouvez avoir problèmes dans la mise à jour du certificat quand il expirera.

Voici comment obtenir un DefaultHttpClient faire confiance à un certificat auto-signé:

* This method returns the appropriate HttpClient. 
* @param isTLS Whether Transport Layer Security is required. 
* @param trustStoreInputStream The InputStream generated from the BKS keystore. 
* @param trustStorePsw The password related to the keystore. 
* @return The DefaultHttpClient object used to invoke execute(request) method. 
private DefaultHttpClient getHttpClient(boolean isTLS, InputStream trustStoreInputStream, String trustStorePsw) 
    throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, KeyManagementException, UnrecoverableKeyException { 
    DefaultHttpClient client = null;   
    SchemeRegistry schemeRegistry = new SchemeRegistry(); 
    Scheme http = new Scheme("http", PlainSocketFactory.getSocketFactory(), 8080); 
    schemeRegistry.register(http); 
    if(isTLS) { 
     KeyStore trustKeyStore = null; 
     char[] trustStorePswCharArray = null; 
     if(trustStorePsw!=null) { 
      trustStorePswCharArray = trustStorePsw.toCharArray(); 
     } 
     trustKeyStore = KeyStore.getInstance("BKS"); 
     trustKeyStore.load(trustStoreInputStream, trustStorePswCharArray); 
     SSLSocketFactory sslSocketFactory = null; 
     sslSocketFactory = new SSLSocketFactory(trustKeyStore); 
     Scheme https = new Scheme("https", sslSocketFactory, 8443); 
     schemeRegistry.register(https); 
    }     
    HttpParams httpParams = new BasicHttpParams(); 
    HttpConnectionParams.setConnectionTimeout(httpParams, CONNECTION_TIMEOUT); 
    HttpConnectionParams.setSoTimeout(httpParams, SOCKET_TIMEOUT);   
    ClientConnectionManager clientConnectionManager = new ThreadSafeClientConnManager(httpParams, schemeRegistry);   
    client = new DefaultHttpClient(clientConnectionManager, httpParams);   
    return client; 
} 

et ici comment obtenir un HttpsURLConnection:

* This method set the certificate for the HttpsURLConnection 
* @param url The url to contact. 
* @param certificateInputStream The InputStream generated from the .crt certificate. 
* @param certAlias The alias for the certificate. 
* @return The returned HttpsURLConnection 
private HttpsURLConnection getHttpsURLConnection(URL url, InputStream certificateInputStream, String certAlias) 
    throws CertificateException, IOException, KeyStoreException, NoSuchAlgorithmException, KeyManagementException { 
    HttpsURLConnection connection = null; 
    CertificateFactory certFactory = null; 
    Certificate cert = null; 
    KeyStore keyStore = null; 
    TrustManagerFactory tmFactory = null; 
    SSLContext sslContext = null; 
    // Load certificates from an InputStream 
    certFactory = CertificateFactory.getInstance("X.509"); 
    cert = certFactory.generateCertificate(certificateInputStream); 
    certificateInputStream.close(); 
    // Create a KeyStore containing the trusted certificates 
    keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); 
    keyStore.load(null, null); 
    keyStore.setCertificateEntry(certAlias, cert); 
    // Create a TrustManager that trusts the certificates in our KeyStore 
    tmFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); 
    tmFactory.init(keyStore); 
    // Create an SSLContext that uses our TrustManager 
    sslContext = SSLContext.getInstance("TLS"); 
    sslContext.init(null, tmFactory.getTrustManagers(), null); 
    connection = (HttpsURLConnection)url.openConnection(); 
    connection.setSSLSocketFactory(sslContext.getSocketFactory()); 
    return connection; 
} 
Questions connexes