2010-05-19 5 views
2

J'ai quelques problèmes avec SSL utilisant httpclient sur android j'essaie d'accéder au certificat auto-signé dans les détails je veux que mon application fasse confiance à tous les certificats (je vais utiliser SSL uniquement pour le cryptage des données). D'abord, j'ai essayé d'utiliser ce guide http://hc.apache.org/httpclient-3.x/sslguide.html sur le bureau fonctionne très bien, mais sur Android, j'ai toujours javax.net.ssl.SSLException: Certificat de serveur non approuvé. Après avoir cherché dans google j'ai trouvé quelques autres exemples comment activer ssl.httpclient ssl certificat sur android

http://groups.google.com/group/android-developers/browse_thread/thread/62d856cdcfa9f16e - Travailler quand j'utilise URLConnection mais avec HttpClient toujours l'exception.

http://www.discursive.com/books/cjcook/reference/http-webdav-sect-self-signed.html - sur Desktop, l'utilisation des fichiers jar d'apache fonctionne, mais dans Android, l'utilisation des classes SDK ne fonctionne pas.

http://mail-archives.apache.org/mod_mbox/hc-httpclient-users/200808.mbox/%[email protected]%3E - aussi obtenir la même exception

donc des idées comment puis-je tous les certificats sur Android à l'aide HttpClient

+0

* « Je veux que mon application à tous les certificats ... » * - Très mauvaise idée. C'est carrément dangereux: [Le code le plus dangereux au monde: la validation des certificats SSL dans les logiciels sans navigateur] (http://www.cs.utexas.edu/~shmat/shmat_ccs12.pdf). – jww

Répondre

9

Si vous arrive de regarder le code de DefaultHttpClient, il ressemble à ceci:

@Override 
    protected ClientConnectionManager createClientConnectionManager() { 
     SchemeRegistry registry = new SchemeRegistry(); 
     registry.register(
       new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); 
     registry.register(
       new Scheme("https", SSLSocketFactory.getSocketFactory(), 443)); 

     ClientConnectionManager connManager = null;  
     HttpParams params = getParams(); 
     ... 
    } 

Notez le mappage du schéma https à org.apache.http.conn.ssl.SSLSocketFactory.getSocketFactory().

Vous pouvez créer une implémentation personnalisée pour l'interface org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory (http://hc.apache.org/httpclient-3.x/apidocs/org/apache/commons/httpclient/protocol/SecureProtocolSocketFactory.html) dans laquelle, vous pouvez créer java.net.SSLSocket avec une coutume TrustManager qui accepte tous les certificats.

Vous pouvez regarder en JSSE pour plus de détails à http://java.sun.com/j2se/1.4.2/docs/guide/security/jsse/JSSERefGuide.html

+0

org.apache.commons.httpclient.contrib.ssl. EasySSLProtocolSocketFactory est l'implémentation de SecureProtocolSocketFactory qui doit approuver tous les certificats. Dans le guide apache est défini comme ceci Protocole.registerProtocol ("https", nouveau protocole ("https", nouveau MySSLSocketFactory(), 443)); Comme je l'ai mentionné j'ai essayé mais ça ne marche toujours pas. Est-ce ce que vous voulez dire ou quelque chose d'autre? –

+0

Qu'est-ce que TrustManager est associé à "MySSLSocketFactory"? –

+0

public class NaiveTrustManager implémente X509TrustManager { \t privé static final X509Certificate [] _AcceptedIssuers = new X509Certificate [] {}; \t (chaîne X509Certificate [], String authType) publique vide checkClientTrusted \t \t \t lancers francs CertificateException { \t} \t checkServerTrusted public void (X509Certificate chaîne [], String authType) \t \t \t jette CertificateException { \t} Public X509Certificate [] getAcceptedIssuers() { \t \t Retourne _AcceptedIssuers; \t} } –

3

L'idée principale est d'utiliser un SSLSocketFactory sur mesure la mise en œuvre LayeredSocketFactory. Le socket personnalisé n'a pas besoin de HostNameVerifier.

