前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >httpclient发送https协议请求以及javax.net.ssl.SSLHandshakeException解决办法

httpclient发送https协议请求以及javax.net.ssl.SSLHandshakeException解决办法

作者头像
FunTester
发布2019-10-17 16:30:27
3.6K0
发布2019-10-17 16:30:27
举报
文章被收录于专栏:FunTesterFunTester

本人在做接口自动化的过程中,遇到了请求第三方https协议请求,在经过了短暂的知识重新学习之后,写完代码执行起来总是遇到一个异常,在用客户端执行请求的时候抛出来的,下面是异常的信息:

 1Exception in thread "main" javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
 2    at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
 3    at sun.security.ssl.Alerts.getSSLException(Alerts.java:154)
 4    at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:2023)
 5    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1125)
 6    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
 7    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
 8    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
 9    at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:394)
10    at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:353)
11    at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:134)
12    at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:353)
13    at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:380)
14    at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236)
15    at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:184)
16    at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:88)
17    at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
18    at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184)
19    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
20    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:107)

查阅了很多资料,大部分都说是因为java本身安全机制引起的,重新去官网下载jar包替换即可。以下是修改方法:

因为jdk中jce的安全机制导致报的错,要去oracle官网下载对应的jce包替换jdk中的jce包。 jce所在地址:%JAVA_HOME%\jre\lib\security里的local_policy.jar,US_export_policy.jar

JDK7:http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html

JDK8:http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html

具体异常教程随处可见,这里就不再赘述。

在原因的第二种里面,有一个需要校验本身的TLS的版本和服务端版本是否一致,我就是在这里出了问题,导致的这个异常。因为我一直用的默认参数去创建新的套接字对象。下面是我用Charles拦截的请求的header信息:

上面圈起来的地方就是现实的服务器的TLS版本,相应地改掉自己代码的中设置版本的地方即可。

下面是我的代码:大多数参考了网上的教程,自己做了一些修改,大同小异。下面是获取SSLcontext对象的方法,实现了X509TrustManager接口,里面方法不用修改。

 1    /**
 2     * 获取SSL套接字对象 重点重点:设置tls协议的版本
 3     * 
 4     * @return
 5     */
 6    public static SSLContext createIgnoreVerifySSL() {
 7        SSLContext sslContext = null;// 创建套接字对象
 8        try {
 9            sslContext = SSLContext.getInstance("TLSv1.2");//指定TLS版本
10        } catch (NoSuchAlgorithmException e) {
11            SourceCode.getInstance().output("创建套接字失败!", e);
12        }
13        // 实现X509TrustManager接口,用于绕过验证
14        X509TrustManager trustManager = new X509TrustManager() {
15            @Override
16            public void checkClientTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
17                    String paramString) throws CertificateException {
18            }
19
20            @Override
21            public void checkServerTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
22                    String paramString) throws CertificateException {
23            }
24
25            @Override
26            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
27                return null;
28            }
29        };
30        try {
31            sslContext.init(null, new TrustManager[] { trustManager }, null);//初始化sslContext对象
32        } catch (KeyManagementException e) {
33            SourceCode.getInstance().output("初始化套接字失败!", e);
34        }
35        return sslContext;
36    }

下面是创建https协议的client的方法,其中用到了连接池的使用:

 1    /**
 2     * 获取https协议请求对象
 3     * 
 4     * @return
 5     */
 6    public static CloseableHttpClient getCloseableHttpsClients() {
 7        // 采用绕过验证的方式处理https请求
 8        SSLContext sslcontext = createIgnoreVerifySSL();
 9        // 设置协议http和https对应的处理socket链接工厂的对象
10        Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory> create()
11                .register("http", PlainConnectionSocketFactory.INSTANCE)
12                .register("https", new SSLConnectionSocketFactory(sslcontext)).build();
13        PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
14        HttpClients.custom().setConnectionManager(connManager);
15        // 创建自定义的httpsclient对象
16        CloseableHttpClient client = HttpClients.custom().setConnectionManager(connManager).build();
17        return client;
18    }

还有一个继承httpclient类,重写createDefault()方法来实现请求https的,经过实验,对于一些https协议是没有问题的。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-10-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 FunTester 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档