使用Retrofit和OkHttp Handshake的HTTPS失败

时间:2017-04-19 08:38:26

标签: android ssl retrofit2 okhttp

我正在尝试学习如何在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。

0 个答案:

没有答案