private static final class TrustAllSSLSocketFactory implements 
    LayeredSocketFactory { 

    private static final TrustAllSSLSocketFactory DEFAULT_FACTORY = new TrustAllSSLSocketFactory(); 

    public static TrustAllSSLSocketFactory getSocketFactory() { 
     return DEFAULT_FACTORY; 
    } 

    private SSLContext sslcontext; 
    private javax.net.ssl.SSLSocketFactory socketfactory; 

    private TrustAllSSLSocketFactory() { 
     super(); 
     TrustManager[] tm = new TrustManager[] { new X509TrustManager() { 

      @Override 
      public void checkClientTrusted(X509Certificate[] chain, 
       String authType) throws CertificateException { 
       // do nothing 
      } 

      @Override 
      public void checkServerTrusted(X509Certificate[] chain, 
       String authType) throws CertificateException { 
       // do nothing 
      } 

      @Override 
      public X509Certificate[] getAcceptedIssuers() { 
       return new X509Certificate[0]; 
      } 

     } }; 
     try { 
      this.sslcontext = SSLContext.getInstance(SSLSocketFactory.TLS); 
      this.sslcontext.init(null, tm, new SecureRandom()); 
      this.socketfactory = this.sslcontext.getSocketFactory(); 
     } catch (NoSuchAlgorithmException e) { 
      Log.e(LOG_TAG, 
       "Failed to instantiate TrustAllSSLSocketFactory!", e); 
     } catch (KeyManagementException e) { 
      Log.e(LOG_TAG, 
       "Failed to instantiate TrustAllSSLSocketFactory!", e); 
     } 
    } 

    @Override 
    public Socket createSocket(Socket socket, String host, int port, 
     boolean autoClose) throws IOException, UnknownHostException { 
     SSLSocket sslSocket = (SSLSocket) this.socketfactory.createSocket(
      socket, host, port, autoClose); 
     return sslSocket; 
    } 

    @Override 
    public Socket connectSocket(Socket sock, String host, int port, 
     InetAddress localAddress, int localPort, HttpParams params) 
     throws IOException, UnknownHostException, ConnectTimeoutException { 
     if (host == null) { 
      throw new IllegalArgumentException(
       "Target host may not be null."); 
     } 
     if (params == null) { 
      throw new IllegalArgumentException(
       "Parameters may not be null."); 
     } 

     SSLSocket sslsock = (SSLSocket) ((sock != null) ? sock 
      : createSocket()); 

     if ((localAddress != null) || (localPort > 0)) { 

      // we need to bind explicitly 
      if (localPort < 0) { 
       localPort = 0; // indicates "any" 
      } 

      InetSocketAddress isa = new InetSocketAddress(localAddress, 
       localPort); 
      sslsock.bind(isa); 
     } 

     int connTimeout = HttpConnectionParams.getConnectionTimeout(params); 
     int soTimeout = HttpConnectionParams.getSoTimeout(params); 

     InetSocketAddress remoteAddress; 
     remoteAddress = new InetSocketAddress(host, port); 

     sslsock.connect(remoteAddress, connTimeout); 

     sslsock.setSoTimeout(soTimeout); 

     return sslsock; 
    } 

    @Override 
    public Socket createSocket() throws IOException { 
     // the cast makes sure that the factory is working as expected 
     return (SSLSocket) this.socketfactory.createSocket(); 
    } 

    @Override 
    public boolean isSecure(Socket sock) throws IllegalArgumentException { 
     return true; 
    } 

} 

Vous pouvez ensuite continuer à utiliser SSLSocketFactory personnalisé dans le registre de schéma pris en charge.

private static final BasicHttpParams sHttpParams = new BasicHttpParams(); 
private static final SchemeRegistry sSupportedSchemes = new SchemeRegistry(); 
static { 
    sHttpParams.setParameter("http.socket.timeout", READ_TIMEOUT); 
    sHttpParams.setParameter("http.connection.timeout", CONNECT_TIMEOUT); 
    sSupportedSchemes.register(new Scheme("http", 
     PlainSocketFactory.getSocketFactory(), 80)); 
    sSupportedSchemes.register(new Scheme("https", 
     TrustAllSSLSocketFactory.getSocketFactory(), 443)); 
}