Fresco 在Android 4.4 版本 加载https图片问题 javax.net.ssl.SSLHandshakeException

由于Android系统的不同版本支持的TLS 版本不同,导致Fresco 加载https图片(图片来源于不同服务器,并且配置不一样)出现SSLHandshakeException
TLS 用于在两个通信应用程序之间提供保密性和数据完整性。TLS 1.0可以理解成SSL3.0 的升级版SSL3.1,TLS已有1.0,1.1,1.2,1.3版本。HTTPS与HTTP区别 – TLS/SSL

不同版本的TLS在Android中的支持情况参考Google SSLEngine(需要VPN)

TLSv1.1和TLSv1.2从Android4.1(Api级别16)开始才被支持,从Android4.4 Wear(Api级别20)才被启用(手机是Android5.0,Api级别21)
AS中SDK Platforms预览
截了一张AS中的SDK图片
下面是Fresco加载图片出现的2个错误

Caused by: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x6ce85028: 
Failure in SSL library, usually a protocol error
System.err: error:1407742E:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert protocol version 
SSL handshake aborted: ssl=0x6d1da010: Failure in SSL library, usually a protocol error
W/System.err: error:14077102:SSL routines:SSL23_GET_SERVER_HELLO:
unsupported protocol (external/openssl/ssl/s23_clnt.c:714 0x63608894:0x00000000)

第一个错误 是图片来源的服务器配置了TLS1.2
第二个错误 是图片来源的服务器配置了TLS1.0

如何查看资源来源TLS版本?打开Google浏览器,按F12,查看Security
在这里插入图片描述
既然4.4版本TLS未启用,所以配置SSLSocketFactory启用TLS,
Fresco 可以选择OKHttp库加载图片,然后构建OKHttp的SSLSocketFactory
Gradle 配置:

compile 'com.facebook.fresco:fresco:1.10.0'
compile 'com.facebook.fresco:imagepipeline-okhttp3:1.10.0'

在Application的onCreate()中配置如下:

 /**
     * Fresco 配置
     */
    private void FrescoInit() {
        OkHttpClient okHttpClient= getUnsafeOkHttpClient();  // build on your own
        ImagePipelineConfig config = OkHttpImagePipelineConfigFactory
                .newBuilder(this, okHttpClient)
                .build();
        Fresco.initialize(this, config);

    }
  private class  TrustAllManager implements X509TrustManager{

        @Override
        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {

        }

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

        }

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[0];
//            return new java.security.cert.X509Certificate[]{};
        }
    }
  /**
     * 配置OKhttp
     * @return
     */
    public OkHttpClient getUnsafeOkHttpClient() {
        try {
            // Create a trust manager that does not validate certificate chains
            // Install the all-trusting trust manager
            final SSLContext sslContext = SSLContext.getInstance("TLS");
            x509TrustManager = new TrustAllManager();
            sslContext.init(null, new TrustManager[] { x509TrustManager }, 
            new java.security.SecureRandom());
            // Create an ssl socket factory with our all-trusting manager
         /*   final SSLSocketFactory sslSocketFactory = sslContext
                    .getSocketFactory();*/
            final SSLSocketFactory sslSocketFactory = new Tls12SocketFactory(sslContext
                    .getSocketFactory());

            OkHttpClient okHttpClient = new OkHttpClient()
                    .newBuilder()
                    .sslSocketFactory(sslSocketFactory,x509TrustManager)
                    .hostnameVerifier(new HostnameVerifier() {
                        @Override
                        public boolean verify(String hostname, SSLSession session) {
                            return true;
                        }
                    })
                    .build();
            return okHttpClient;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }

Tls12SocketFactory 类extends SSLSocketFactory

public class Tls12SocketFactory extends SSLSocketFactory {
    private static final String[] TLS_SUPPORT_VERSION = {"TLSv1","TLSv1.1", "TLSv1.2"};

    final SSLSocketFactory delegate;

    public Tls12SocketFactory(SSLSocketFactory delegate) {
        this.delegate = delegate;
    }

    @Override
    public String[] getDefaultCipherSuites() {
        return delegate.getDefaultCipherSuites();
    }

    @Override
    public String[] getSupportedCipherSuites() {
        return delegate.getSupportedCipherSuites();
    }

    @Override
    public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
        return patch(delegate.createSocket(s, host, port, autoClose));
    }

    @Override
    public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
        return patch(delegate.createSocket(host, port));
    }

    @Override
    public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {
        return patch(delegate.createSocket(host, port, localHost, localPort));
    }

    @Override
    public Socket createSocket(InetAddress host, int port) throws IOException {
        return patch(delegate.createSocket(host, port));
    }

    @Override
    public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
        return patch(delegate.createSocket(address, port, localAddress, localPort));
    }

    private Socket patch(Socket s) {
        if (s instanceof SSLSocket) {
            ((SSLSocket) s).setEnabledProtocols(TLS_SUPPORT_VERSION);
        }
        return s;

    }
}

参考:
Android HTTPS、TLS版本支持相关解决方案
OkHttpUtils: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0xb8f02e68
不同版本的TLS在Android中的支持情况
https://stackoverflow.com/questions/29916962/javax-net-ssl-sslhandshakeexception-javax-net-ssl-sslprotocolexception-ssl-han
当Fresco/Picasso遇到https(1)----https跳过证书验证
Android 设置客户端支持的TLS支持的版本号

javax.net.ssl.SSLHandshakeException是一个SSL握手异常,通常在建立SSL连接时发生。这个异常可能是由多种原因引起的,比如证书问题、协议版本不兼容、密钥交换失败等。根据引用提供的解决方案,可能可以尝试以下步骤来解决该异常。 1. 首先,检查你的证书是否有效,确保证书链上的所有证书都是可信的。如果证书无效或不可信,可以尝试更新或更换证书。 2. 检查服务器和客户端之间的SSL协议版本是否兼容。如果协议版本不匹配,可以尝试调整SSL协议版本来解决问题。 3. 检查密钥交换算法是否正确配置。密钥交换是SSL握手的一个关键步骤,确保服务器和客户端可以正确交换密钥。 4. 如果以上步骤都不能解决问题,可以尝试添加自定义的主机认证和信任管理器来处理SSL握手。根据引用中提供的代码示例,在HttpSendUtils.java文件中添加相关代码,包括配置认证管理器和激活主机认证。 需要注意的是,以上步骤只是一些常见的解决方案,具体解决方法可能因具体情况而异。建议根据具体错误信息和日志来进行排查和调试,以找到准确的解决方法。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure的一个解决方案-附件资源](https://download.csdn.net/download/weixin_42200791/15591143)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [解决 javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path build...](https://blog.csdn.net/chaishen10000/article/details/82992291)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [SSL证书认证失败javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: 解决...](https://blog.csdn.net/qq_40315210/article/details/102503946)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值