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


    Springboot开启双向验证
    yaml文件配置
    证书生成
    热加载信任库
    测试
    yaml文件配置
    server:
    port: 6820
    ssl:
    enabled: true
    key-store: C:\Users\Administrator\Desktop\server.jks ## 这里放到桌面,原因后面会说
    key-store-password: changeit
    key-alias: localhost
    key-store-type: JKS
    trust-store: C:\Users\Administrator\Desktop\server.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

    热加载信任库
    服务端的jks文件不要放在resource文件下,网上很多博文都是放到这个目录,其实根本不能进行热加载,因为打包之后 是不能对resource文件夹下的文件进行修改替换的,必须放到jar包外层。
    配置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();
    }
    }


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

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

    SslWebServerFactoryCustomizer
    public class SslWebServerFactoryCustomizer implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> {

    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();
    }
    }
    }

    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;

    /**
    * @param x509Certificates 客户端传过来的证书
    * @param s 加密方式
    * @throws CertificateException
    */
    @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];
    }

    }

    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;
    }
    }

    将以上代码配置好之后就不要其他操作拉。
    测试
    自定义接口
    @RestController
    @RequestMapping("/test")
    public class TestController {

    @GetMapping("/test")
    public String test(){
    return "777";
    }
    }

    首先未在server.jks中导入客户端证书,访问接口:

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

    访问成功。
    如果要测试删除证书是否能访问,需要重启浏览器哦。
    ————————————————
    版权声明:本文为CSDN博主「别卷了啊」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/qq_34239851/article/details/121371896

  • 相关阅读:
    #背包#nssl 1488 上升子序列
    #环#nssl 1487 图
    #分治#JZOJ 4211 送你一颗圣诞树
    #概率,dp#JZOJ 4212 我想大声告诉你
    #并查集#JZOJ 4223 旅游
    #dp#nssl 1478 题
    #对顶堆#nssl 1477 赛
    #线段树,离散#nssl 1476 联
    #折半搜索,状压dp#nssl 1471 Y
    #并查集,线性筛#nssl 1470 X
  • 原文地址:https://www.cnblogs.com/telwanggs/p/16561941.html
Copyright © 2020-2023  润新知