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

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

Exception in thread "main" javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
	at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
	at sun.security.ssl.Alerts.getSSLException(Alerts.java:154)
	at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:2023)
	at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1125)
	at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
	at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
	at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
	at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:394)
	at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:353)
	at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:134)
	at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:353)
	at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:380)
	at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236)
	at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:184)
	at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:88)
	at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
	at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184)
	at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
	at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:107)

查阅了不少资料,大部分都说是由于java自己安全机制引发的,从新去官网下载jar包替换便可。如下是修改方法:java

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

JDK7 JDK8apache

具体异常教程以下:传送门编程

在缘由的第二种里面,有一个须要校验自己的TLS的版本和服务端版本是否一致,我就是在这里出了问题,致使的这个异常。由于我一直用的默认参数去建立新的套接字对象。下面是我用Charles拦截的请求的header信息:安全

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

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

/**
	 * 获取SSL套接字对象 重点重点:设置tls协议的版本
	 * 
	 * @return
	 */
	public static SSLContext createIgnoreVerifySSL() {
		SSLContext sslContext = null;// 建立套接字对象
		try {
			sslContext = SSLContext.getInstance("TLSv1.2");//指定TLS版本
		} catch (NoSuchAlgorithmException e) {
			SourceCode.getInstance().output("建立套接字失败!", e);
		}
		// 实现X509TrustManager接口,用于绕过验证
		X509TrustManager trustManager = new X509TrustManager() {
			@Override
			public void checkClientTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
					String paramString) throws CertificateException {
			}
 
			@Override
			public void checkServerTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
					String paramString) throws CertificateException {
			}
 
			@Override
			public java.security.cert.X509Certificate[] getAcceptedIssuers() {
				return null;
			}
		};
		try {
			sslContext.init(null, new TrustManager[] { trustManager }, null);//初始化sslContext对象
		} catch (KeyManagementException e) {
			SourceCode.getInstance().output("初始化套接字失败!", e);
		}
		return sslContext;
	}

下面是建立https协议的client的方法,其中用到了链接池的使用:框架

/**
	 * 获取https协议请求对象
	 * 
	 * @return
	 */
	public static CloseableHttpClient getCloseableHttpsClients() {
		// 采用绕过验证的方式处理https请求
		SSLContext sslcontext = createIgnoreVerifySSL();
		// 设置协议http和https对应的处理socket连接工厂的对象
		Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory> create()
				.register("http", PlainConnectionSocketFactory.INSTANCE)
				.register("https", new SSLConnectionSocketFactory(sslcontext)).build();
		PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
		HttpClients.custom().setConnectionManager(connManager);
		// 建立自定义的httpsclient对象
		CloseableHttpClient client = HttpClients.custom().setConnectionManager(connManager).build();
		return client;
	}

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

技术类文章精选

非技术文章精选

大咖风采

点击查看公众号地图

相关文章
相关标签/搜索