OkHttp信任证书 [英] OkHttp trusting certificate

查看:1180
本文介绍了OkHttp信任证书的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的Andr​​oid应用程序,我需要执行一些要求,我的服务器OkHttp库。 我有一个SSL证书,它由四部分组成:

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

我已经进口的所有部分portecle 1.9,然后我把我的密钥库的密码,我已经出口了.bks证书。

然后,我已经在我的应用程序项目的RES /原始文件夹中插入该mycert.bks。 现在,我想通过HTTPS与此code连接到我的服务器:

  OkHttpClient客户端=新OkHttpClient();
        尝试{
            client.setSslSocketFactory(getPinnedCertSslSocketFactory(上下文));
            RequestBody formBody =新FormEncodingBuilder()
                    。新增(PARAMS,XXX)
                    。建立();
            请求请求=新Request.Builder()
                    .URL(HTTPS:\\ mydomain.com)
                    。员额(formBody)
                    。建立();

            响应响应= client.newCall(要求).execute();
            如果抛出IOException异常新(意外code+响应)(response.isSuccessful()!);
            返回response.body()。字符串();;
        }赶上(例外五){
            e.printStackTrace();
        }
        返回null;

    }


私人SSLSocketFactory的getPinnedCertSslSocketFactory(上下文的背景下){
    尝试 {
        密钥仓库中可信任= KeyStore.getInstance(BKS);
        InputStream的时间= context.getResources()openRawResource(R.raw.mycert)。
        trusted.load(在为mypass.toCharArray());
        的SSL连接的SSL连接= SSLContext.getInstance(TLS);
        的TrustManagerFactory的TrustManagerFactory = TrustManagerFactory.getInstance(
        TrustManagerFactory.getDefaultAlgorithm());
        trustManagerFactory.init(信任);
        sslContext.init(空,trustManagerFactory.getTrustManagers(),NULL);
        返回sslContext.getSocketFactory();
    }赶上(例外五){
        Log.e(MyApp的,e.getMessage(),E);
    }
    返回null;
}
 

不过,我得到一个例外,这是logcat的:

  10-11 18:22:51.930 13604-5341 / com.aaa.android.client W / System.err的:javax.net.ssl​​.SSLPeerUnverifiedException:主机名myserver.net不验证:
10-11 18:22:51.930 13604-5341 / com.aaa.android.client W / System.err的:证书: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 =域控制验证
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的:在com.squareup.okhttp.Connection.connectTls(Connection.java:244)
10-11 18:22:51.940 13604-5341 / com.aaa.android.client W / System.err的:在com.squareup.okhttp.Connection.connectSocket(Connection.java:199)
10-11 18:22:51.940 13604-5341 / com.aaa.android.client W / System.err的:在com.squareup.okhttp.Connection.connect(Connection.java:172)
10-11 18:22:51.940 13604-5341 / com.aaa.android.client W / System.err的:在com.squareup.okhttp.Connection.connectAndSetOwner(Connection.java:367)
10-11 18:22:51.940 13604-5341 / com.aaa.android.client W / System.err的:在com.squareup.okhttp.OkHttpClient $ 1.connectAndSetOwner(OkHttpClient.java:128)
10-11 18:22:51.940 13604-5341 / com.aaa.android.client W / System.err的:在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的:在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的:在com.squareup.okhttp.Call.getResponse(Call.java:267)
10-11 18:22:51.940 13604-5341 / com.aaa.android.client W / System.err的:在com.squareup.okhttp.Call $ ApplicationInterceptorChain.proceed(Call.java:224)
10-11 18:22:51.940 13604-5341 / com.aaa.android.client W / System.err的:在com.squareup.okhttp.Call.getResponseWithInterceptorChain(Call.java:195)
10-11 18:22:51.940 13604-5341 / com.aaa.android.client W / System.err的:在com.squareup.okhttp.Call.execute(Call.java:79)
10-11 18:22:51.940 13604-5341 / com.aaa.android.client W / System.err的:在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的:在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的:在android.os.AsyncTask $ 2.call(AsyncTask.java:288)
10-11 18:22:51.950 13604-5341 / com.aaa.android.client W / System.err的:在java.util.concurrent.FutureTask.run(FutureTask.java:237)
10-11 18:22:51.950 13604-5341 / com.aaa.android.client W / System.err的:在android.os.AsyncTask $ SerialExecutor $ 1.运行(AsyncTask.java:231)
10-11 18:22:51.950 13604-5341 / com.aaa.android.client W / System.err的:在java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
10-11 18:22:51.950 13604-5341 / com.aaa.android.client W / System.err的:在java.util.concurrent.ThreadPoolExecutor中的$ Worker.run(ThreadPoolExecutor.java:587)
10-11 18:22:51.950 13604-5341 / com.aaa.android.client W / System.err的:在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

解决方案

让我们假设你的服务器应用程序托管服务器的机器,有一个服务器证书,其中里面的颁发给本地主机为例。然后,验证方法中,你可以验证本地主机

 的HostnameVerifier的HostnameVerifier =新的HostnameVerifier(){
    @覆盖
    公共布尔验证(字符串主机名,的SSLSession会话){
        的HostnameVerifier HV =
            HttpsURLConnection.getDefaultHostnameVerifier();
        返回hv.verify(localhost,则会议);
    }
};
 

您可以阅读以下链接:

  1. 的HostnameVerifier

      

    有一个握手期间使用如果URL的主机名不匹配等方的识别主机名。

  2. 常见的有主机名验证问题

      

    原因之一可能发生这种情况是由于服务器配置错误。该   服务器配置了不具有的受试者的证书   或者符合你的服务器使用者备用名称字段   试图达成...

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

P / S:另一个临时的解决方法是返回true; 验证的方法,但是,它的不推荐使用。

In my android app I need to execute some request to my server with OkHttp library. I have a ssl certificate that consist in four parts:

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

I have imported all parts in portecle 1.9, then I set my keystore password and I have exported the .bks cert.

Then I have inserted this mycert.bks in res/raw folder of my app project. Now I'm trying to connect to my server by https with this code:

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

But I obtain an exception, this is the 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)

Where is the problem?

UPDATE: I have done a lot of tries on this library and I discovered this:

  • If I do a request to https:\link.com OkHttp library automatically trust all certificate.
  • If I want trust only my certificate, I have to do the solution that I posted above.
  • If I doesn't want to accept all host,but without use my certificate I can use hostnameVerifier as BNK suggest.

But why I posted the question if my solution works? Because I'm stupid and I did the request to my vps url (vpsxxx.net/directory.php) and not to my domain (mydomain.it/directory.php).

Obviously the SSL certificate is applied to my domain and not to my vps.

I'll hope that this can be useful for someone.

P.S.: Sorry for my English! :D

解决方案

Let's assume your server app is hosting inside a server machine which has a server certificate in which "Issued to" is "localhost", for example. Then, inside verify method you can verify "localhost".

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

You can read more at the following links:

  1. HostnameVerifier

    It is to be used during a handshake if the URL's hostname does not match the peer's identification hostname.

  2. Common Problems with Hostname Verification

    One reason this can happen is due to a server configuration error. The server is configured with a certificate that does not have a subject or subject alternative name fields that match the server you are trying to reach...

Then, you can use the hostname verifier in your app, by calling client.setHostnameVerifier(hostnameVerifier);. Hope this helps!

P/S: another temporary workaround is return true; inside verify method, however, it's not recommended.

这篇关于OkHttp信任证书的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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