`

SSL错误解决方案

 
阅读更多

1.问题报告

前两天在客户现场环境的同学,在进行跟第三方业务联调的过程中出现了一个https调用的错误,具体报错信息为javax.net.ssl.SSLException:Unrecognized SSL message,plaintext connection?


 

2.问题分析

这个错误意思是说,无法识别 SSL 信息,明文连接?看这个意思是说在使用 https 协议访问网络资源时无法识别 SSL 信息。但是在我们将程序发布客户现场前已经充分测试通过的,为什么在客户现场就会出现这个错误呢?

SSL(Secure Socket Layer 安全套接层)是基于HTTPS下的一个协议加密层,最初是由网景公司(Netscape)研发,后被IETF(The Internet Engineering Task Force - 互联网工程任务组)标准化后写入(RFCRequest For Comments 请求注释),RFC里包含了很多互联网技术的规范!
起初是因为HTTP在传输数据时使用的是明文(虽然说POST提交的数据时放在报体里看不到的,但是还是可以通过抓包工具窃取到)是不安全的,为了解决这一隐患网景公司推出了SSL安全套接字协议层,SSL是基于HTTP之下TCP之上的一个协议层,是基于HTTP标准并对TCP传输数据时进行加密,所以HPPTS是HTTP+SSL/TCP的简称。
SSL协议位于TCP/IP协议与各种应用层协议之间,为数据通讯提供安全支持。SSL协议可分为两层: SSL记录协议(SSL Record Protocol):它建立在可靠的传输协议(如TCP)之上,为高层协议提供数据封装、压缩、加密等基本功能的支持。 SSL握手协议(SSL Handshake Protocol):它建立在SSL记录协议之上,用于在实际的数据传输开始前,通讯双方进行身份认证、协商加密算法、交换加密密钥等。

3.初步方案

本来 https 是在 http 的基础上进行加密。使用 SSL 协议进行加密。这样通讯的双方在通讯前就要去做身份校验,通过证书的方式验证身份。原来是证书方面的问题,需要我们调整一下代码,使其信任所有证书(忽略证书的校验),根据不同的HTTP请求工具会有所不同,我们这里用的是HttpClient

,不同的版本的写法有所不同,不过整体思路是一致的,就是信任所有证书

Ø HttpClient <4.3版本

现在让我们将HTTPClient配置为信任所有证书,无论其有效性如何

@Test
	public final void test() 
	  throws GeneralSecurityException {
		String urlOverHttps = "https://www.baidu.com/";
	    HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
	    CloseableHttpClient httpClient = (CloseableHttpClient) requestFactory.getHttpClient();
	    //信用所有证书
	    TrustStrategy acceptingTrustStrategy = (cert, authType) -> true;
	    //NoopHostnameVerifier类:  作为主机名验证工具,实质上关闭了主机名验证,它接受任何
        //有效的SSL会话并匹配到目标主机
	    SSLSocketFactory sf = new SSLSocketFactory(acceptingTrustStrategy, ALLOW_ALL_HOSTNAME_VERIFIER);
	    httpClient.getConnectionManager().getSchemeRegistry().register(new Scheme("https", 8443, sf));
	 
	    ResponseEntity<String> response = new RestTemplate(requestFactory).
	      exchange(urlOverHttps, HttpMethod.GET, null, String.class);
	    assertThat(response.getStatusCode().value(), equalTo(200));
	}

 

Ø HttpClient 4.4及更高版本

使用新的HTTPClient,现在我们有了一个增强的,重新设计的默认SSL主机名验证程序。此外,通过引入SSLConnectionSocketFactory和RegistryBuilder,可以轻松构建

SSLSocketFactory

@Test
	public final void test()
	  throws GeneralSecurityException {
		String urlOverHttps = "https://www.baidu.com/";
//信用所有证书
	    TrustStrategy acceptingTrustStrategy = (cert, authType) -> true;
	    SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build();
	    SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, 
	      NoopHostnameVerifier.INSTANCE);
	     
	    Registry<ConnectionSocketFactory> socketFactoryRegistry = 
	      RegistryBuilder.<ConnectionSocketFactory> create()
	      .register("https", sslsf)
	      .register("http", new PlainConnectionSocketFactory())
	      .build();
	 
	    BasicHttpClientConnectionManager connectionManager = 
	      new BasicHttpClientConnectionManager(socketFactoryRegistry);
	    CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslsf)
	      .setConnectionManager(connectionManager).build();
	 
	    HttpComponentsClientHttpRequestFactory requestFactory = 
	      new HttpComponentsClientHttpRequestFactory(httpClient);
	    ResponseEntity<String> response = new RestTemplate(requestFactory)
	      .exchange(urlOverHttps, HttpMethod.GET, null, String.class);
	    assertThat(response.getStatusCode().value(), equalTo(200));
	}

4.初次回归

根据对应的解决方案,我们同步调整对程序使用HttpClient封装的HTTP请求工具类进行类调整,然后重新发布客户现回归测试发现仍然存在同样的SSL错误,怎么会这样呢?

/**
     * @description 连接池配置
     * 采用PoolingHttpClientConnectionManager  可以为多线程提供并发HTTP请求服务。主要作用就是分配连接、
     * 回收连接等..当请求一个新的连接时,如果连接池有有可用的持久连接,连接管理器就会使用其中的一个,
     * 而不是再创建一个新的连接
     * @author songyl
     * @date 2019年8月15日 上午12:51:20
     */
    private static void configPoolMgr() {

        try {
            /**Http连接使用java.net.Socket类来传输数据。这依赖于ConnectionSocketFactory接口来创建、
             初始化和连接socket。这样也就允许HttpClient的用户在代码运行时,指定socket初始化的代码**/
            ConnectionSocketFactory plainsf = PlainConnectionSocketFactory.getSocketFactory();

            //配置通用的SSL
            TrustStrategy acceptingTrustStrategy = (cert, authType) -> true;
            SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build();
            sslsf = new SSLConnectionSocketFactory(sslContext,
                    NoopHostnameVerifier.INSTANCE);

            //自定义的socket工厂类可以和指定的协议(Http、Https)联系起来,用来创建自定义的连接管理器
            Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                    .register("http", plainsf)
                    .register("https", sslsf)
                    .build();

            //连接池管理器
            connMgr = new PoolingHttpClientConnectionManager(registry);
            //最大连接数
            connMgr.setMaxTotal(MAX_TOTAL);
            //每个路由基础的连接数
            connMgr.setDefaultMaxPerRoute(ROUTE_MAX_TOTAL);
        } catch (Exception e) {
            LOGGER.error("configPoolMgr error: ", e);
//            throw new TbspBaseRuntimeException("连接池配置异常", e);
        }
    }
 /**
     * @return
     * @description 获取HttpClient
     * 添加 PoolingHttpClientConnectionManager connMgr 连接池
     * 添加 HttpRequestRetryHandler retryHandler 重试机制
     * @author songyl
     * @date 2019年8月15日 上午1:08:25
     */
    private static CloseableHttpClient getHttpClient() {
		HttpClientBuilder httpClientBuilder = HttpClients.custom();
		httpClientBuilder.setConnectionManager(connMgr);
		httpClientBuilder.setRetryHandler(retryHandler);
		httpClientBuilder.setSSLSocketFactory(sslsf);
		//创建httpClient
		return httpClientBuilder.build();
    }

5.最终方案

通过忽略SSL证书在客户现场并没有把问题给解决掉,这个时候我们只能再分析客户现场跟我们本地有什么差异,通过了解客户现场再网络链路上对外请求HTTP增加了一层代理服务器,差异如下,客户现场多了代理服务器这一段网络链路。

因此在通过代理服务器访问第三方目标地址时,需要在setProxy()方法中设置代理IP后可以将url中的域名换成这个代理IP,http很简单,但是https这样会报错。

问题:如何使用代理发送https请求?

客户端发送https请求之前会先向这台服务器请求ssl证书,并在客户端对这个证书做一个校验。

而使用代理IP时,实际上请求打到了这个代理IP上,而客户端并不知道这件事,他仍然在等待url域名中所对应的ssl证书,而这代理IP对应的服务器实际上并没有这个证书,导致了https请求失败。

 解决办法:在忽略SSL证书验证的同时应该显式的配置代理地址,通过代理转发到目标地址

// 代理信息
    protected static String proxyUrl;
    
    /**
     * @return
     * @description 获取HttpClient
     * 添加 PoolingHttpClientConnectionManager connMgr 连接池
     * 添加 HttpRequestRetryHandler retryHandler 重试机制
     * @author songyl
     * @date 2019年8月15日 上午1:08:25
     */
    private static CloseableHttpClient getHttpClient() {
		HttpClientBuilder httpClientBuilder = HttpClients.custom();
		httpClientBuilder.setConnectionManager(connMgr);
		httpClientBuilder.setRetryHandler(retryHandler);
		httpClientBuilder.setSSLSocketFactory(sslsf);
		if (proxyUrl != null) {
			HttpHost proxy = HttpHost.create(proxyUrl);
			DefaultProxyRoutePlanner routePlanner = new DefaultProxyRoutePlanner(proxy);
			httpClientBuilder.setRoutePlanner(routePlanner);
		}
		//创建httpClient
		return httpClientBuilder.build();
    }
 

6.再次回归

再次发布客户现场回归测试后我们发现SSL异常问题已彻底解决,同时通过请求日志我们会发现请求底层会进行一次代理服务器的路由转发

 

7.问题总结

通过这个问题的分析跟解决我发现在我们平时做一些基础工具的研发过程中,由于我们所服务的客户的特点(客户存在本地化部署&云部署模式)我们需要更多的考虑客户现场跟我们本地的一些网络链路上的差异,尽可能的考虑程序的兼容性及健壮性,在这个问题上我们初期就应该考虑直连与代理访问两种情况。

  • 大小: 671.8 KB
  • 大小: 200.7 KB
  • 大小: 34.1 KB
分享到:
评论

相关推荐

    Ubuntu/Deepin下Python3.8出现SSL错误的解决方案

    在使用pip3的时候,错误信息如下...而且网上的某些方法用./configure –with-ssl这条命令是无效的,下面给出解决问题的方案。 出现这种错误可以在Modules/Setup中,Ctrl + F查找字符串SSL, 将找到的第一个SSL下面的命

    Win7配置Tomcat6与SSL问题以及解决方案.doc

    1. 将JDK与Tomcat6安装到C盘后,配置SSL时候运行keytool命令无法生成server.keystore(暂未找到合理的解决方案) 2. 将JDK与Tomcat6安装到D盘后,配置SSL时候可以运行keytool命令,并可以生成server.keystore,但是...

    Nginx配置SSL证书出错解决方案

    一、引言 当我们的Linux服务器上当中发布了web项目,有时候需要配置一个SSL证书,这样表示你这...二、错误解决步骤 既然在安装的时候没有编译ssl,难道把nginx卸载重新安装一次?不不不,我们只需要在原有的基础上添加

    Python SSL证书验证问题解决方案

    这篇文章主要介绍了Python SSL证书验证问题解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一、SSL问题 1、在你不启用fiddler时,python代码直接发送...

    Charles抓包Https请求显示Unknown解决方案.pdf

    Charles抓包Https请求显示Unknown解决方案

    【PHP、SSL、证书】报cURL error 60: SSL certificate problem的证书问题解决

    PHP本地环境在调用第三方接口有时会出现cURL error 60: SSL certificate problem: unable to get local issuer certificate的错误提示,这边提供如下解决方案: 1、下载资源,并解压 2、将pem文件放于指定目录下,...

    SQL Server成功与服务器建立连接但是在登录过程中发生错误的快速解决方案

    之前的连接是没问题的,后网上找了资料,根据牛人所说的方案解决了。 1. Exception message 已成功与服务器建立连接,但是在登录过程中发生错误。 (provider: SSL Provider, error: 0 – 接收到的消息异常,或格式不...

    服务器负载均衡解决方案.doc

    深信服科技 AD服务器负载方案 深信服科技有限公司 目录 第1章 概述 1 第2章 需求分析 1 第3章 解决方案 2 3.1 网络拓扑 2 3.2 方案描述 2 3.2.1 方案设计 2 3.2.2 方案实现 3 3.3 产品彩页 4 1. 概述 随着组织机构的...

    Secure Streams converter:HTTP 到 HTTPS 流转换器。 现在您可以摆脱 SSL 错误-开源

    我们为您提供解决方案。 这是我们的 HTTP 到 HTTPS 流转换器,您可以使用它摆脱 SSL 警告并享受现有无线电流 URL 的 https 无线电流。 使用我们的流转换器,您可以享受以下功能: · 删除 SSL 浏览器错误 · 提供...

    C# httpwebrequest访问HTTPS错误处理方法

    试了网上的N种方法,以下是本次的解决方案: ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3; 把网上找到的解决方案列一下,没准就能解决了你的问题 以下是网上找到的解决方案: 1. request....

    Oracle\oracle_EM无法正常登陆解决方案

    打开浏览器在地址栏键入 http://pc-name:port/em 打开登录界面,输入用户名和密码、选择登陆身份点击登录企业管理器,报出错误信息:java.lang.Exception Exception in sending Request null

    微信小程序 HTTPS报错整理常见问题及解决方案

    微信小程序 HTTPS报错常见问题及解决方案 微信小程序开放公测已经一个多月了,因官方需求文档要求后台使用HTTPS请求进行网络通信,不满足条件的域名和协议无法请求。越来越多的开发者纷纷使用SSL证书实践微信小程序...

    微信小程序 Windows2008 R2服务器配置TLS1.2方法

    微信小程序免费SSL证书https、TLS版本问题的解决方案《二十四》request:fail错误(含https解决方案)(真机预览问题把下面的代码复制到PowerShell里运行一下,然后重启服务器。# Enables TLS 1.2 on … 请首先阅读...

    docker-mattermost:最重要的Docker解决方案

    贡献如果您发现此图片很有用,请按照以下方法提供帮助: 发送带有您很棒的新功能和错误修复的请求请求帮助新用户解决他们可能遇到的问题 问题请在问题页面上提出问题请求。 安装映像的自动构建可在Dockerhub上获得...

    FlashFXP.rar绿色免安装中文版

    在 U3 manifest 中添加了 hostCleanUp, 解决了 U3 Lauchpad 较早版本中的一个错误 ”跟踪深层动态链接” 与 ”传送期间更新目录缓存” 的内部值弄反了 Vista 兼容问题,即:当进行拖动操作时,投放目标没有适当...

    小程序开发填坑《十三》微信小程序部署HTTPS报错怎么办

    下面我们就来分析一下常见的SSL证书报错现象和解决方案,以及SSL证书的选择。   (此图片来源于网络,如有侵权,请联系删除! )     常见的SSL证书问题和处理方法 常见问题一:在微信小程序内测的过程中,几乎每个...

    PHP和MySQL WEB开发(第4版)

    18.2 使用加密套接字层(SSL) 18.3 屏蔽用户的输入 18.4 提供安全存储 18.5 存储信用卡号码 18.6 在PHP中使用加密技术 18.6.1 安装GPG 18.6.2 测试GPG 18.7 进一步学习 18.8 下一章 第四篇 PHP的高级技术 第19章 ...

    PHP和MySQL Web开发第4版pdf以及源码

    目录 读者反馈 ...18.2 使用加密套接字层(SSL) 18.3 屏蔽用户的输入 18.4 提供安全存储 18.5 存储信用卡号码 18.6 在PHP中使用加密技术 18.6.1 安装GPG 18.6.2 测试GPG 18.7 进一步学习 ...

    PHP和MySQL Web开发第4版

    目录 读者反馈 ...18.2 使用加密套接字层(SSL) 18.3 屏蔽用户的输入 18.4 提供安全存储 18.5 存储信用卡号码 18.6 在PHP中使用加密技术 18.6.1 安装GPG 18.6.2 测试GPG 18.7 进一步学习 ...

Global site tag (gtag.js) - Google Analytics