你是不是想要写一个尽量干净的SSL连接,最好能够完全通过JDK就能完成,不需要借助任何其他依赖,那么看这篇博客就对了。
我会将这部分的代码展示出来,作为分享,作为回报你们应该也多多的分享自己的作品!
我这里分两个类,一个是包含请求方法的类,一个是实现X509TrustManager接口的类。
我这里做了一个比较丰富例子,那么我介绍一下.
- 对本地ES发起的一个SSL请求
- POST请求类型
- 含有账号密码认证BASIC Auth
- 请求体内容为JSON格式
额外说明
因为是SSL请求必不可少就是信任问题,面对信任问题,SSL有单向和双向认证,我这里很简单就是单项验证,请求方 验证响应方 ,那么作为请求的发起程序就需要有信任证书库,库里面要有响应方的证书的签发者即根证书。这里我们可以
- 导入JDK默认的证书库中
借助JDK自带的keytool 工具将根证书放到一个信任证书库中,JDK有一个默认的库,JDK8中的位置是JAVA_HOME\jre\lib\security ,名字是cacerts 密码是changeit,8以上的JDK版本证书位置会不一样,但是名字和密码都是一样的。
-
导入证书
//说明 -keystore 是证书库名 -file后面是证书名称, -alias是证书在证书库中别名方便我们找到他
keytool -import -keystore cacerts -file root.cer -alias xxx-root
- 自建证书库
也可以我们自己建一个库里面放根证书,然后将路径配置到系统配置中。
-
建立证书库
//说明 -keystore 是证书库名如果没有就会自动创建库然后做导入操作 -file后面是证书名称, -alias是证书在证书库中别名方便我们找到他
keytool -import -keystore mycacerts -file root.cer -alias xxx-root -
路径和密码配置
java
System.setProperty("javax.net.ssl.trustStore", TrustStorePath);
System.setProperty("javax.net.ssl.trustStorePassword", TrustStorePassword);
如果没有做上面的两个步骤来保证单向认证的畅通,那么尝试建立连接的话就会报以下错误。
PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
代码
我这里提供了一个跳过验证过程也就是insecure的模式,需要实现一个X509TrustManager接口,将其中的验证方法置空,就不用验证书了。但是记住这是存在风险的,在正式环境中切勿这样做。
java
package com.java;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import java.io.*;
import java.net.Authenticator;
import java.net.MalformedURLException;
import java.net.PasswordAuthentication;
import java.net.URL;
public class REST {
public static void main(String[] args) throws IOException {
String url = "https://xxx.xxx.xxx.xxx:9200/index/_search";
// String url = "https://www.sun.com";
String data = "{\t\t\n" +
"\t\t\"query\": {\n" +
" \"bool\": {\n" +
" \"must\": [\n" +
" {\"match\": {\n" +
" \"status\": 1\n" +
" }},\n" +
" {\"match\": {\n" +
" \"xx_name\": \"xxxx\"\n" +
" }}\n" +
" ]\n" +
" }\n" +
"\t\t}}";
String res = httpRequest(url, data);
}
public static String httpRequest(String httpsUrl, String data) {
/**
*下面两行就是指定自建库位置和密码的配置
*当你导入了根证书或者配置了自建库下面的四行空验证insecure模式代码就可以去掉,推荐证书链完整的验证方式
*/
//System.setProperty("javax.net.ssl.trustStore", "F:\\JDKversions\\JDK11\\lib\\security\\mycacerts");
//System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
HttpsURLConnection urlCon = null;
try {
urlCon = (HttpsURLConnection)(new URL(httpsUrl)).openConnection();
urlCon.setDoInput(true);
urlCon.setDoOutput(true);
urlCon.setRequestMethod("POST");
urlCon.setRequestProperty("Content-Type", "application/json");
//下面的四行就是为了配置一个自定义的空验证,即不需要验证就建立连接的一个insecure模式,不建议
TrustManager[] tm = {new MyX509TrustManager ()};
SSLContext sslContext = SSLContext.getInstance("SSL","SunJSSE");
sslContext.init(null, tm, new java.security.SecureRandom());
urlCon.setSSLSocketFactory(sslContext.getSocketFactory());
Authenticator authenticator = new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("xxxxxx", "xxxx".toCharArray());
}
};
urlCon.setAuthenticator(authenticator);
urlCon.setRequestProperty("Content-Length", String.valueOf(data.getBytes().length));
urlCon.setUseCaches(false);
urlCon.getOutputStream().write(data.getBytes("utf-8"));
urlCon.getOutputStream().flush();
urlCon.getOutputStream().close();
BufferedReader in = new BufferedReader(new InputStreamReader(urlCon.getInputStream(), "utf-8"));
StringBuffer sb = new StringBuffer();
String line;
while((line = in.readLine()) != null) {
sb.append(line + "\r\n");
}
return sb.toString();
} catch (MalformedURLException var6) {
var6.printStackTrace();
} catch (IOException var7) {
var7.printStackTrace();
} catch (Exception var8) {
var8.printStackTrace();
}
return null;
}
}
java
package com.java;
import javax.net.ssl.X509TrustManager;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
public class MyX509TrustManager implements X509TrustManager {
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}
参考博客