我正在开发一个Android
调用 some API
s over的应用程序https
。使用retrofit2
和okhttp3
。在我的开发过程中,我使用在服务器中生成的自签名证书。API
当我使用自签名证书时,我在调用 s 时遇到了很多问题,我解决了所有问题,但遇到了这个异常SSLPeerUnverifiedException
。
目前,我已将证书复制ServerCertificate.cer
到Download
目录以加载它并将其添加到 allowed KeyStore
。我尝试了很多来自不同网站的解决方案。我尝试okhttp
使用 CustomTrust和Android 开发者网站
我根据 Android 开发人员示例编写以下代码:
X509TrustManager mTrustManager = null;
private Retrofit getRetrofit(String identity, String serverBaseUrl) {
Retrofit retrofit = null;
try {
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.sslSocketFactory(getSSLConfig().getSocketFactory(), mTrustManager)
.addInterceptor(new CustomInterceptor(identity))
.addInterceptor((new okhttp3.logging.HttpLoggingInterceptor())
.setLevel(okhttp3.logging.HttpLoggingInterceptor.Level.BODY))
.connectTimeout(60, TimeUnit.SECONDS)
.readTimeout(60, TimeUnit.SECONDS)
.writeTimeout(60, TimeUnit.SECONDS)
.build();
retrofit = new Retrofit.Builder()
.baseUrl(serverBaseUrl)
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build();
} catch (Exception ex) {
}
return retrofit;
}
private SSLContext getSSLConfig() throws Exception {
FileHelper fileHelper = FileHelper.getInstance();
String cerFilePath = "/storage/emulated/0/Download/ServerCertificate.cer";
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream caInput = new FileInputStream(cerFilePath);
Certificate ca;
try {
ca = cf.generateCertificate(caInput);
//Below line print: ca=CN=SS_CEM_5_4
System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());
} finally {
caInput.close();
}
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);
mTrustManager = (X509TrustManager) tmf.getTrustManagers()[0];
return context;
}
目前,当我调用任何API
我得到以下异常:
Exception occurred while calling heartbeat
javax.net.ssl.SSLPeerUnverifiedException: Hostname ss_cem_5_4 not verified:
certificate: sha256/OUxkHCacC0q0+ZQpL/3V1jFgV57CXweub/lSSUXsAZw=
DN: CN=\00S\00S\00_\00C\00E\00M\00_\005\00_\004
subjectAltNames: []
at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.java:330)
at okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.java:283)
at okhttp3.internal.connection.RealConnection.connect(RealConnection.java:168)
at okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:257)
at okhttp3.internal.connection.StreamAllocation.findHealthyConnection(StreamAllocation.java:135)
at okhttp3.internal.connection.StreamAllocation.newStream(StreamAllocation.java:114)
at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:42)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:126)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at co.sedco.sevicesbase.managementproxy.webproxy.CustomInterceptor.intercept(CustomInterceptor.java:39)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:254)
at okhttp3.RealCall.execute(RealCall.java:92)
at retrofit2.OkHttpCall.execute(OkHttpCall.java:186)
at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall.execute(ExecutorCallAdapterFactory.java:92)
at co.sedco.sevicesbase.managementproxy.webproxy.ManagementWebProxy.callHeartbeat(ManagementWebProxy.java:271)
at co.sedco.sevicesbase.heartbeat.HeartbeatManager$CallHeartbeatTimerTask.run(HeartbeatManager.java:91)
at java.util.TimerThread.mainLoop(Timer.java:555)
at java.util.TimerThread.run(Timer.java:505)
我只是设法通过添加和覆盖函数HostnameVerifier
来使自签名证书工作始终返回,但是这种解决方案是不可接受的,我相信我会遇到必须在客户服务器中使用自签名证书的情况(虽然不推荐)。OkHttpClient
Verify
true
我正在使用 URL 调用服务器:https://ss_cem_5_4/Portal/api/GetHeartbeat
我还应该提到我无法通过服务器名称调用服务器,因此我修改hosts
了路径“/system/etc/”中的文件以添加我的服务器的映射。(我正在使用有根设备)