OkHttp javax.net.ssl.SSLPeerUnverifiedException:主机名 domain.com 未验证 [英] OkHttp javax.net.ssl.SSLPeerUnverifiedException: Hostname domain.com not verified

查看:45
本文介绍了OkHttp javax.net.ssl.SSLPeerUnverifiedException:主机名 domain.com 未验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经尝试了好几天才能让它发挥作用.我正在尝试使用自签名证书通过 https 连接到我的服务器.我认为现在没有任何页面或示例我没有读过.

I've been trying for days to get this working. I'm trying to connect to my server over https with a self signed certificate. I don't think there is any pages or examples that I haven't read by now.

我做了什么:

  1. 按照本教程创建 bks 密钥库:http://blog.crazybob.org/2010/02/android-trusting-ssl-certificates.html

它使用 openssl s_client -connect domain.com:443 从服务器获取证书.然后使用充气城堡创建一个 bks 密钥库.

It uses openssl s_client -connect domain.com:443 to get the certificate from the server. Then creates a bks keystore using bouncy castle.

  1. 从原始文件夹读取创建的密钥库,将其添加到 sslfactory,然后添加到 OkHttpClient.像这样:

  1. Reading created keystore from raw folder adding it to sslfactory and and then to OkHttpClient. Like this:

public ApiService() {
    mClient = new OkHttpClient();
    mClient.setConnectTimeout(TIMEOUT_SECONDS, TimeUnit.SECONDS);
    mClient.setReadTimeout(TIMEOUT_SECONDS, TimeUnit.SECONDS);
    mClient.setCache(getCache());
    mClient.setCertificatePinner(getPinnedCerts());
    mClient.setSslSocketFactory(getSSL());
}

protected SSLSocketFactory getSSL() {
    try {
        KeyStore trusted = KeyStore.getInstance("BKS");
        InputStream in = Beadict.getAppContext().getResources().openRawResource(R.raw.mytruststore);
        trusted.load(in, "pwd".toCharArray());
        SSLContext sslContext = SSLContext.getInstance("TLS");
        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        trustManagerFactory.init(trusted);
        sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
        return sslContext.getSocketFactory();
    } catch(Exception e) {
        e.printStackTrace();
    }
    return null;
}

public CertificatePinner getPinnedCerts() {
    return new CertificatePinner.Builder()
            .add("domain.com", "sha1/theSha=")
            .build();
}

  • 出于某种原因,无论是否使用密钥库,它总是会生成 SSLPeerUnverifiedException.有或没有 CertificatePinner.

    javax.net.ssl.SSLPeerUnverifiedException: Hostname domain.com not verified: 0         
     W/System.err﹕ certificate: sha1/theSha=
     W/System.err﹕ DN: 1.2.840.113549.1.9.1=#1610696e666f40626561646963742e636f6d,CN=http://domain.com,OU=development,O=domain,L=Valencia,ST=Valencia,C=ES
     W/System.err﹕ subjectAltNames: []
     W/System.err﹕ at com.squareup.okhttp.internal.http.SocketConnector.connectTls(SocketConnector.java:124)
     W/System.err﹕ at com.squareup.okhttp.Connection.connect(Connection.java:143)
     W/System.err﹕ at com.squareup.okhttp.Connection.connectAndSetOwner(Connection.java:185)
     W/System.err﹕ at com.squareup.okhttp.OkHttpClient$1.connectAndSetOwner(OkHttpClient.java:128)
     W/System.err﹕ at com.squareup.okhttp.internal.http.HttpEngine.nextConnection(HttpEngine.java:341)
     W/System.err﹕ at com.squareup.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:330)
     W/System.err﹕ at com.squareup.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:248)
     W/System.err﹕ at com.squareup.okhttp.Call.getResponse(Call.java:273)
     W/System.err﹕ at com.squareup.okhttp.Call$ApplicationInterceptorChain.proceed(Call.java:230)
     W/System.err﹕ at com.squareup.okhttp.Call.getResponseWithInterceptorChain(Call.java:201)
     W/System.err﹕ at com.squareup.okhttp.Call.execute(Call.java:81)
     ...
    

  • 我做错了什么?

    推荐答案

    我终于通过多种答案的组合解决了这个问题.

    I finally got this working with a mix of multiple answers.

    首先,证书制作错误,不知道是怎么制作的.但是通过使用 this answer 中的脚本创建它们使它们工作.需要的是服务器证书和密钥.然后客户端需要另一个证书.

    First, the certificates was made wrongly, not sure how. But by creating them using the script in this answer made them work. What was needed was a server certificate and a key. Then the client needed another certificate.

    为了在 android 中使用证书,我将 .pem 文件转换为 .crt 文件,如下所示:

    To use the certificate in android I converted the .pem file to a .crt file like this:

    openssl x509 -outform der -in client.pem  -out client.crt
    

    在 android 中,我将证书添加到我的 OkHttp 客户端,如下所示:

    In android I added the certificate to my OkHttp client like the following:

    public ApiService() {
        mClient = new OkHttpClient();
        mClient.setConnectTimeout(TIMEOUT_SECONDS, TimeUnit.SECONDS);
        mClient.setReadTimeout(TIMEOUT_SECONDS, TimeUnit.SECONDS);
        mClient.setCache(getCache());
        mClient.setSslSocketFactory(getSSL());
    }
    
    protected SSLSocketFactory getSSL() {
        try {
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            InputStream cert = getAppContext().getResources().openRawResource(R.raw.client);
            Certificate ca = cf.generateCertificate(cert);
            cert.close();
    
            // creating a KeyStore containing our trusted CAs
            String keyStoreType = KeyStore.getDefaultType();
            KeyStore keyStore = KeyStore.getInstance(keyStoreType);
            keyStore.load(null, null);
            keyStore.setCertificateEntry("ca", ca);
    
            return new AdditionalKeyStore(keyStore);
        } catch(Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    

    new AdditionalKeyStore() 的最后一部分来自这个写得很好的答案.这增加了一个后备密钥库.

    The last part with new AdditionalKeyStore() is taken from this very well written answer. Which adds a fallback keystore.

    我希望这可以帮助其他人!这是使 HTTPS 与我发现的自签名证书一起工作的最简单方法.其他方法包括拥有一个对我来说似乎过多的 BouncyCastle 密钥库.

    I hope this might help anyone else! This is the simplest way to get HTTPS working with a self-signed certificate that I have found. Other ways include having a BouncyCastle keystore which seems excessive to me.

    这篇关于OkHttp javax.net.ssl.SSLPeerUnverifiedException:主机名 domain.com 未验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    相关文章
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