Spring Security X509证书认证的JUnit测试实现方法咨询
X509证书单元测试实现步骤
1. 前置依赖准备
JDK 原生提供 java.security.cert.CertificateFactory 可直接解析生成 X509 证书对象,无需额外依赖。如果需要快速在代码中动态生成测试用自签证书,可以引入 BouncyCastle 测试依赖:
<!-- Maven 依赖,仅测试 scope 生效 --> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk18on</artifactId> <version>1.77</version> <scope>test</scope> </dependency>
2. 构造X509Certificate测试对象
有两种常用的构造方式,可按需选择:
方式1:读取本地测试证书文件
你 Postman 测试用的证书可以导出为 .cer/.pem 格式放到项目测试资源目录,直接解析生成对象:
import java.io.FileInputStream; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; // 读取测试资源下的证书生成对象 CertificateFactory cf = CertificateFactory.getInstance("X.509"); try (FileInputStream fis = new FileInputStream("src/test/resources/test-cert.cer")) { X509Certificate cert = (X509Certificate) cf.generateCertificate(fis); }
方式2:代码动态生成测试证书
无需依赖本地文件,更适合单元测试,可以自定义证书的 CN 字段值:
import org.bouncycastle.asn1.x500.X500Name; import org.bouncycastle.cert.X509v3CertificateBuilder; import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; import java.math.BigInteger; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.Security; import java.security.cert.X509Certificate; import java.util.Date; // 注册BouncyCastle安全提供者 Security.addProvider(new BouncyCastleProvider()); // 生成RSA密钥对 KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA"); keyPairGen.initialize(2048); KeyPair keyPair = keyPairGen.generateKeyPair(); // 证书有效期:前后各1年,可按需调整 Date notBefore = new Date(System.currentTimeMillis() - 365 * 24 * 60 * 60 * 1000L); Date notAfter = new Date(System.currentTimeMillis() + 365 * 24 * 60 * 60 * 1000L); // 证书主体DN,CN设置为你要测试的目标值,比如test-user X500Name subject = new X500Name("CN=test-user,OU=Test,O=Test Org,C=CN"); X509v3CertificateBuilder certBuilder = new JcaX509v3CertificateBuilder( subject, BigInteger.valueOf(System.currentTimeMillis()), notBefore, notAfter, subject, keyPair.getPublic() ); // 签名生成最终X509Certificate对象 X509Certificate cert = new JcaX509CertificateConverter() .setProvider("BC") .getCertificate(certBuilder.build(new JcaContentSignerBuilder("SHA256WithRSA").build(keyPair.getPrivate())));
3. 编写单元测试验证提取逻辑
构造好测试证书对象后,直接传入你自定义的 Principal 提取函数,断言结果符合预期即可,JUnit5 示例如下:
import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; public class X509PrincipalExtractorTest { // 你自己实现的Principal提取类实例 private final X509PrincipalExtractor extractor = new X509PrincipalExtractor(); @Test void testExtractPrincipalFromCn() throws Exception { // 构造测试证书,CN设置为test-user X509Certificate testCert = generateTestCert("test-user"); // 调用提取逻辑 Object principal = extractor.extractPrincipal(testCert); // 断言结果符合预期 assertEquals("test-user", principal.toString()); } // 把动态生成证书的逻辑封装为工具方法,可传入自定义CN参数 private X509Certificate generateTestCert(String cn) throws Exception { // 替换X500Name中的CN值为传入的cn参数即可 } }
如果你的提取逻辑包含证书有效性校验,生成测试证书时可按需调整
notBefore、notAfter参数,也可以构造过期、证书链不完整的测试用例覆盖异常场景。
内容的提问来源于stack exchange,提问作者MrNobody
相关产品推荐
相关产品推荐

