一个干净的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请求

相关推荐
Channing Lewis9 分钟前
sql server如何创建表导入excel的数据
数据库·oracle·excel
秃头摸鱼侠10 分钟前
MySQL安装与配置
数据库·mysql·adb
UGOTNOSHOT15 分钟前
每日八股文6.3
数据库·sql
行云流水行云流水38 分钟前
数据库、数据仓库、数据中台、数据湖相关概念
数据库·数据仓库
John Song40 分钟前
Redis 集群批量删除key报错 CROSSSLOT Keys in request don‘t hash to the same slot
数据库·redis·哈希算法
IvanCodes1 小时前
七、Sqoop Job:简化与自动化数据迁移任务及免密执行
大数据·数据库·hadoop·sqoop
tonexuan1 小时前
MySQL 8.0 绿色版安装和配置过程
数据库·mysql
JohnYan1 小时前
工作笔记- 记一次MySQL数据移植表空间错误排除
数据库·后端·mysql
我最厉害。,。2 小时前
Windows权限提升篇&数据库篇&MYSQL&MSSQL&ORACLE&自动化项目
数据库·mysql·sqlserver
远方16092 小时前
20-Oracle 23 ai free Database Sharding-特性验证
数据库·人工智能·oracle