java 下载证书导java-tools中

package com.tp.tools;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.KeyStore;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Date;
import java.util.Enumeration;

import javax.net.ssl.HttpsURLConnection;

import org.springframework.stereotype.Component;

import lombok.extern.slf4j.Slf4j;
@Slf4j
@Component
public class CertificateLoader {

 private static final String KEYSTORE_PATH = System.getProperty("java.home") + "/lib/security/cacerts";
 private static final String KEYSTORE_PSWD = "changeit";
 private static final String CERT_ALIAS_PREFIX = "auto-cert:";
 private static final String BASE_PATH="e://";

 private static String downloadCertificate(String host ) throws Exception {
     HttpsURLConnection connection = (HttpsURLConnection) new java.net.URL(host).openConnection();
     connection.connect();

     Certificate[] certs = connection.getServerCertificates();
     for (Certificate cert : certs) {
         if (cert instanceof X509Certificate) {
             String fileName = getMD5(host)+".crt";
             try (FileOutputStream fos = new FileOutputStream(BASE_PATH+File.separator+fileName)) {
                 fos.write("-----BEGIN CERTIFICATE-----\n".getBytes());
                 fos.write(java.util.Base64.getMimeEncoder(64, new byte[]{'\n'}).encode(((X509Certificate) cert).getEncoded()));
                 fos.write("\n-----END CERTIFICATE-----\n".getBytes());
             }
             log.info("已下载证书:" + fileName);
             return fileName;
         }
     }
     return null;
 }


 private static void loadCertificate(String fileName) {
     File keystoreFile = new File(KEYSTORE_PATH);
     if (!keystoreFile.exists()) {
         log.info("Keystore 文件不存在: " + KEYSTORE_PATH);
         return;
     }

     try (FileInputStream ksStream = new FileInputStream(keystoreFile)) {
         KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
         keyStore.load(ksStream, KEYSTORE_PSWD.toCharArray());

         // 加载证书
         CertificateFactory cf = CertificateFactory.getInstance("X.509");
         try (InputStream certStream = new FileInputStream(BASE_PATH+File.separator+fileName)) {
             Certificate cert = cf.generateCertificate(certStream);

             // 检查证书是否已存在
             String alias =CERT_ALIAS_PREFIX +fileName; // 可根据证书指纹生成唯一别名
             if (keyStore.getCertificate(alias) != null) {
                 log.info("证书已存在,跳过导入: " + alias);
                 return;
             }

             // 导入证书
             keyStore.setCertificateEntry(alias, cert);

             // 保存 keystore
             try (FileOutputStream fos = new FileOutputStream(keystoreFile)) {
                 keyStore.store(fos, KEYSTORE_PSWD.toCharArray());
             }

             log.info("证书已成功导入 keystore: " + alias);
         }
     } catch (Exception e) {
         log.error("导入证书失败: " + e.getMessage());
     }finally {
         try {
            if(Files.deleteIfExists(Paths.get(BASE_PATH,fileName))){
                 log.info("删除临时证书成功");
             }else {
                 log.error("删除临时证书失败");
             }
         } catch (IOException e) {
             log.error(e.getMessage());
         }

     }
 }




 private static void removeExpiredOrOldCertificates(String targetAlias) throws Exception {
     File ksFile = new File(KEYSTORE_PATH);
     try (FileInputStream fis = new FileInputStream(ksFile)) {
         KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
         ks.load(fis, KEYSTORE_PSWD.toCharArray());

         int removedCount = 0;
         Enumeration<String> aliases = ks.aliases();

         while (aliases.hasMoreElements()) {
             String alias = aliases.nextElement();

             // 只处理我们自动管理的证书(可选)
             if (!alias.startsWith(CERT_ALIAS_PREFIX)) {
                 continue;
             }

             Certificate cert = ks.getCertificate(alias);
             if (cert instanceof X509Certificate) {
                 X509Certificate x509 = (X509Certificate) cert;
                 Date now = new Date();
                 Date expires = x509.getNotAfter();

                 // 条件1: 已过期
                 boolean isExpired = now.after(expires);
                 // 条件2: 是我们要更新的目标别名(即使未过期也删,准备导入新版)
                 boolean isTarget = alias.equals(CERT_ALIAS_PREFIX+targetAlias);

                 if (isExpired || isTarget) {
                     ks.deleteEntry(alias);
                     log.info("已删除证书: " + alias + (isExpired ? " (已过期)" : " (更新替换)"));
                     removedCount++;
                 }
             }
         }

         // 保存 keystore
         try (FileOutputStream fos = new FileOutputStream(ksFile)) {
             ks.store(fos, KEYSTORE_PSWD.toCharArray());
         }

         log.info("共删除 " + removedCount + " 个旧/过期证书");
     }
 }
 private static String getMD5(String input) {
     try {
         MessageDigest md = MessageDigest.getInstance("MD5");
         byte[] hashBytes = md.digest(input.getBytes());

         // 转换为16进制字符串
         StringBuilder hexString = new StringBuilder();
         for (byte b : hashBytes) {
             String hex = String.format("%02x", b);
             hexString.append(hex);
         }
         return hexString.toString();
     } catch (NoSuchAlgorithmException e) {
         throw new RuntimeException("MD5 algorithm not found", e);
     }
 }

 public static void download(String host) throws Exception {
    String fileName = CertificateLoader.downloadCertificate(host);
    CertificateLoader.removeExpiredOrOldCertificates(fileName);
    CertificateLoader.loadCertificate(fileName);
 }



 public  static void main(String[] args) throws Exception {
     CertificateLoader.download("https://www.baidu.com");
 }





}
评论