Java可通过java.security.cert API解析Apache的SSLCertificateFile(PEM格式)并检查有效期:先剥离PEM头尾、Base64解码,再用CertificateFactory加载首个X.509证书,调用getNotBefore()/getNotAfter()获取有效期,对比当前时间判断状态。

Java 本身不直接解析 Apache 的 SSLCertificateFile(通常是 PEM 格式证书文件),但你可以借助 Java 的 java.security.cert API 读取并检查其有效期。关键在于:Apache 配置中的证书路径指向的是一个 PEM 文件(可能含证书链),而 Java 可以用 CertificateFactory 解析其中的首个(或指定)X.509 证书。
1. 读取 PEM 文件并提取 X.509 证书
Apache 的 SSLCertificateFile 通常为 PEM 格式(以 -----BEGIN CERTIFICATE----- 开头)。Java 不能直接加载 PEM,需先剥离头尾、Base64 解码,再用 CertificateFactory 解析。
- 跳过非证书内容(如注释、空行、私钥块)
- 只取第一个有效证书(Apache 一般把服务器证书放在最前面)
- 使用
CertificateFactory.getInstance("X.509")解析字节数组
2. 获取并校验有效期
解析成功后,调用 X509Certificate.getNotBefore() 和 getNotAfter() 获取有效期区间。
- 用
new Date()对比是否已过期或即将到期(例如提前 30 天预警) - 注意时区:证书时间是 UTC,
Date默认也是 UTC,无需额外转换 - 可格式化输出为易读字符串,如
yyyy-MM-dd HH:mm:ss
3. 完整可运行脚本示例(Java 8+)
以下是一个独立的 Java 类,接收 PEM 路径作为参数,打印证书信息和剩余天数:
立即学习“Java免费学习笔记(深入)”;
<font size="2"><strong>import java.io.*;
import java.security.cert.*;
import java.text.SimpleDateFormat;
import java.util.Date;
<p>public class CertExpiryChecker {
public static void main(String[] args) {
if (args.length == 0) {
System.err.println("Usage: java CertExpiryChecker <cert.pem>");
System.exit(1);
}
String certPath = args[0];
try {
X509Certificate cert = loadFirstCertificate(new File(certPath));
Date now = new Date();
Date notBefore = cert.getNotBefore();
Date notAfter = cert.getNotAfter();
long daysLeft = (notAfter.getTime() - now.getTime()) / (1000L <em> 3600 </em> 24);</p><pre class='brush:php;toolbar:false;'> SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("Subject: " + cert.getSubjectDN());
System.out.println("Valid From: " + sdf.format(notBefore));
System.out.println("Valid Until: " + sdf.format(notAfter));
System.out.println("Days left: " + daysLeft);
System.out.println("Status: " + (now.before(notBefore) ? "Not yet valid" :
now.after(notAfter) ? "EXPIRED" : "Valid"));
} catch (Exception e) {
System.err.println("Error reading certificate: " + e.getMessage());
e.printStackTrace();
}
}
static X509Certificate loadFirstCertificate(File file) throws Exception {
String pem = new String(Files.readAllBytes(file.toPath()));
String b64 = pem.replaceAll("(?m)^-+[A-Z ]+-+$|\s", "");
byte[] der = java.util.Base64.getDecoder().decode(b64);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
return (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(der));
}}
编译运行:javac CertExpiryChecker.javajava CertExpiryChecker /etc/ssl/certs/mydomain.crt
4. 注意事项与增强建议
- 若 PEM 文件含多张证书(如中间证书),上述脚本只取第一张;如需遍历,可用
cf.generateCertificates(...)返回列表 - 生产环境建议加入对证书链完整性和签名的信任验证(需配合 truststore),但仅查有效期无需此步
- 可封装为 Shell 脚本调用,或集成进监控系统(如 Zabbix、Prometheus Exporter)定期扫描多个 Apache 配置中的证书路径
- 注意文件权限:Java 进程需有读取证书文件的权限(尤其在 root 启动的 Apache 下,证书可能属 root:root)

















