场景
写一个调用第三方登陆的模块,本地开发的时候使用Apache HttpClient时候,就按照一般的POST JSon数据能够正确获取返回数据,但是当部署到线上环境的时候,就报
Exception in thread "main" javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
然后google了一下,通过下面这张图
和overflow 上的各种大神的解释,大概的原因(英语水平受限)就是TLS版本冲突。
既然jdk1.8是ok的,jdk1.7有问题,那就是要把TLS版本设置为TLSv1.2,试过用Httpclient设置,失败!
看到许多人说 使用第三方的Bouncy Castle可以解决,然后又继续找Bouncy Castle的方法,但是很多都说的很简单,终于发现一个大神能说仔细了。
点击查看
嗯,看来这次没跑了,好了直接贴代码吧(虽然和链接里面的大致一样)
第一步,加maven依赖
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.54</version>
</dependency>
然后是建立一个TLSSocketConnectionFactory
package com.netease.urs.outerlogin.util;
import java.io.*;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.*;
import java.security.cert.*;
import java.util.*;
import javax.net.ssl.*;
import javax.security.cert.X509Certificate;
import org.bouncycastle.crypto.tls.*;
import org.bouncycastle.crypto.tls.Certificate;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
/**
* Created by hzlizhou on 2016/9/9.
*/
public class TLSSocketConnectionFactory extends SSLSocketFactory {
static {
if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
Security.addProvider(new BouncyCastleProvider());
}
}
@Override
public Socket createSocket(Socket socket, final String host, int port,
boolean arg3) throws IOException {
if (socket == null) {
socket = new Socket();
}
if (!socket.isConnected()) {
socket.connect(new InetSocketAddress(host, port));
}
final TlsClientProtocol tlsClientProtocol = new TlsClientProtocol(socket.getInputStream(), socket.getOutputStream(), new SecureRandom());
return _createSSLSocket(host, tlsClientProtocol);
}
@Override
public String[] getDefaultCipherSuites() {
return null;
}
@Override
public String[] getSupportedCipherSuites() {
return null;
}
@Override
public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
throw new UnsupportedOperationException();
}
@Override
public Socket createSocket(InetAddress host, int port) throws IOException {
throw new UnsupportedOperationException();
}
@Override
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {
return null;
}
@Override
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
throw new UnsupportedOperationException();
}
private SSLSocket _createSSLSocket(