studio - Hacer una solicitud HTTPS usando Android Volley
volley android example (7)
Esto puede suceder por varias razones, incluyendo:
- La CA que emitió el certificado del servidor era desconocida
- El certificado del servidor no fue firmado por una CA, pero fue autofirmado
- A la configuración del servidor le falta una CA intermedia
Solución: puede proporcionar un archivo de certificado dentro de la solicitud
Estoy tratando de hacer una solicitud https usando este código:
RequestQueue queue = Volley.newRequestQueue(getApplicationContext());
request = new Request<String>(Request.Method.GET,"https://devblahblahblah.com/service/etc",errListener);
pero estoy recibiendo este error:
com.android.volley.NoConnectionError: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: confíe el ancla para la ruta de certificación no encontrada.
Dos puntos a tener en cuenta:
- El certificado HTTPS es válido. Se abre fácilmente sin ninguna advertencia en el navegador.
- El código anterior funciona bien con enlaces HTTP.
¿Realmente necesito saber si hay algún interruptor / opción en el marco de Android Volley mediante el cual podré acceder a una URL de HTTPS?
Hasta ahora, la única respuesta es hablar de agregar un certificado que no es de confianza como la solución, pero como su navegador no se queja, generalmente significa que Volley no puede encontrar el certificado intermedio que completa la cadena de confianza.
Me pasó con certificados LetsEncrypt. La mayoría de los navegadores ya tienen esos certificados intermedios, por lo que en el navegador todo parece estar bien, pero parece que a Volley le falta algo.
La solución
Agregue el certificado intermedio a la configuración de su servidor web. Para Apache puedes seguir esta referencia:
https://access.redhat.com/solutions/43575
Para LetsEncrypt, específicamente es este archivo: /etc/letsencrypt/live/your.website.com/chain.pem
Entonces, además de su CertificateFile y KeyFile que ya debería haber trabajado, ahora tiene esta tercera línea:
SSLCertificateChainFile /etc/letsencrypt/live/your.website.com/chain.pem
Simplemente agregando esa línea, reiniciando Apache y Volley ya no se quejan y no presentó ninguna vulnerabilidad de seguridad.
No pude abrir el enlace proporcionado por @ Ogre_BGR, pero mientras navegaba por la red, encontré la implementación real realizada en smanikandan14 Github. Mire la explicación de su conexión de SSl para saber más sobre esto.
Probablemente este enlace le sea útil: Uso de Android Volley con certificado SSL autofirmado
Probablemente estos códigos a continuación te serán útiles:
1.Crear una clase HttpsTrustManager
que implementa X509TrustManager
:
public class HttpsTrustManager implements X509TrustManager {
private static TrustManager[] trustManagers;
private static final X509Certificate[] _AcceptedIssuers = new X509Certificate[]{};
@Override
public void checkClientTrusted(
java.security.cert.X509Certificate[] x509Certificates, String s)
throws java.security.cert.CertificateException {
}
@Override
public void checkServerTrusted(
java.security.cert.X509Certificate[] x509Certificates, String s)
throws java.security.cert.CertificateException {
}
public boolean isClientTrusted(X509Certificate[] chain) {
return true;
}
public boolean isServerTrusted(X509Certificate[] chain) {
return true;
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return _AcceptedIssuers;
}
public static void allowAllSSL() {
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String arg0, SSLSession arg1) {
return true;
}
});
SSLContext context = null;
if (trustManagers == null) {
trustManagers = new TrustManager[]{new HttpsTrustManager()};
}
try {
context = SSLContext.getInstance("TLS");
context.init(null, trustManagers, new SecureRandom());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
HttpsURLConnection.setDefaultSSLSocketFactory(context
.getSocketFactory());
}
}
2.Agregue HttpsTrustManager.allowAllSSL()
antes de realizar una solicitud https:
HttpsTrustManager.allowAllSSL();
String tag_string_req = "string_req";
StringRequest strReq = new StringRequest(Request.Method.POST,
your_https_url, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
Log.d(TAG, "response :"+response);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d(TAG, "Error: " + error.getMessage());
}
}){
@Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
params.put("username", "max");
params.put("password", "123456");
return params;
}
};
AppController.getInstance().addToRequestQueue(strReq, tag_string_req);
Puedes agregar esta clase y ejecutarla desde el método onCreate
new NukeSSLCerts().nuke();
Hará volea para confiar en todos los certificados SSL.
Si está utilizando volley y desea solicitar HTTPS o un servicio certificado SSL, puede elegir la forma más fácil: ->
Paso -> 1. mantener el archivo .cer en la carpeta res / raw /.
Paso -> 2. Use este método y reemplace el nombre del archivo .cer con su archivo .cer y reemplace también el nombre de su host.
private SSLSocketFactory getSocketFactory() {
CertificateFactory cf = null;
try {
cf = CertificateFactory.getInstance("X.509");
InputStream caInput = getResources().openRawResource(R.raw.cert_name);
Certificate ca;
try {
ca = cf.generateCertificate(caInput);
Log.e("CERT", "ca=" + ((X509Certificate) ca).getSubjectDN());
} finally {
caInput.close();
}
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
HostnameVerifier hostnameVerifier = new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
Log.e("CipherUsed", session.getCipherSuite());
return hostname.compareTo("10.199.89.68")==0; //The Hostname of your server.
}
};
HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);
SSLContext context = null;
context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);
HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());
SSLSocketFactory sf = context.getSocketFactory();
return sf;
} catch (CertificateException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
return null;
}
Paso -> 3. Reemplace esta línea "RequestQueue queue = Volley.newRequestQueue (this);" con "RequestQueue queue = Volley.newRequestQueue (esto, nuevo HurlStack (null, getSocketFactory ()));" A petición de la volea.