Sử dụng com.squareup.okhttp:okhttp:2.4.0
với com.squareup.retrofit:retrofit:1.9.0
trên ứng dụng Android, cố gắng liên lạc với máy chủ REST API qua HTTPS, sử dụng chứng chỉ tự ký.Chứng chỉ ghim không hoạt động với OkHttp trên Android
Kho lưu trữ máy chủ có khóa cá nhân và 2 chứng chỉ, chứng chỉ của máy chủ và chứng chỉ gốc. openssl s_client
đầu ra -
Certificate chain
0 s:/C=...OU=Dev/CN=example.com
i:/C=... My CA/[email protected]
1 s:/C=... My CA/[email protected]
i:/C=... My CA/[email protected]
Tại ứng dụng Android, OkHttp được khởi tạo với chữ ký SHA1 chứng chỉ gốc của -
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();
Nhưng khi cố gắng gửi một yêu cầu không thành công với ngoại lệ -
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)
Nó được ném tại com.squareup.okhttp.internal.http.SocketConnector
khi thử sslSocket.startHandshake()
, thậm chí trước khi CertificatePinner
được sử dụng để kiểm tra certi đã nhận ficates.
Tôi đã đảm bảo máy chủ có chứng chỉ được cài đặt chính xác bằng cách sử dụng openssl
và với curl --cacert root.pem
.
Vậy tại sao OkHttp lại ném ngoại lệ trước khi thử kiểm tra xem các chứng chỉ được cung cấp có ổn không?
Yup. Việc ghim chứng chỉ không thay thế xác minh chứng chỉ hiện có; nó bổ sung nó. Bạn cần định cấu hình ứng dụng khách của mình để tin cậy chứng chỉ của mình; có rất nhiều ví dụ trong các bài kiểm tra! –
@JesseWilson và @Kof: Tôi có thể đặt câu hỏi không, 'một CA đã biết 'có nghĩa là một CA được cài đặt thành công trong điện thoại Android hay không (Tôi có thể thấy nó trong' Thông tin đáng tin cậy - Người dùng'? Cảm ơn – BNK
Có thể, đó là CA thiết bị có chữ ký được cài đặt trong cơ sở dữ liệu CA đáng tin cậy của nó – Kof