javax.net.ssl.SSLHandshakeException: Chain validation failed 异常解决

javax.net.ssl.SSLHandshakeException: Chain validation failed 异常解决

描述

在项目中使用RxJava,OkHttp和Retrofit封装的网络请求,再测试时一切正常,但修改为https的线上正式服务器后就报了异常:

javax.net.ssl.SSLHandshakeException: Chain validation failed

初次打开时会系统会有提示:

探究

作为一名合格的面向百度编程工程师,我熟练的打开了搜索引擎,找到了鸿洋大佬的 Android Https相关完全解析 当OkHttp遇到Https 博客。发现了以下内容

OkHttp 默认是支持 Https 协议的网站,但前提条件是:支持 Https 的网站证书都是由 CA 机构版本的证书。

与后台沟通后说证书没问题,是通过 CA 认证颁布的,之后通过浏览器打开了这个网址:

通过Chrome浏览器打开网址,有个锁头的图标,也说明了证书是有效的。这就很奇怪,接下来再点击证书看一下具体的证书信息

在这里插入图片描述
可以看到,证书的有效期是2019/12/26到2020/12/05,证书是有有效期的,那么和这个有效期进行对比的就应该是设备时间,我恍然大悟,回头检查了一下手机设置的时间,发现还是2019/6/1日,这时我将系统时间修改到证书有效期内的时间,就可以正常访问了。这样看来,证书有效期是和访问设备的系统时间有关,也是https的SSL验证机制使然。

解决方法一:

解决方法很简单,检查一下设备系统时间是否在证书有效期内,若没有就改到有效期即可(一般系统时间调整为跟网络一致)。

解决方法二:跳过https验证机制

问题解决了,只要将手机系统时间改为当前时间即可了。如果没有其他特殊需求,看到这里就可以结束了。

接下来就是特殊需求,为了某些SDK的算法验证,系统时间是我特意设置成2019年6月1号的,就不能用当前时间,所以以上方法对我来说没用,但既然知道了原理,那么解决起来就方便了。既然是Https的SSL验证,那么通过okhttp跳过这个验证不就好了,在网上查了一下,发现了跳过验证的写法:

在构建Okhttps时,自定义SSL验证流程,信任一切证书:


	//自定义SS验证相关类
	private static class TrustAllCerts 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];
        }
    }

    private static class TrustAllHostnameVerifier implements HostnameVerifier {
        @Override
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    }

    private static SSLSocketFactory createSSLSocketFactory() {
        SSLSocketFactory ssfFactory = null;
        try {
            SSLContext sc = SSLContext.getInstance("TLS");
            sc.init(null, new TrustManager[]{new TrustAllCerts()}, new SecureRandom());
            ssfFactory = sc.getSocketFactory();
        } catch (Exception e) {
        }
        return ssfFactory;
    }

构建Okhttp时,使用它:


    okBuilder.sslSocketFactory(createSSLSocketFactory());
    okBuilder.hostnameVerifier(new TrustAllHostnameVerifier());
    return okBuilder.build();

这样就解决了我的问题,但缺点是信任任何网址,无论是否有证书或者在证书有效期内,我的项目是公司内部网站,小伙伴们如果使用这个方法请斟酌一下。

有关Https知识,也可以看看扔物线的https讲解视频

当出现"javax.net.ssl.SSLHandshakeException: Chain validation failed"异常时,表示在SSL握手过程中,证书链验证失败。这个异常通常发生在TLS/SSL连接过程中,当客户端无法验证服务器端的证书链时会抛出该异常。证书链验证失败可能有以下几个原因: 1. 证书过期或无效: 当证书的有效期已过或证书无效时,会导致验证失败。这可能是由于证书颁发机构(CA)的信任链中的某个证书过期、被吊销或者被篡改。 2. 证书不匹配: 当服务器提供的证书与预期的证书不匹配时,验证也会失败。这可能是由于服务器使用了错误的证书或者证书不属于该服务器。 3. 证书链不完整: 当服务器只提供了部分证书链,没有提供完整的证书链时,验证也会失败。证书链是由服务器证书、中间证书和根证书组成的,缺少其中任何一个证书都会导致验证失败。 解决此问题的方法包括: 1. 检查证书是否过期或无效: 需要确保服务器端的证书链中的每个证书都是有效的,并且没有过期或被吊销。 2. 检查证书是否正确匹配: 确保服务器端提供的证书与预期的证书匹配。可以检查证书的主体名称、主体备用名称等信息来验证是否正确匹配。 3. 检查证书链是否完整: 确保服务器端提供了完整的证书链,包括服务器证书、中间证书和根证书。如果缺少任何一个证书,都会导致验证失败。 如果以上方法无法解决问题,可以尝试更新Java安全性策略文件,或者检查网络连接是否正常。 需要注意的是,在部署TLS/SSL连接时,确保服务器端和客户端的证书配置正确,并且证书链能够被正确验证,以确保安全的通信。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [javax.net.ssl.SSLHandshakeException: Chain validation failed](https://blog.csdn.net/u014084081/article/details/128002198)[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: 50%"] - *3* [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: 50%"] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值