使用Android Volley发出HTTPS请求
我正在尝试使用此代码进行https请求:
RequestQueue queue = Volley.newRequestQueue(getApplicationContext()); request = new Request<String>(Request.Method.GET,"https://devblahblahblah.com/service/etc",errListener);
但我得到这个错误:
com.android.volley.NoConnectionError:javax.net.ssl.SSLHandshakeException:java.security.cert.CertPathValidatorException:未find证书path的信任锚点。
需要注意的两点:
- HTTPS证书是有效的。 在浏览器中轻松打开,不会有任何警告。
- 上面的代码工作正常与HTTP链接。
我实际上需要知道在Android Volley框架中是否有任何开关/选项,我可以使用它来成功打开HTTPS URL?
可能这个链接将对你有所帮助: 使用Android Volley With Self-Signed SSL Certificate
大概这些代码可能对你有帮助:
1.创build一个实现X509TrustManager
的HttpsTrustManager
类:
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()); } }
HttpsTrustManager.allowAllSSL()
在发出https请求之前添加HttpsTrustManager.allowAllSSL()
:
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);
你可以添加这个类并从onCreate
方法执行它
new NukeSSLCerts().nuke();
它会让排除信任所有的SSL证书。
我无法打开由@ Ogre_BGR提供的链接,但浏览networking时,我发现在下面的smanikandan14 Github中完成了实际的实现。 查看他的SSl 连接的解释,以更多地了解它。
到目前为止,唯一的答案是增加一个不可信的证书作为解决scheme,但是由于您的浏览器没有抱怨,通常意味着Volley找不到完成完整信任链的中间证书。
它发生在我身上的LetsEncrypt证书。 大多数浏览器已经有这样的中间证书,所以在浏览器上看起来很好,但是Volley显然缺less一些东西。
解决scheme
将中间证书添加到您的web服务器configuration。 对于Apache,你可以按照这个参考:
https://access.redhat.com/solutions/43575
对于LetsEncrypt具体是这个文件: /etc/letsencrypt/live/your.website.com/chain.pem
所以除了你的CertificateFile和KeyFile你应该已经有工作,你现在有这第三行:
SSLCertificateChainFile /etc/letsencrypt/live/your.website.com/chain.pem
只需添加该行,重新启动apache,Volley不会再抱怨,并且不会引入任何安全漏洞!
这可能有几个原因,包括:
- 颁发服务器证书的CA是未知的
- 服务器证书不是由CA签名的,而是自签名的
- 服务器configuration缺less中间CA.
来自android的官方文档
解决scheme:您可以在请求中提供证书文件