有没有童鞋遇到个问题,就是公司项目太老,用的是JDK1.7,JDK1.8以下的,由于需要调用HTTPS相关接口导致SSLException等异常,
解决办法尝试过的童鞋会采用升级JDK1.8以上,了解版本更新的童鞋就会知道,JDK1.8已经默认支持了HTTPS相关支持。
由于项目老,升级JDK导致很多地方出现问题。
JDK1.7 默认是 TSLv1, 但是可以支持 TSLv1.1,TSLv1.2;
JDK1.8 默认是 TSLv1.2
由于JDK1.8以下,发送https请求会导致各种SSL异常信息报错
常见的问题是:
先介绍HTTPS
HTTPS(全称:Hyper Text Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的安全版。
即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。 它是一个URI scheme(抽象标识符体系),句法类同http:体系。
用于安全的HTTP数据传输。https:URL表明它使用了HTTP,但HTTPS存在不同于HTTP的默认端口及一个加密/身份验证层(在HTTP与TCP之间)。
这个系统的最初研发由网景公司(Netscape)进行,并内置于其浏览器Netscape Navigator中,提供了身份验证与加密通讯方法。
现在它被广泛用于万维网上安全敏感的通讯,例如交易支付方面。–百度百科
HTTPS和HTTP的区别主要为以下四点:
一、https协议需要到ca申请证书,一般免费证书很少,需要交费。
二、http是超文本传输协议,信息是明文传输,https 则是具有安全性的ssl加密传输协议。
三、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
四、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
常用的方法:
1:System.setProperty(“https.protocols”,“SSLv3,TLSv1,TLSv1.1,TLSv1.2…”);
很多童鞋用这样的一段代码,可能有些灵,也有可能出现时不时可以,时不时不可以。
2:根据官网的提示替换jar 包
C:\Program Files\Java\jdk1.8.0_40\jre\lib\security local_policy.jar和 US_export_policy.jar
调用报错:javax.net.ssl.SSLException: java.lang.RuntimeException: Could not generate DH keypair
然后继续:
下载2个jar包: bcprov-ext-jdk15on-1.52.jar 和 bcprov-jdk15on-1.52.jar
复制两个jar包到: $JAVA_HOME/jre/lib/ext
需修改: $JAVA_HOME/jre/lib/security/java.security
添加security.provider.10=org.bouncycastle.jce.provider.BouncyCastleProvider
也有下载证书的等,但是太过于繁琐。
本文推荐了代码编写(继承重写源码),使用第三方Bouncy Castle,既搬既用(CV大法唯快不破)。
选择:
单向认证:是由于JDK1.8以下不支持tsl1.x协议问题导致,可以适用单向认证的代码
双向认证:假设HTTPS是第三方的,你调第三方的https,对方的证书是自制的或者CA的双向认证(具体待研究),
发起请求的的时候需要携带证书(第三方提供的)发送,就可以适用双向认证的代码。
相关JAR包
bcprov-jdk15on-1.57.jar
一:
建立两个类:
import javax.net.ssl.HttpsURLConnection;
import java.io.IOException;
import java.io.InputStream;
import java.net.*;
/**
- JDK1.7,1.8以下工具类
- Created by BugRoot
*/
public class HttpsUrlConnectionForTLS {
public HttpURLConnection createConnection(URI uri) throws IOException {
URL url = uri.toURL();
URLConnection connection = url.openConnection();
HttpsURLConnection httpsURLConnection = (HttpsURLConnection) connection;
httpsURLConnection.setSSLSocketFactory(new TLSSocketConnectionFactory());
return httpsURLConnection;
}
public static String getResponse(HttpURLConnection Conn) throws IOException {
InputStream is;
if (Conn.getResponseCode() >= 400) {
is = Conn.getErrorStream();
} else {
is = Conn.getInputStream();
}
String response = “”;
byte buff[] = new byte[512];
int b = 0;
while ((b = is.read(buff, 0, buff.length)) != -1) {
response += new String(buff, 0, b);
}
is.close();
System.out.println(response);
return response;
}
}
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.KeyStore;
import java.security.Principal;
import java.security.SecureRandom;
import java.security.Security;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateFactory;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;
import javax.net.ssl.HandshakeCompletedListener;
import javax.net.ssl.SSLPeerUnverifiedException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSessionContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.security.cert.X509Certificate;
import org.bouncycastle.crypto.tls.*;
import org.bouncycastle.crypto.tls.Certificate;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
/**
-
重写SSLSocketFactory
-
Created by BugRoot
*/
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()) {