2010-06-28 15 views
17

J'utilise HttpClient sur Android pour me connecter à https://someUrl.com/somePath. Le problème est que le certificat du site est pour * .someUrl.com, pas someUrl.com, donc j'obtiens une exception SSLException. Lame sur la partie du site, oui, mais à moins que je puisse le faire réparer, je suis coincé. Y a-t-il un moyen pour que HttpClient se détende et accepte le certificat?Android HttpClient - nom d'hôte dans le certificat ne correspond pas <example.com>! = <*. Example.com>

Répondre

33

Ceci est mon (édité) solution:

class MyVerifier extends AbstractVerifier { 

    private final X509HostnameVerifier delegate; 

    public MyVerifier(final X509HostnameVerifier delegate) { 
     this.delegate = delegate; 
    } 

    @Override 
    public void verify(String host, String[] cns, String[] subjectAlts) 
       throws SSLException { 
     boolean ok = false; 
     try { 
      delegate.verify(host, cns, subjectAlts); 
     } catch (SSLException e) { 
      for (String cn : cns) { 
       if (cn.startsWith("*.")) { 
        try { 
          delegate.verify(host, new String[] { 
           cn.substring(2) }, subjectAlts); 
          ok = true; 
        } catch (Exception e1) { } 
       } 
      } 
      if(!ok) throw e; 
     } 
    } 
} 


public DefaultHttpClient getTolerantClient() { 
    DefaultHttpClient client = new DefaultHttpClient(); 
    SSLSocketFactory sslSocketFactory = (SSLSocketFactory) client 
      .getConnectionManager().getSchemeRegistry().getScheme("https") 
      .getSocketFactory(); 
    final X509HostnameVerifier delegate = sslSocketFactory.getHostnameVerifier(); 
    if(!(delegate instanceof MyVerifier)) { 
     sslSocketFactory.setHostnameVerifier(new MyVerifier(delegate)); 
    } 
    return client; 
} 

Il a l'avantage de ne pas changer le comportement par défaut, sauf si il y a un domaine générique, et dans ce cas il revalide comme si le domaine en 2 parties (par exemple, someUrl.com) faisait partie du certificat, sinon l'exception originale est renvoyée. Cela signifie que les certs vraiment invalides échoueront toujours.

+0

J'ai essayé d'utiliser ce qui précède, mais j'ai parfois des exceptions de débordement de pile - la méthode verify() ne cesse jamais d'être récursive. Sur quelques centaines de milliers d'installations, cela arrive environ 80 fois par semaine. Avez-vous vu des problèmes avec cela? – user291701

+0

@ user291701 J'ai modifié le code pour essayer de contourner votre problème. Je suppose que le problème est que vous finissez par remettre le vérificateur dans la même usine, de sorte qu'il finit par se déléguer à lui-même en quelque sorte ... N'hésitez pas à éditer ma réponse si vous trouvez un meilleur moyen. – noah

+0

Dans tous les cas, je suis confronté 'l'erreur de serveur ne peut pas traiter la demande car le type de support n'est pas pris en charge''. Ne pas avoir la moindre idée de la raison de cela. –

1

Si elle veut *.someUrl.com, il semble que vous pourriez donner www.someUrl.com/somePath au lieu de someUrl.com/somePath.

+1

Nope. www.someUrl.com redirige vers someUrl.com – noah

+0

Je suppose que c'est inutile, alors. Avez-vous vraiment besoin de https? Je le devinerais, mais cela rendrait la vie beaucoup plus facile. –

+0

Ceci est une excellente solution temporaire lorsque le site ne fait PAS de redirection! –

3

Le BouncyCastle sur Android est trop ancien et il ne reconnaît pas les certificats génériques.

Vous pouvez écrire votre propre X509TrustManager pour rechercher un caractère générique.

ou vous pouvez désactiver la vérification de certificat complètement si vous pouvez accepter le risque. Voir cette question,

Self-signed SSL acceptance on Android

+0

En fait ZZ, si l'OP est correct sur le nom du site et la structure du certificat, alors le message d'erreur est correct: **. SomeUrl.com * est supposé correspondre à www.someUrl.com et à n'importe quoi. com, mais pas * someUrl.com ou this.that.someUrl.com. –

1

si vous utilisez un WebView il suffit d'appeler

webview.clearSslPreferences(); 

pour ignorer les erreurs SSL