JVM导入证书
传统都是通过java命令导入证书,但是比较繁琐,对于sso-cas系统部署证书也是一件烦心事。遂有了如下代码。
核心代码
import java.io.*;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
/**
* @author wangqimeng
* @date 2019/10/15 13:36
*/
@Slf4j
public class KeyStoreUtil {
private KeyStoreUtil() {
}
public static void saveCertificate(String cerNameAlias,
InputStream certIn,
String passphrase) throws Exception {
log.debug("程序进行证书导入工作");
final char sep = File.separatorChar;
File dir = new File(System.getProperty("java.home") + sep + "lib" + sep + "security");
log.debug("导入证书路径:{}", dir);
char[] passphraseArray = passphrase.toCharArray();
OutputStream out = null;
File targetKeyStore = new File(dir, "cacerts");
//输入流和输出流不可同时在同一文件,否则文件会被置空
try (InputStream localCertIn = new FileInputStream(targetKeyStore)) {
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(localCertIn, passphraseArray);
//判断是否已经存在在该证书
if (keystore.containsAlias(cerNameAlias)) {
log.debug("已经存在该证书:{}", cerNameAlias);
return;
}
BufferedInputStream bis = new BufferedInputStream(certIn);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
while (bis.available() > 0) {
Certificate cert = cf.generateCertificate(bis);
keystore.setCertificateEntry(cerNameAlias, cert);
}
out = new FileOutputStream(targetKeyStore);
keystore.store(out, passphraseArray);
} finally {
if (out != null) {
try {
out.close();
} catch (IOException e) {
log.error("输出流关闭失败");
}
}
}
}
public static void doKeyStore(ResourceLoader resourceLoader,
String[] certificatePath, String certificateFileName,
String certificateNameAlias, String passphrase) throws Exception {
try (InputStream inputStream = getResource(resourceLoader, certificatePath, certificateFileName).getInputStream()) {
KeyStoreUtil.saveCertificate(certificateNameAlias,
inputStream, passphrase);
}
}
private static Resource getResource(ResourceLoader resourceLoader, String[] certificatePath, String fileName) {
for (int i = certificatePath.length - 1; i >= 0; i--) {
Resource resource = resourceLoader.getResource(certificatePath[i] + fileName);
if (resource.exists()) {
return resource;
}
}
throw new RuntimeException(fileName + "资源未找到");
}
}
Test
import org.junit.Before;
import org.junit.Test;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.ResourceLoader;
/**
* @author wangqimeng
* @date 2019/10/28 11:36
*/
public class KeyStoreUtilTest {
private ResourceLoader resourceLoader;
private String[] certificatePath;
private String certificateFileName;
private String certificateNameAlias;
private String passphrase;
@Before
public void init() {
this.resourceLoader = new DefaultResourceLoader();
this.certificatePath = new String[]{"classpath:/ssl/", "file:./ssl/"};
this.certificateFileName = "sso.ga.cer";
this.certificateNameAlias = "sso.ga.cer";
this.passphrase = "changeit";
}
@Test
public void doKeyStore() throws Exception {
KeyStoreUtil.doKeyStore(resourceLoader,
certificatePath,certificateFileName,
certificateNameAlias,passphrase);
}
}
For Spring Boot
证书实体
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.validation.annotation.Validated;
/**
* @author wangqimeng
* @date 2019/10/15 11:06
*/
@Data
@Validated
@ConfigurationProperties(prefix = "sso")
public class CertificateProperties {
private String certificatePath;
private String certificateNameAlias;
private String passphrase = "changeit";
private boolean autoImportCertificate;
}
sso:
auto-import-certificate: true
certificate-name-alias: sso.ga.cer
certificate-path: public/ssl/sso.ga.cer
passphrase:
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.io.ResourceLoader;
/**
* @author wangqimeng
* @date 2019/10/15 11:15
*/
@Slf4j
public class AutoImportRunner implements ApplicationRunner {
@Autowired
private CertificateProperties certificateProperties;
@Autowired
private ResourceLoader resourceLoader;
@Override
public void run(ApplicationArguments args) throws Exception {
KeyStoreUtil.doKeyStore(resourceLoader, certificateProperties.getCertificatePath(), certificateProperties.getCertificateFileName(),
certificateProperties.getCertificateNameAlias(), certificateProperties.getPassphrase());
}
}