简体   繁体   English

如何发出HTTP或HTTPS请求(强调“或”)

[英]How to make an HTTP or HTTPS request (emphasis on “or”)

I need to tweak an app somebody else built to use an API that I wrote. 我需要调整其他人使用我编写的API编写的应用程序。 In a production environment, said app will be making HTTPS requests to a server with a signed, trusted certificate. 在生产环境中,该应用将使用签名的受信任证书向服务器发出HTTPS请求。 No problem there. 没问题。

However, my local development server has no SSL certificate (other than a self-signed one I knocked up). 但是,我的本地开发服务器没有SSL证书(除了我自己敲的自签名证书之外)。 Android complains about this, specifically throwing javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found. Android对此javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.抱怨,特别是抛出javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

So, I need to do one of two things. 因此,我需要做两件事之一。

  • Convince a HttpsURLConnection to accept a http:// URL; 说服HttpsURLConnection接受http:// URL;
  • Convince the same HttpsURLConnection to accept a self-signed certificate being returned. 说服相同的HttpsURLConnection接受返回的自签名证书。

I've already tried writing a custom HostnameVerifier (with a verify method that always returns true), but that hasn't helped me past the problem. 我已经尝试编写自定义HostnameVerifier(使用始终返回true的verify方法),但这并没有帮助我解决问题。

Edit: For clarity, I cannot simply provide an http URL to HttpsURLConnection, since I then get a com.android.okhttp.internal.huc.HttpURLConnectionImpl cannot be cast to javax.net.ssl.HttpsURLConnection error. 编辑:为了清楚起见,我不能简单地向HttpsURLConnection提供一个http URL,因为随后我收到一个com.android.okhttp.internal.huc.HttpURLConnectionImpl cannot be cast to javax.net.ssl.HttpsURLConnection错误。

在没有较低级别的解决方案的情况下,我只使用了Webb库。

I was in same situation working on one project few months ago. 几个月前,我在同一情况下从事一个项目。 I had local server for developing with self signed certificate. 我有用于使用自签名证书进行开发的本地服务器。 This is my android code, it worked for me: 这是我的android代码,对我有用:

final HttpsURLConnection https = (HttpsURLConnection) requestedUrl.openConnection();

try {

    https.setConnectTimeout(timeout);
    https.setReadTimeout(timeout);
    https.setRequestMethod(method);

    if (sslSocketFactory != null) {
        https.setSSLSocketFactory(sslSocketFactory);
    }

    https.setHostnameVerifier(new HostnameVerifier() {
        @Override
        public boolean verify(String hostname, SSLSession session) {
            HostnameVerifier hv = HttpsURLConnection.getDefaultHostnameVerifier();
            return hv.verify("localhost", session);
        }
    });
...

I remember, that there was one tricky thing - the self signed certificate for server was written for name "localhost", but in android, the HTTPS request was made with IP address and this was a problem causing denying of server certificate. 我记得,有一件棘手的事情-服务器的自签名证书是为名称“ localhost”编写的,但是在android中,HTTPS请求是使用IP地址发出的,这是导致拒绝服务器证书的问题。

And loading client certificate (in my case, it was stored in .p12 file on android device): 并加载客户端证书(在我的情况下,它存储在android设备上的.p12文件中):

public static SSLContext loadCertificate(String password)
            throws IOException, KeyStoreException, CertificateException, NoSuchAlgorithmException,
            UnrecoverableKeyException, KeyManagementException {

        final FileInputStream fis = new FileInputStream(new File(CERT_FILE_DIRECTORY, CERT_FILE_NAME));

        final KeyStore keyStore = KeyStore.getInstance("PKCS12");
        keyStore.load(fis, password.toCharArray());

        final KeyManagerFactory kmf = KeyManagerFactory.getInstance("X509");
        kmf.init(keyStore, null);
        final KeyManager[] keyManagers = kmf.getKeyManagers();
        final SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(keyManagers, new TrustManager[]{new MyTrustManager()}, null);
        return sslContext;
    }

And empty MyTrustManager: 并清空MyTrustManager:

public class MyTrustManager implements X509TrustManager {

    @Override
    public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
    }

    @Override
    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
    }

    @Override
    public X509Certificate[] getAcceptedIssuers() {
        return new X509Certificate[0];
    }
}

With all this, i was able to connect via HTTPS to my local server with self signed certificate. 有了这些,我就可以使用自签名证书通过HTTPS连接到本地服务器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM