使用Android Volley发出HTTPS请求

时间:2013-06-11 13:48:19

标签: android https android-volley

我正在尝试使用此代码发出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:信任锚   未找到证书路径。

需要注意两点:

  1. HTTPS证书有效。轻松打开浏览器时没有任何警告。
  2. 以上代码适用于HTTP链接。
  3. 我实际上需要知道Android Volley框架中是否有任何交换机/选项,我将成功点击HTTPS网址?

11 个答案:

答案 0 :(得分:52)

以下这些代码可能会对您有所帮助:

1.创建一个实现HttpsTrustManager的{​​{1}}类:

X509TrustManager

2.在发出https请求之前添加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()

答案 1 :(得分:15)

这个链接可能会对您有所帮助:Using Android Volley With Self-Signed SSL Certificate

答案 2 :(得分:10)

你可以add this class并从onCreate方法

执行它
new NukeSSLCerts().nuke();

它将使凌空信任所有SSL证书。

答案 3 :(得分:3)

到目前为止,唯一的答案是关于添加不受信任的证书作为解决方案,但由于您的浏览器没有抱怨,通常意味着Volley无法找到完成完整信任链的中间证书。 / p>

LetsEncrypt证书发生在我身上。大多数浏览器已经拥有中间证书,所以在浏览器上看起来一切都很好,但是Volley显然缺少一些东西。

解决方案
将中间证书添加到您的Web服务器配置中。对于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不再抱怨,并且您没有引入任何安全漏洞!

答案 4 :(得分:3)

如果您正在使用排球并想要HTTPS请求或SSL认证服务,那么您可以选择以下最简单的方式: - &gt;

步骤 - &gt; 1.将.cer文件保存到res / raw /文件夹中。

步骤 - &gt; 2.使用此方法并将.cer文件名替换为.cer文件,并替换您的主机名。

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

步骤 - &gt; 3.将此行替换为“RequestQueue queue = Volley.newRequestQueue(this);” “RequestQueue queue = Volley.newRequestQueue(this,new HurlStack(null,getSocketFactory()));”在排球的请求。

答案 5 :(得分:1)

我无法打开@ Ogre_BGR提供的链接,但在浏览网页时,我发现实际的实现是在smanikandan14 Github之后完成的。请查看他的SSl-connection explanation以了解更多信息。

答案 6 :(得分:0)

出现这种情况有几个原因,包括:

  • 颁发服务器证书的CA未知
  • 服务器证书未经CA签名,但已自签名
  • 服务器配置缺少中间CA

Official doc from android

解决方案: 您可以在请求中提供证书文件

答案 7 :(得分:0)

对于遇到此类问题并且您对SSL使用 Letsencrypt 和对Web服务器使用 node.js 的任何人,请尝试此操作。假设您有这样的事情。我通过添加 const chain = fs ... 这一行来解决此问题,希望对您有所帮助

...
const app = express();
const privateKey  = fs.readFileSync('ssl/privkey.pem', 'utf8');
const certificate = fs.readFileSync('ssl/cert.pem', 'utf8');
const chain = fs.readFileSync('ssl/chain.pem', 'utf8');
const credentials = {key: privateKey, cert: certificate, ca: chain};
...
var httpsServer = https.createServer(credentials, app);

答案 8 :(得分:0)

当我将ssl添加到域时,我遇到了同样的问题。两天后,我发现URL错误的解决方案。我使用的是https://example.com,但是当我将ssl添加到域中时,网址将会更改

https://www.example.com

并且POST运行正常

答案 9 :(得分:0)

当我从cloudflare关闭代理时,收到此错误 check image here 解决此问题的最佳方法是您可以重新打开代理,还可以对ssl证书添加完全安全的访问权限。

答案 10 :(得分:0)

如果有人使用nginx和来自letsencrypt的SSL证书,解决方案是简单地使用文件fullchain.pem中的证书而不是cert.pem

ssl_certificate     /.../fullchain.pem;

此文件包括您的证书和CA的串联。