使用com.nimbusds.jose验证Azure AD JWT时遇PKIX路径构建失败
使用com.nimbusds.jose验证JWT时的PKIX证书路径错误问题
报错信息
com.nimbusds.jose.RemoteKeySourceException: Couldn't retrieve remote JWK set: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target. Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
实现代码
try { ConfigurableJWTProcessor jwtProcessor = new DefaultJWTProcessor(); JWKSource keySource = null; try { ResourceRetriever jwkRetriever = new DefaultResourceRetriever(100000, 100000); JWKSetCache jwkSetCache = new DefaultJWKSetCache(1440, 1430, TimeUnit.MINUTES); keySource = new RemoteJWKSet(new URL( "https://login.windows.net/36799f34-92fd-4612-8473-80173f2406e8/discovery/v2.0/keys"),jwkRetriever,jwkSetCache); } catch (MalformedURLException e) { e.printStackTrace(); } JWSAlgorithm expectedJWSAlg = JWSAlgorithm.RS256; JWSKeySelector keySelector = new JWSVerificationKeySelector(expectedJWSAlg,keySource); jwtProcessor.setJWSKeySelector(keySelector); JWTClaimsSet claimsSet = null; SecurityContext ctx = null; // optional context parameter, not required here try { claimsSet = jwtProcessor.process(token, ctx); } catch (ParseException e) { e.printStackTrace(); } catch (BadJOSEException e) { e.printStackTrace(); } catch (JOSEException e) { e.printStackTrace(); }
已配置的信任库信息(application.properties)
trust.store=myapp_dev.p12 trust.store.password=changeit
疑问
我已经将证书添加到信任库,但仍出现上述错误,请问哪里操作有误?
可能的原因及解决方法
1. Spring配置未被DefaultResourceRetriever识别
DefaultResourceRetriever默认使用JVM自带的信任库,不会自动读取Spring配置的trust.store。需要手动加载自定义信任库并构建SSLContext,传给DefaultResourceRetriever:
// 加载自定义PKCS12信任库 KeyStore trustStore = KeyStore.getInstance("PKCS12"); try (InputStream is = new FileInputStream("myapp_dev.p12")) { trustStore.load(is, "changeit".toCharArray()); } // 初始化信任管理器并构建SSLContext TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); tmf.init(trustStore); SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, tmf.getTrustManagers(), null); // 给ResourceRetriever设置自定义SSLContext DefaultResourceRetriever jwkRetriever = new DefaultResourceRetriever(100000, 100000); jwkRetriever.setSSLContext(sslContext);
2. 证书导入不规范
- 确认导入的是Microsoft授权服务器的根证书/中间证书链,而非客户端证书;
- 用命令检查p12文件是否包含完整证书链:
keytool -list -v -keystore myapp_dev.p12 -storetype PKCS12 - 重新导入证书时使用正确命令:
keytool -importcert -file microsoft_root_cert.cer -keystore myapp_dev.p12 -storetype PKCS12 -alias microsoft_root
3. 信任库路径配置错误
- 确认
trust.store的路径是绝对路径,或相对于项目运行工作目录的路径;可通过System.getProperty("user.dir")打印当前工作目录验证文件是否存在; - 若信任库放在类路径下,可直接通过类加载器读取:
InputStream is = getClass().getResourceAsStream("/myapp_dev.p12");
4. 未通过JVM参数指定信任库
若不想在代码中手动加载SSLContext,可通过JVM启动参数强制指定自定义信任库:
-Djavax.net.ssl.trustStore=myapp_dev.p12 -Djavax.net.ssl.trustStorePassword=changeit -Djavax.net.ssl.trustStoreType=PKCS12
内容的提问来源于stack exchange,提问作者SocketM
相关产品推荐
相关产品推荐

