栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

springboot通过已有的server.key,crt,ca证书生成jks文件并开启HTTPS 并启动双向认证+动态加载信任库

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

springboot通过已有的server.key,crt,ca证书生成jks文件并开启HTTPS 并启动双向认证+动态加载信任库

Springboot开启双向验证
  • yaml文件配置
  • 证书生成
  • 热加载信任库
  • 测试

yaml文件配置
server:
  port: 6820
  ssl:
    enabled: true
    key-store: C:UsersAdministratorDesktopserver.jks ## 这里放到桌面,原因后面会说
    key-store-password: changeit
    key-alias: localhost
    key-store-type: JKS
    trust-store: C:UsersAdministratorDesktopserver.jks
    trust-store-password: changeit ## 密码最好用这个
    trust-store-provider: SUN
    trust-store-typ: JKS
    client-auth: need ## 开启双向认证的必要条件
证书生成
1.通过服务端crt和key生成p12格式证书
openssl pkcs12 -export -in server.crt -inkey server.key  -out server.p12 -name localhost -CAfile ca.crt -caname root 
   
2.p12格式转为jks格式
keytool -importkeystore -destkeystore server.jks -srckeystore server.p12 -srcstoretype pkcs12 -alias localhost 

3.客户端证书导入服务端
keytool -import -alias client -file client.crt -keystore server.jks  -storepass changeit -trustcacerts

4.通过客户端crt和key生成p12格式证书
openssl pkcs12 -export -in client.crt -inkey client.key  -out client.p12 -name localhost -CAfile ca.crt -caname root

5.将服务端证书导入客户端
keytool -importcert -keystore client.p12 -alias servercert -file server.crt 
--------以下为验证部分
检验服务端是否具有自己的private key和客户端的cert
keytool -list -keystore server.jks

验证证书是否合法
CERTUTIL -urlfetch -verify client.crt
热加载信任库
  1. 服务端的jks文件不要放在resource文件下,网上很多博文都是放到这个目录,其实根本不能进行热加载,因为打包之后 是不能对resource文件夹下的文件进行修改替换的,必须放到jar包外层。
  2. 配置Tomcat,使得TrustManagerClassName可被设置,代码如下:
@Configuration
@ConditionalOnClass({Servlet.class, Tomcat.class, UpgradeProtocol.class})
public class SslTomcatAutoConfiguration {

    @Autowired
    private X509TrustManager x509TrustManager;

    @Bean
    public SslWebServerFactoryCustomizer hotSslWebServerFactoryCustomizer() {
        return new SslWebServerFactoryCustomizer(x509TrustManager);
    }

    @Bean
    @ConditionalOnMissingBean
    public X509TrustManager x509TrustManager() {
        return new SslX509TrustManager();
    }
}

  1. 使用自定义{ProtocolHandler},主要是为了设置{@link AbstractHttp11Protocol#setTrustManagerClassName(String)}}
public class HttpsNioProtocol extends Http11NioProtocol {

    public HttpsNioProtocol() {
        super.setTrustManagerClassName(SslWebServerFactoryCustomizer.SslTrustManager.class.getName());
    }
}
  1. SslWebServerFactoryCustomizer
public class SslWebServerFactoryCustomizer implements WebServerFactoryCustomizer {

    private static X509TrustManager x509TrustManager;

    public SslWebServerFactoryCustomizer(X509TrustManager x509TrustManager) {
        SslWebServerFactoryCustomizer.x509TrustManager = x509TrustManager;
    }

    @Override
    public void customize(TomcatServletWebServerFactory factory) {
        factory.setProtocol(HttpsNioProtocol.class.getName());
    }

    
    public static class SslTrustManager implements X509TrustManager {

        @Override
        public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
            x509TrustManager.checkClientTrusted(x509Certificates, s);
        }

        @Override
        public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
            x509TrustManager.checkServerTrusted(x509Certificates, s);
        }

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return x509TrustManager.getAcceptedIssuers();
        }
    }
}
  1. SslX509TrustManager
public class SslX509TrustManager implements X509TrustManager {

    @Value("${server.ssl.trust-store}")
    private String trustStore;

    @Value("${server.ssl.trust-store-password}")
    private String trustStorePassword = "";


    @Value("${server.ssl.trust-store-type:JKS}")
    private String trustStoreType;

    
    @Override
    public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
        KeyStore keyStore = KeyStoreLoader.load(trustStore, trustStorePassword, trustStoreType);
        if (ObjectUtils.isEmpty(keyStore)) {
            System.out.println("验证不通过");
            throw new CertificateException();
        }
        for (X509Certificate x509Certificate : x509Certificates) {
            try {
                if (keyStore.getCertificateAlias(x509Certificate) != null) {
                    System.out.println("验证通过");
                    return;
                }

            } catch (Exception e) {
                // pass
            }
        }
        System.out.println("验证不通过");
        try {
            storeTrust();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        throw new CertificateException();
    }

    @Override
    public void checkServerTrusted(X509Certificate[] x509Certificates, String s) {
        // 一般不用管,验证服务端的证书是否都有效
    }

    @Override
    public X509Certificate[] getAcceptedIssuers() {
        return new X509Certificate[0];
    }

}
  1. KeyStore加载器,主要完成从文件加载
public class KeyStoreLoader {

    private KeyStoreLoader() {
    }

    private static ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();

    public static KeyStore load(String name, String password, String type) {
        File file = new File(name);
        KeyStore keyStore;
        try {
            InputStream inputStream = new FileInputStream(file);
            try {
                keyStore = KeyStore.getInstance(type);
                keyStore.load(inputStream, password.toCharArray());
                return keyStore;

            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }
}
  1. 将以上代码配置好之后就不要其他操作拉。
测试
  1. 自定义接口
@RestController
@RequestMapping("/test")
public class TestController {

    @GetMapping("/test")
    public String test(){
        return "777";
    }
}
  1. 首先未在server.jks中导入客户端证书,访问接口:

    访问失败了。
  2. 通过keytool命令加入客户端证书,在进行访问:

访问成功。
如果要测试删除证书是否能访问,需要重启浏览器哦。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/530870.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号