gpt4 book ai didi

android - 证书固定不适用于 Android 上的 OkHttp

转载 作者:可可西里 更新时间:2023-11-01 19:06:36 25 4
gpt4 key购买 nike

在 Android 应用上使用 com.squareup.okhttp:okhttp:2.4.0com.squareup.retrofit:retrofit:1.9.0,尝试与基于 HTTPS 的服务器 REST API,使用自签名证书。

服务器 keystore 有一个私钥和 2 个证书,服务器证书和根证书。 openssl s_client 输出 -

Certificate chain
0 s:/C=...OU=Dev/CN=example.com
i:/C=... My CA/emailAddress=info@example.com
1 s:/C=... My CA/emailAddress=info@example.com
i:/C=... My CA/emailAddress=info@example.com

在 Android 应用程序中,OkHttp 使用根证书的 SHA1 签名进行初始化 -

CertificatePinner certificatePinner = new CertificatePinner.Builder()
.add("example.com", "sha1/5d...3b=")
.build();

OkHttpClient client = new OkHttpClient();
client.setCertificatePinner(certificatePinner);

RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint("https://example.com")
.setClient(new OkClient(client))
.build();

但是当尝试发送请求失败并出现异常时 -

retrofit.RetrofitError: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:395)
at retrofit.RestAdapter$RestHandler.invoke(RestAdapter.java:240)
at java.lang.reflect.Proxy.invoke(Proxy.java:397)
at $Proxy1.report(Unknown Source)
...
at android.os.AsyncTask$2.call(AsyncTask.java:288)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)
Caused by: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:306)
at com.squareup.okhttp.internal.http.SocketConnector.connectTls(SocketConnector.java:103)
at com.squareup.okhttp.Connection.connect(Connection.java:143)
at com.squareup.okhttp.Connection.connectAndSetOwner(Connection.java:185)
at com.squareup.okhttp.OkHttpClient$1.connectAndSetOwner(OkHttpClient.java:128)
at com.squareup.okhttp.internal.http.HttpEngine.nextConnection(HttpEngine.java:341)

在尝试 sslSocket.startHandshake() 时,它会在 com.squareup.okhttp.internal.http.SocketConnector 处抛出,甚至在 CertificatePinner 之前用于检查收到的证书。

我已使用 opensslcurl --cacert root.pem 确保服务器已正确安装证书。

那么为什么 OkHttp 在尝试检查提供的证书是否正常之前就抛出异常?

最佳答案

OkHttp 不支持自签名证书。

当使用由已知 CA 签名的证书时,握手成功,然后 CertificatePinner 确保证书链至少包含一个提供的签名。如果没有出现,它将抛出异常,停止请求。

因此可以使用由已知 CA 签名的证书并固定其中一个证书以确保我们正在与正确的服务器通信。

关于android - 证书固定不适用于 Android 上的 OkHttp,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32297776/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com