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

相关推荐
尘浮生2 分钟前
Java项目实战II基于微信小程序的校运会管理系统(开发文档+数据库+源码)
java·开发语言·数据库·微信小程序·小程序·maven·intellij-idea
偶尔。5353 分钟前
什么是事务?事务有哪些特性?
数据库·oracle
安迁岚5 分钟前
【SQL Server】华中农业大学空间数据库实验报告 实验六 视图
数据库·sql·mysql·oracle·实验报告
xoxo-Rachel15 分钟前
(超级详细!!!)解决“com.mysql.jdbc.Driver is deprecated”警告:详解与优化
java·数据库·mysql
JH30731 小时前
Oracle与MySQL中CONCAT()函数的使用差异
数据库·mysql·oracle
蓝染-惣右介1 小时前
【MyBatisPlus·最新教程】包含多个改造案例,常用注解、条件构造器、代码生成、静态工具、类型处理器、分页插件、自动填充字段
java·数据库·tomcat·mybatis
冷心笑看丽美人1 小时前
Spring框架特性及包下载(Java EE 学习笔记04)
数据库
hgdlip2 小时前
主IP地址与从IP地址:深入解析与应用探讨
网络·网络协议·tcp/ip
武子康2 小时前
Java-07 深入浅出 MyBatis - 一对多模型 SqlMapConfig 与 Mapper 详细讲解测试
java·开发语言·数据库·sql·mybatis·springboot
代码吐槽菌2 小时前
基于SSM的毕业论文管理系统【附源码】
java·开发语言·数据库·后端·ssm