问题示例
@Test
public void linkTest() throws Exception {
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> forEntity = restTemplate.getForEntity("https://www.beetel.in/", String.class);
System.out.println(forEntity.getBody());
}
错误信息
SSL 协议版本不一致
Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: protocol_version
at sun.security.ssl.Alert.createSSLException(Alert.java:131)
at sun.security.ssl.Alert.createSSLException(Alert.java:117)
at sun.security.ssl.TransportContext.fatal(TransportContext.java:314)
at sun.security.ssl.Alert$AlertConsumer.consume(Alert.java:293)
at sun.security.ssl.TransportContext.dispatch(TransportContext.java:187)
at sun.security.ssl.SSLTransport.decode(SSLTransport.java:154)
at sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1198)
at sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1107)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:400)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:372)
at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:436)
at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:384)
at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:142)
at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:376)
JDK1.8 支持的TLS/SSL协议
https://blogs.oracle.com/java/post/diagnosing-tls-ssl-and-https
- TLSv1.2 (默认)
- TLSv1.1
- TLSv1
- SSLv3
解决方案
- 升级JDK版本(本文不描述)
- 扩展组件包:
openjsse
openjsse组件包
- 引入依赖(根据自身JDK版本选择依赖版本)
<dependency>
<groupId>org.openjsse</groupId>
<artifactId>openjsse</artifactId>
<version>1.1.4</version>
</dependency>
- 代码中加入
Security.insertProviderAt(new OpenJSSE(), 1);
@Test
public void linkTest() throws Exception {
Security.insertProviderAt(new OpenJSSE(), 1);
SSLContext build = SSLContexts.custom().build();
CloseableHttpClient httpClient = HttpClients.custom().setSSLContext(build).setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE).build();
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient);
RestTemplate restTemplate = new RestTemplate(factory);
ResponseEntity<String> forEntity = restTemplate.getForEntity("https://www.beetel.in/", String.class);
System.out.println(forEntity.getBody());
}