javax.net.ssl.SSLException: Received fatal alert: protocol_version 问题解决

记录一次线上bug修改过程。

线上服务中有一个需要调用对接接口的业务,对接的接口是 https协议的,之前请求一直没有问题,最近对方反馈收不到我们的请求了,所以到线上看了下,发现了了一些错误日志:

javax.net.ssl.SSLException: Received fatal alert: protocol_version
        at sun.security.ssl.Alerts.getSSLException(Alerts.java:208) ~[na:1.7.0_45]
        at sun.security.ssl.Alerts.getSSLException(Alerts.java:154) ~[na:1.7.0_45]
        at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1959) ~[na:1.7.0_45]
        at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1077) ~[na:1.7.0_45]
        at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1312) ~[na:1.7.0_45]
        at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1339) ~[na:1.7.0_45]
        at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1323) ~[na:1.7.0_45]
        ...

查了相关资料,说是因为JDK的版本问题导致会使用不同的TLS协议。

我检查了下线上JDK的版本,是1.7版本,1.7版本的JDK默认是使用TLS协议。两种办法解决这个问题

  1. 调整了线上JDK的版本到1.8,1.8版本的JDK默认使用TLSv1.2 协议,调整后此问题就没有了。

  2. 当然还有一种办法,就是给在JDK1.7的环境下,主动设置使用TLS1.2 协议,不是使用默认的TLS协议。此方法还可以解决https正式验证问题。

CloseableHttpClient httpClient =  HttpClients.custom().
						setRetryHandler(new DefaultHttpRequestRetryHandler(0, false))
						.setSSLSocketFactory(buildSslSocketFactoryForIgnoreCertificate())
						.build();
						
private static SSLSocketFactory buildSslSocketFactoryForIgnoreCertificate() throws NoSuchAlgorithmException, KeyManagementException {

		X509TrustManager trustManager = new X509TrustManager() {

			@Override
			public void checkClientTrusted(X509Certificate[] chain, String authType) throws java.security.cert.CertificateException {
			}

			@Override
			public void checkServerTrusted(X509Certificate[] chain, String authType) throws java.security.cert.CertificateException {
			}

			@Override
			public X509Certificate[] getAcceptedIssuers() {
				return null;
			}

		};

		SSLContext sslcontext = SSLContext.getInstance("TLSv1.2");

		sslcontext.init(null, new TrustManager[]{trustManager}, null);

		SSLSocketFactory sslSocketFactory = new SSLSocketFactory(sslcontext);

		sslSocketFactory.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

		return sslSocketFactory;

	}

之所以之前一直正常,后来请求失败。我感觉很大可能是对方的服务器限制了TLS协议的请求。

关于TLS协议和SSL的区别及介绍,可以看此文章:https://kb.cnblogs.com/page/197396/

你可能感兴趣的:(Java-http)