OkHttp信任证书

时间:2015-10-11 16:29:50

标签: android ssl https keystore okhttp

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

  • AddTrustExternalCARoot.crt
  • COMODORSAAddTrustCA.crt
  • COMODORSADomainValidationSecureServerCA.crt
  • www_mydomain_com.crt

我已经在portecle 1.9中导入了所有部分,然后我设置了我的密钥库密码,并且我已经导出了.bks证书。

然后我在我的app项目的res / raw文件夹中插入了mycert.bks。 现在我正尝试使用以下代码通过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;
}

但我获得了一个例外,这是logcat:

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库 信任所有证书。
  • 如果我只想要信任我的证书,我必须做我的解决方案 张贴在上面。
  • 如果我不想接受所有主持人,但不使用我的证书我 可以使用hostnameVerifier作为BNK建议。

但是为什么我发布了问题,如果我的解决方案有效?因为我很蠢,我向vps url(vpsxxx.net/directory.php)发出请求,而不是我的域名(mydomain.it/directory.php)。

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

我希望这对某人有用。

P.S。:对不起我的英文! :d

1 个答案:

答案 0 :(得分:3)

假设您的服务器应用程序托管在服务器计算机内,该服务器计算机具有"Issued to""localhost"的服务器证书。然后,在verify方法内,您可以验证"localhost"

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

您可以通过以下链接了解更多信息:

  1. undefined-behavior

      

    如果URL的主机名与对等方的标识主机名不匹配,则在握手期间使用它。

  2. HostnameVerifier

      

    可能发生这种情况的一个原因是服务器配置错误。该   服务器配置了没有主题的证书   或者使用与您所在服务器匹配的替代名称字段   试图达到......

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

    P / S:return true;方法中的另一个临时解决方法是verify,但不建议这样做。