Android OkHttp信任证书

Android OkHttp信任证书,android,ssl,https,keystore,okhttp,Android,Ssl,Https,Keystore,Okhttp,在我的android应用程序中,我需要使用OkHttp库向我的服务器执行一些请求。 我的ssl证书由四部分组成: AddTrustExternalCARoot.crt COMODORSAAddTrustCA.crt COMODORSADomainValidationSecureServerCA.crt www_mydomain_com.crt 我已经在Portecle1.9中导入了所有部分,然后设置了密钥库密码并导出了.bks证书 然后我将这个mycert.bks插入到我的应用程序项目的re

在我的android应用程序中,我需要使用OkHttp库向我的服务器执行一些请求。 我的ssl证书由四部分组成:

  • AddTrustExternalCARoot.crt
  • COMODORSAAddTrustCA.crt
  • COMODORSADomainValidationSecureServerCA.crt
  • www_mydomain_com.crt
我已经在Portecle1.9中导入了所有部分,然后设置了密钥库密码并导出了.bks证书

然后我将这个mycert.bks插入到我的应用程序项目的res/raw文件夹中。 现在,我正尝试使用以下代码通过https连接到我的服务器:

OkHttpClient client = new OkHttpClient();
        try{
            client.setSslSocketFactory(getPinnedCertSslSocketFactory(context));
            RequestBody formBody = new FormEncodingBuilder()
                    .add("params", "xxx")
                    .build();
            Request request = new Request.Builder()
                    .url("https:\\mydomain.com")
                    .post(formBody)
                    .build();

            Response response = client.newCall(request).execute();
            if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
            return response.body().string();;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;

    }


private SSLSocketFactory getPinnedCertSslSocketFactory(Context context) {
    try {
        KeyStore trusted = KeyStore.getInstance("BKS");
        InputStream in = context.getResources().openRawResource(R.raw.mycert);
        trusted.load(in, "mypass".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) {
        Log.e("MyApp", e.getMessage(), e);
    }
    return null;
}
但我得到一个例外,这是日志:

10-11 18:22:51.930 13604-5341/com.aaa.android.client W/System.err: javax.net.ssl.SSLPeerUnverifiedException: Hostname myserver.net not verified:
10-11 18:22:51.930 13604-5341/com.aaa.android.client W/System.err:     certificate: sha1/"mysha1string"
10-11 18:22:51.930 13604-5341/com.aaa.android.client W/System.err:     DN: CN=www.aaa.it,OU=PositiveSSL,OU=Domain Control Validated
10-11 18:22:51.930 13604-5341/com.aaa.android.client W/System.err:     subjectAltNames: [www.aaa.it, aaa.it]
10-11 18:22:51.940 13604-5341/com.aaa.android.client W/System.err:     at com.squareup.okhttp.Connection.connectTls(Connection.java:244)
10-11 18:22:51.940 13604-5341/com.aaa.android.client W/System.err:     at com.squareup.okhttp.Connection.connectSocket(Connection.java:199)
10-11 18:22:51.940 13604-5341/com.aaa.android.client W/System.err:     at com.squareup.okhttp.Connection.connect(Connection.java:172)
10-11 18:22:51.940 13604-5341/com.aaa.android.client W/System.err:     at com.squareup.okhttp.Connection.connectAndSetOwner(Connection.java:367)
10-11 18:22:51.940 13604-5341/com.aaa.android.client W/System.err:     at com.squareup.okhttp.OkHttpClient$1.connectAndSetOwner(OkHttpClient.java:128)
10-11 18:22:51.940 13604-5341/com.aaa.android.client W/System.err:     at com.squareup.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:328)
10-11 18:22:51.940 13604-5341/com.aaa.android.client W/System.err:     at com.squareup.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:245)
10-11 18:22:51.940 13604-5341/com.aaa.android.client W/System.err:     at com.squareup.okhttp.Call.getResponse(Call.java:267)
10-11 18:22:51.940 13604-5341/com.aaa.android.client W/System.err:     at com.squareup.okhttp.Call$ApplicationInterceptorChain.proceed(Call.java:224)
10-11 18:22:51.940 13604-5341/com.aaa.android.client W/System.err:     at com.squareup.okhttp.Call.getResponseWithInterceptorChain(Call.java:195)
10-11 18:22:51.940 13604-5341/com.aaa.android.client W/System.err:     at com.squareup.okhttp.Call.execute(Call.java:79)
10-11 18:22:51.940 13604-5341/com.aaa.android.client W/System.err:     at com.aaa.android.client.Login$BackgroundTask.doInBackground(Login.java:294)
10-11 18:22:51.940 13604-5341/com.aaa.android.client W/System.err:     at com.aaa.android.client.Login$BackgroundTask.doInBackground(Login.java:277)
10-11 18:22:51.950 13604-5341/com.aaa.android.client W/System.err:     at android.os.AsyncTask$2.call(AsyncTask.java:288)
10-11 18:22:51.950 13604-5341/com.aaa.android.client W/System.err:     at java.util.concurrent.FutureTask.run(FutureTask.java:237)
10-11 18:22:51.950 13604-5341/com.aaa.android.client W/System.err:     at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
10-11 18:22:51.950 13604-5341/com.aaa.android.client W/System.err:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
10-11 18:22:51.950 13604-5341/com.aaa.android.client W/System.err:     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
10-11 18:22:51.950 13604-5341/com.aaa.android.client W/System.err:     at java.lang.Thread.run(Thread.java:818)
问题在哪里

更新: 我在这个库上做了很多尝试,我发现:

  • 如果我自动请求https:\link.com OkHttp库 信任所有证书
  • 如果我只想信任我的证书,我必须执行我需要的解决方案 贴在上面
  • 如果我不想接受所有主机,但不使用我的证书,我 可以按照BNK的建议使用hostnameVerifier
但是,如果我的解决方案有效,为什么我会发布这个问题呢?因为我很笨,我请求的是我的vps url(vpsxxx.net/directory.php),而不是我的域(mydomain.it/directory.php)

显然,SSL证书应用于我的域,而不是我的vps

我希望这对某人有用


附言:对不起我的英语D

让我们假设您的服务器应用程序托管在一台服务器计算机内,该服务器计算机具有一个服务器证书,例如,
“颁发给”
的是
“localhost”
。然后,在
verify
方法中,您可以验证
“localhost”

您可以通过以下链接阅读更多内容:

  • 如果URL的主机名与对等方的标识主机名不匹配,则在握手过程中使用

  • 发生这种情况的一个原因是服务器配置错误。这个 服务器配置了一个没有主题的证书 或与您所在的服务器匹配的主题备选名称字段 试图达到

  • 然后,您可以通过调用
    client.setHostnameVerifier(hostnameVerifier)在应用程序中使用主机名验证器。希望这有帮助

    p/S:另一个临时解决方法是
    返回true
    verify
    方法中,但不建议使用该方法。

    为什么不在
    verify()中返回true?
    
    HostnameVerifier hostnameVerifier = new HostnameVerifier() {
        @Override
        public boolean verify(String hostname, SSLSession session) {
            HostnameVerifier hv =
                HttpsURLConnection.getDefaultHostnameVerifier();
            return hv.verify("localhost", session);
        }
    };