我正在尝试学习如何在HTTPS中使用Retrofit和OkHttp。
根据我的阅读内容,我需要在raw
文件夹中获取证书,或者使用此命令echo -n | openssl s_client -connect api.****.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > gtux.cert
获取证书。我在哪里运行上述命令?
在我的情况下,我已经在.cer
文件夹中找到了raw
文件(它是给了我的)。根据{{3}}要点,我的代码如下所示:
public class SelfSignInClient {
private Context context;
public SelfSignInClient(Context context) {
this.context = context;
}
public OkHttpClient getOkHttpClient() {
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder okHttpClient = new OkHttpClient.Builder();
Certificate certificate = getCertificate();
KeyStore keyStore = createKeyStoreTrustedCAs(certificate);
TrustManagerFactory managerFactory = createTrustManagerCAs(keyStore);
SSLContext sslContext = createSSLSocketFactory(managerFactory);
okHttpClient.sslSocketFactory(sslContext.getSocketFactory());
okHttpClient.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return hostname.equals("https://dev.api.***.com:443");
}
});
// If you need an Interceptor to add some header
//okHttpClient.addInterceptor();
okHttpClient.addInterceptor(logging);
return okHttpClient.build();
}
// creating an SSLSocketFactory that uses our TrustManager
private SSLContext createSSLSocketFactory(TrustManagerFactory managerFactory) {
final String PROTOCOL = "TLS";
SSLContext sslContext = null;
try {
sslContext = SSLContext.getInstance(PROTOCOL);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
try {
assert sslContext != null;
sslContext.init(null, managerFactory.getTrustManagers(), null);
} catch (KeyManagementException e) {
e.printStackTrace();
}
return sslContext;
}
// creating a TrustManager that trusts the CAs in our KeyStore
private TrustManagerFactory createTrustManagerCAs(KeyStore keyStore) {
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory managerFactory = null;
try {
managerFactory = TrustManagerFactory.getInstance(tmfAlgorithm);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
try {
assert managerFactory != null;
managerFactory.init(keyStore);
} catch (KeyStoreException e) {
e.printStackTrace();
}
return managerFactory;
}
// creating a KeyStore containing our trusted CAs
private KeyStore createKeyStoreTrustedCAs(Certificate certificate) {
final String ALIAS_CA = "ca";
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = null;
try {
keyStore = KeyStore.getInstance(keyStoreType);
} catch (KeyStoreException e) {
e.printStackTrace();
}
try {
assert keyStore != null;
keyStore.load(null, null);
} catch (IOException | NoSuchAlgorithmException | CertificateException e) {
e.printStackTrace();
}
try {
keyStore.setCertificateEntry(ALIAS_CA, certificate);
} catch (KeyStoreException e) {
e.printStackTrace();
}
return keyStore;
}
// creating a Certificate
private Certificate getCertificate() {
Certificate certificate = null;
CertificateFactory certificateFactory = loadCertificateAuthorityFromResources();
InputStream inputStream = getCAFromResources();
try {
certificate = certificateFactory.generateCertificate(inputStream);
} catch (CertificateException e) {
e.printStackTrace();
}
return certificate;
}
// loading CAs from an InputStream
private CertificateFactory loadCertificateAuthorityFromResources() {
final String CERT_TYPE = "X.509";
InputStream certificateAuthority = getCAFromResources();
CertificateFactory certificateFactory = null;
try {
certificateFactory = CertificateFactory.getInstance(CERT_TYPE);
} catch (CertificateException e) {
e.printStackTrace();
}
try {
assert certificateFactory != null;
certificateFactory.generateCertificate(certificateAuthority);
} catch (CertificateException e) {
e.printStackTrace();
} finally {
try {
certificateAuthority.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return certificateFactory;
}
// loading CAs from Resources
// save your certificate.crt on raw package in your resources
private InputStream getCAFromResources() {
return context.getResources().openRawResource(R.raw.certificate);
}
}
然后,我的REST客户端:
private static final String BASE_URL = "***";
ApiService mApiService;
public RestClient() {
SelfSignInClient selfSignInClient = new SelfSignInClient(App.getContext());
OkHttpClient okClient;
okClient = selfSignInClient.getOkHttpClient();
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Peem.class, new PeemDeserializer());
gsonBuilder.registerTypeAdapterFactory(new ItemTypeAdapterFactory());
Retrofit retrofit;
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gsonBuilder.create()))
.client(okClient)
.build();
this.mApiService = retrofit.create(ApiService.class);
}
但是,每当我尝试运行时,我都会遇到此异常:
04-19 08:26:13.666 3932-3932 / com.peems.itcrowd W / System.err:javax.net.ssl.SSLHandshakeException:握手失败 04-19 08:26:13.666 3932-3932 / com.peems.itcrowd W / System.err:at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:429) 04-19 08:26:13.666 3932-3932 / com.peems.itcrowd W / System.err:at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.java:241) 04-19 08:26:13.666 3932-3932 / com.peems.itcrowd W / System.err:at okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.java:198) 04-19 08:26:13.666 3932-3932 / com.peems.itcrowd W / System.err:at okhttp3.internal.connection.RealConnection.buildConnection(RealConnection.java:174) 04-19 08:26:13.666 3932-3932 / com.peems.itcrowd W / System.err:at okhttp3.internal.connection.RealConnection.connect(RealConnection.java:114) 04-19 08:26:13.666 3932-3932 / com.peems.itcrowd W / System.err:at okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:193) 04-19 08:26:13.667 3932-3932 / com.peems.itcrowd W / System.err:at okhttp3.internal.connection.StreamAllocation.findHealthyConnection(StreamAllocation.java:129) 04-19 08:26:13.667 3932-3932 / com.peems.itcrowd W / System.err:at okhttp3.internal.connection.StreamAllocation.newStream(StreamAllocation.java:98) 04-19 08:26:13.667 3932-3932 / com.peems.itcrowd W / System.err:at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:42) 04-19 08:26:13.667 3932-3932 / com.peems.itcrowd W / System.err:at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92) 04-19 08:26:13.667 3932-3932 / com.peems.itcrowd W / System.err:at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67) 04-19 08:26:13.667 3932-3932 / com.peems.itcrowd W / System.err:at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:109) 04-19 08:26:13.667 3932-3932 / com.peems.itcrowd W / System.err:at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92) 04-19 08:26:13.667 3932-3932 / com.peems.itcrowd W / System.err:at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67) 04-19 08:26:13.667 3932-3932 / com.peems.itcrowd W / System.err:at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93) 04-19 08:26:13.667 3932-3932 / com.peems.itcrowd W / System.err:at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92) 04-19 08:26:13.667 3932-3932 / com.peems.itcrowd W / System.err:at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:124) 04-19 08:26:13.667 3932-3932 / com.peems.itcrowd W / System.err:at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92) 04-19 08:26:13.667 3932-3932 / com.peems.itcrowd W / System.err:at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67) 04-19 08:26:13.668 3932-3932 / com.peems.itcrowd W / System.err:at okhttp3.logging.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.java:212) 04-19 08:26:13.668 3932-3932 / com.peems.itcrowd W / System.err:at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92) 04-19 08:26:13.668 3932-3932 / com.peems.itcrowd W / System.err:at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67) 04-19 08:26:13.668 3932-3932 / com.peems.itcrowd W / System.err:at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:170) 04-19 08:26:13.668 3932-3932 / com.peems.itcrowd W / System.err:at okhttp3.RealCall.access $ 100(RealCall.java:33) 04-19 08:26:13.668 3932-3932 / com.peems.itcrowd W / System.err:at okhttp3.RealCall $ AsyncCall.execute(RealCall.java:120) 04-19 08:26:13.668 3932-3932 / com.peems.itcrowd W / System.err:at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32) 04-19 08:26:13.669 3932-3932 / com.peems.itcrowd W / System.err:at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133) 04-19 08:26:13.669 3932-3932 / com.peems.itcrowd W / System.err:at java.util.concurrent.ThreadPoolExecutor $ Worker.run(ThreadPoolExecutor.java:607) 04-19 08:26:13.669 3932-3932 / com.peems.itcrowd W / System.err:at java.lang.Thread.run(Thread.java:761) 04-19 08:26:13.670 3932-3932 / com.peems.itcrowd W / System.err:压制:javax.net.ssl.SSLHandshakeException:握手失败 04-19 08:26:13.670 3932-3932 / com.peems.itcrowd W / System.err:... 29更多 04-19 08:26:13.671 3932-3932 / com.peems.itcrowd W / System.err:引起:javax.net.ssl.SSLProtocolException:SSL握手中止:ssl = 0xac0d93c0:SSL库失败,通常是协议错误 04-19 08:26:13.671 3932-3932 / com.peems.itcrowd W / System.err:错误:100000f7:SSL例程:OPENSSL_internal:WRONG_VERSION_NUMBER(external / boringssl / src / ssl / tls_record.c:192 0x9d254196:0x00000000 ) 04-19 08:26:13.671 3932-3932 / com.peems.itcrowd W / System.err:at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method) 04-19 08:26:13.671 3932-3932 / com.peems.itcrowd W / System.err:at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:357)
修改
当我尝试在CMD中运行echo -n | openssl s_client -connect api.****.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > gtux.cert
时,我收到此回复Loading 'screen' into random state -'sed' is not recognized as an internal or external command, operable program or batch file.
,并且我有一个0.krt文件,该文件为0kb。