java SSLContext创建方式

 更新时间:2024年01月23日 10:09:29   作者:shuxiaohua  
这篇文章主要介绍了java SSLContext创建方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

概述

HTTPS相对于HTTP多了SSL(security sock layer),应用层将数据丢给TCP时,需要经过SSL层的加密处理;TCP层的数据丢给应用层时,需要经过SSL层的解密处理。

因此网络中传输的都是加密后的数据,提高的通信的安全性。

HTTPS除了拥有传输加密的功能,还提供身份认证,防止对端伪造身份。这个是通过HTTPS证书实现。

注下图中对HTTPS握手过程进行简化,握手过程的关键步骤就是证书校验及对称加密秘钥的协商,另外客户端证书的校验是可选的。

问题

标准证书都是第三方机构颁发的,需要付费找第三方机构申请。有些出于节省成本或者省事的目的,一般会使用工具生成自签名的证书。

浏览器访问这种自签名证书的网址时就会弹出不安全的提示,如果是java代码访问这种网址时就会抛出异常。

解决这种问题有2个途径,一种是忽略证书认证,另一种就是将自签名的证书添加到受信证书库中。

SSLContext关键参数说明

SSLContext都是通过SSLContext.getInstance(String protocol)方法获取,获取后需要调用init方法初始化。

init方法签名如下:

public final void init(KeyManager[] km, TrustManager[] tm,SecureRandom random)

KeyManager

  • 用于HTTPS双向认证时,客户端向服务端发送的认证信息(证书);与不同的服务端交互时,客户端可能用不同的身份(证书),所以需要KeyManager进行管理。
  • 如果只是单向认证,KeyManager[]可以为空

TrustManager

  • 用于客户端检测服务端发送过来的证书。

KeyStore:只是单纯的存储证书、秘钥数据,不包含任何逻辑。

TrustManager,KeyManager可以使用KeyStore得到证书列表进行相应的业务处理。

忽略证书认证

有些语言比如Python是可以修改全局配置去忽略证书检查,但是Java好像没有提供这种功能,所以需要覆写证书认证的类X509TrustManager 。

忽略证书认证后,双方通信的时候仍然是加密的,只是无法对服务端的身份进行认证,有服务端伪造的风险。如果都是在内网,可以采用这种简洁的手法。

public SSLContext buildSSLContext() throws Exception {
    X509TrustManager x509TrustManager = new X509TrustManager() {
        @Override
        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        }
        @Override
        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        }
        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[0];
        }
    };
    SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
    sslContext.init((KeyManager[]) null, new X509TrustManager[] {x509TrustManager}, (SecureRandom) null);
    return sslContext;
}

将自签名证书放到受信证书库

将证书直接导入到JDK的证书库

待续

通过编码的方式将证书放到受信证书列表中

@Override
public SSLContext buildSSLContext() throws Exception {
    KeyStore keyStore = buildKeyStore();
    TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    tmf.init(keyStore);
    SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
    sslContext.init((KeyManager[]) null, tmf.getTrustManagers(), (SecureRandom) null);
    return sslContext;
}

private KeyStore buildKeyStore() throws Exception {
    // 获取自签名的证书
    List<X509Certificate> certs = loadHttpsCerts();
    KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
    keyStore.load(null, null);
    TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
            TrustManagerFactory.getDefaultAlgorithm());
    trustManagerFactory.init((KeyStore) null);
    // 获得jdk证书库中的证书
    Arrays.stream(trustManagerFactory.getTrustManagers())
            .filter(manager -> manager instanceof X509TrustManager)
            .findFirst()
            .ifPresent(manager -> {
                List<X509Certificate> jdkCerts = Arrays.asList(((X509TrustManager) manager).getAcceptedIssuers());
                certs.addAll(jdkCerts);
            });
    certs.stream().forEach(cert -> {
            keyStore.setCertificateEntry(cert.getSubjectDN().getName(), cert);
    });
    return keyStore;
}

private List<X509Certificate> loadHttpsCerts() throws IOException, CertificateException {
    List<X509Certificate> certs = new ArrayList<>(32);
    PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
    Resource[] resources = resolver.getResources(HTTPS_CERTS_PATH);
    for (Resource resource : resources) {
        InputStream inStream = resource.getInputStream();
        CertificateFactory factory = CertificateFactory.getInstance("X.509");
        X509Certificate cert = (X509Certificate) factory.generateCertificate(inStream);
        certs.add(cert);
    }
    return certs; 
}

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。 

相关文章

  • Java去掉小数点后面无效0的方案与建议

    Java去掉小数点后面无效0的方案与建议

    当前小数点后面的位数过多的时候,多余的0没有实际意义,下面这篇文章主要给大家介绍了关于Java去掉小数点后面无效0的方案与建议,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
    2022-07-07
  • Java基础之面向对象机制(多态、继承)底层实现

    Java基础之面向对象机制(多态、继承)底层实现

    这篇文章主要介绍了Java基础之面向对象机制(多态、继承)底层实现,文中有非常详细的代码示例,对正在学习java的小伙伴们有非常好的帮助,需要的朋友可以参考下
    2021-04-04
  • SpringBoot如何集成Kaptcha验证码

    SpringBoot如何集成Kaptcha验证码

    本文介绍了如何在Java开发中使用Kaptcha生成验证码的功能,包括在pom.xml中配置依赖、在系统公共配置类中添加配置、在控制器中添加生成验证码的方法,以及前端页面如何引用,同时,还补充了Kaptcha的更多配置属性及其默认值
    2025-01-01
  • SpringBoot集成极光推送完整实现代码

    SpringBoot集成极光推送完整实现代码

    本文主要介绍了SpringBoot集成极光推送完整实现代码,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-12-12
  • Windows 下安装配置 Eclipse详细教程

    Windows 下安装配置 Eclipse详细教程

    Eclipse是一款非常优秀的开源IDE,非常适合Java开发,由于支持插件技术,受到了越来越多的开发者的欢迎。配合众多令人眼花缭乱的插件,完全可以满足从企业级Java应用到手机终端Java游戏的开发。本文将带您手把手步入Eclipse的广阔天地
    2016-09-09
  • idea引包导包为灰色如何解决

    idea引包导包为灰色如何解决

    这篇文章主要介绍了idea引包导包为灰色的问题及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-03-03
  • java中sleep方法和wait方法的五个区别

    java中sleep方法和wait方法的五个区别

    这篇文章主要介绍了java中sleep方法和wait方法的五个区别,sleep 方法和 wait 方法都是用来将线程进入休眠状态,但是又有一些区别,下面我们就一起来看看吧
    2022-05-05
  • SpringBoot起步依赖和自动配置基本介绍

    SpringBoot起步依赖和自动配置基本介绍

    这篇文章主要介绍了SpringBoot起步依赖和自动配置,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-04-04
  • 解析Java设计模式编程中命令模式的使用

    解析Java设计模式编程中命令模式的使用

    这篇文章主要介绍了Java设计模式编程中命令模式的使用,在一些处理请求响应的场合经常可以用到命令模式的编程思路,需要的朋友可以参考下
    2016-02-02
  • Spring之IOC详解

    Spring之IOC详解

    本文主要介绍了Spring中的IOC的相关知识。具有很好的参考价值。下面跟着小编一起来看下吧
    2017-03-03

最新评论