Retrofit 2.2.0 Android API 24 javax.net.ssl.SSLHandshakeException: 握手失败

3

我正在使用Retrofit 2.2.0将图片上传到服务器(使用Java语言)。在一个Android设备上(三星Galaxy S6),API为24(版本号:NRD90M.G920FXXU5EQAC)当我尝试提交请求时,会出现以下错误:

javax.net.ssl.SSLHandshakeException: Handshake failed

PS:我尝试将Retrofit 2.1.0降级,结果完美运行。


请尝试使用http而不是https访问您的URL。 - Reza
2个回答

9

对于我来说,解决方案是添加更多的密码作为 OkHttpClient 可接受的密码。自 API 21 以来,一些 TLS 证书已不再适用于 Android。这可能会有所帮助:

ConnectionSpec spec = new 
ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
                .tlsVersions(TlsVersion.TLS_1_2)
                .cipherSuites(      
CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,                    
CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256)
                .build();

OkHttpClient client = new OkHttpClient.Builder()
            .connectionSpecs(Collections.singletonList(spec))
            .build();

更多信息请访问:https://github.com/square/okhttp/wiki/HTTPS

(这是关于HTTPS的资料,可以点击链接查看)

5

我使用过它的版本是2.2.0。

创建一个不验证证书链的信任管理器。

final TrustManager[] trustAllCerts = new TrustManager[]{
                new X509TrustManager() {
                    @Override
                    public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
                    }

                    @Override
                    public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {

                    }

                    @Override
                    public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                        return new java.security.cert.X509Certificate[]{};
                   }
                }
        };

        // Install the all-trusting trust manager

        HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
        httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        OkHttpClient.Builder client = new OkHttpClient.Builder();
        client.interceptors().add(httpLoggingInterceptor);
        client.readTimeout(180, TimeUnit.SECONDS);
        client.connectTimeout(180, TimeUnit.SECONDS);

        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
       keyStore.load(null, null);

        SSLContext sslContext = SSLContext.getInstance("TLS");

        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
       trustManagerFactory.init(keyStore);
        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        keyManagerFactory.init(keyStore, "keystore_pass".toCharArray());
        sslContext.init(null, trustAllCerts, new SecureRandom());
        client.sslSocketFactory(sslContext.getSocketFactory())
                .hostnameVerifier(new HostnameVerifier() {
                    @Override
                    public boolean verify(String hostname, SSLSession session) {
                        return true;
                    }
               });

        Gson gson = new GsonBuilder().setLenient().create();

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(Common.BASE_URL)
                .addConverterFactory(GsonConverterFactory.create(gson))
                .client(client.build())
                .build();

        serviceApi = retrofit.create(Api.class);

谢谢,希望这能对您有所帮助。有时服务器端未安装SSL版本1.2或更低版本。


2
对我起作用了,不过我有一个后续问题。这个修复意味着你可能会很脆弱,因为你将接受发送给客户端的任何证书吗? - Abhishek Dewan
这里的keystore_pass是什么? - Kameswari
对我没用,而且接受所有的输入会使应用程序变得容易受到攻击。 - Neeraj Sewani

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接