一个干净的SSL连接

你是不是想要写一个尽量干净的SSL连接,最好能够完全通过JDK就能完成,不需要借助任何其他依赖,那么看这篇博客就对了。

我会将这部分的代码展示出来,作为分享,作为回报你们应该也多多的分享自己的作品!

我这里分两个类,一个是包含请求方法的类,一个是实现X509TrustManager接口的类。

我这里做了一个比较丰富例子,那么我介绍一下.

  1. 对本地ES发起的一个SSL请求
  2. POST请求类型
  3. 含有账号密码认证BASIC Auth
  4. 请求体内容为JSON格式

额外说明

因为是SSL请求必不可少就是信任问题,面对信任问题,SSL有单向和双向认证,我这里很简单就是单项验证,请求方 验证响应方 ,那么作为请求的发起程序就需要有信任证书库,库里面要有响应方的证书的签发者即根证书。这里我们可以

  1. 导入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

  1. 自建证书库

也可以我们自己建一个库里面放根证书,然后将路径配置到系统配置中。

  • 建立证书库

    //说明 -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];
    }

}

参考博客

java HttpsURLConnection发送https请求

相关推荐
喵叔哟13 分钟前
重构代码之移动字段
java·数据库·重构
念白44317 分钟前
智能病历xml提取
数据库·sql·oracle
qingy_204621 分钟前
【JavaWeb】JavaWeb入门之XML详解
数据库·oracle
大数据面试宝典25 分钟前
用AI来写SQL:让ChatGPT成为你的数据库助手
数据库·人工智能·chatgpt
努力的小雨30 分钟前
快速上手 KSQL:轻松与数据库交互的利器
数据库·经验分享
Gentle58632 分钟前
labview中连接sql server数据库查询语句
数据库·labview
Gentle58633 分钟前
labview用sql server数据库存取数据到一个单元格
数据库·labview
2401_8576363936 分钟前
共享汽车管理新纪元:SpringBoot框架应用
数据库·spring boot·汽车
菲兹园长36 分钟前
表的设计(MYSQL)
数据库·mysql
Java Fans1 小时前
MySQL数据库常用命令大全(完整版——表格形式)
数据库·mysql