OkHttp信任证书 [英] OkHttp trusting certificate
问题描述
在我的Android应用程序,我需要执行一些要求,我的服务器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,则会议);
}
};
您可以阅读以下链接:
-
有一个握手期间使用如果URL的主机名不匹配等方的识别主机名。
-
原因之一可能发生这种情况是由于服务器配置错误。该 服务器配置了不具有的受试者的证书 或者符合你的服务器使用者备用名称字段 试图达成...
然后,您可以使用主机名验证你的应用程序中,通过调用 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:
It is to be used during a handshake if the URL's hostname does not match the peer's identification hostname.
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屋!