2010-06-28 12 views

Respuesta

33

Este es mi (editado) solución:

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; 
} 

Tiene la ventaja de no cambiar el comportamiento por defecto a menos que haya un dominio comodín, y en ese caso se revalida como si el dominio de 2 partes (por ejemplo, someUrl.com) fuera parte del certificado, de lo contrario se vuelve a lanzar la excepción original. Eso significa que los certs verdaderamente inválidos seguirán fallando.

+0

He intentado utilizar lo anterior, pero a veces obtengo excepciones de desbordamiento de pila: el método verify() nunca detiene la recursión. De unas pocas cientos de miles de instalaciones, sucede aproximadamente 80 veces a la semana. ¿Has visto algún problema con esto? – user291701

+0

@ user291701 He editado el código para tratar de solucionar tu problema. Supongo que el problema es que terminas configurando el verificador en la misma fábrica de nuevo, por lo que termina delegándose a sí mismo de alguna manera ... No dudes en editar mi respuesta si encuentras una mejor manera. – noah

+0

En cualquier caso, estoy frente a 'el servidor no puede atender la solicitud porque el tipo de medio no está soportado' 'error. Sin obtener ninguna pista sobre el motivo de esto. –

1

Si quiere *.someUrl.com, entonces parece que podría simplemente darle www.someUrl.com/somePath en lugar de someUrl.com/somePath.

+1

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

+0

Supongo que eso es inútil, entonces. ¿Realmente necesitas https? Supongo que sí, pero eso haría la vida mucho más fácil. –

+0

¡Esta es una gran solución temporal cuando el sitio NO hace un redireccionamiento! –

3

El BouncyCastle en Android es demasiado antiguo y no reconoce el certificado de comodín.

Puede escribir su propio X509TrustManager para buscar comodines.

o puede deshabilitar la verificación del certificado por completo si puede aceptar el riesgo. Ver esta pregunta,

Self-signed SSL acceptance on Android

+0

En realidad ZZ, si el OP es correcto sobre el nombre del sitio y la estructura del certificado, entonces el mensaje de error es correcto: **. SomeUrl.com * se supone que coincide con www.someUrl.com y anything.someUrl. com, pero * no * someUrl.com o this.that.someUrl.com. –

1

si se utiliza un WebView sólo llamar

webview.clearSslPreferences(); 

para ignorar los errores SSL

Cuestiones relacionadas