CAS SunCertPathBuilderException:unable 找到请求目标的有效证书路径
CAS SunCertPathBuilderException:unable to find valid certification path to requested target
我在我的计算机中配置了 CAS 以在特定域(比如 a.com
)上工作,效果很好。我有一对 .crt 和 .key 文件以及代码。现在需要更改域,所以我所做的是相应地更改源代码中的域(比如 b.com
)并导入我收到的 .crt 和 .key 文件。现在,当我访问 CAS 登录页面时,我可以访问它。但是当我提供登录凭据并单击登录按钮时,它失败并出现以下异常。
sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141)
sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126)
java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382)
sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292)
sun.security.validator.Validator.validate(Validator.java:260)
sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324)
sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229)
sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124)
sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1496)
sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)
sun.security.ssl.Handshaker.processLoop(Handshaker.java:1026)
sun.security.ssl.Handshaker.process_record(Handshaker.java:961)
sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)
sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)
sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1546)
sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1474)
sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:254)
org.jasig.cas.client.util.CommonUtils.getResponseFromServer(CommonUtils.java:429)
org.jasig.cas.client.validation.AbstractCasProtocolUrlBasedTicketValidator.retrieveResponseFromServer(AbstractCasProtocolUrlBasedTicketValidator.java:41)
org.jasig.cas.client.validation.AbstractUrlBasedTicketValidator.validate(AbstractUrlBasedTicketValidator.java:193)
org.springframework.security.cas.authentication.CasAuthenticationProvider.authenticateNow(CasAuthenticationProvider.java:158)
org.springframework.security.cas.authentication.CasAuthenticationProvider.authenticate(CasAuthenticationProvider.java:143)
org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:174)
org.springframework.security.cas.web.CasAuthenticationFilter.attemptAuthentication(CasAuthenticationFilter.java:270)
org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
org.jasig.cas.client.session.SingleSignOutFilter.doFilter(SingleSignOutFilter.java:97)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:121)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:121)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:66)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214)
org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177)
org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
谁能告诉我这到底是怎么回事?我见过很多类似的问题,但 none 似乎解决了我的情况。
原来是我的Tomcat配置有问题。即使我已将密钥导入密钥库,tomcat 仍未访问密钥库,导致无法读取证书。
似乎这适用于那些下载和提取 tomcat 发行版的二进制文件而不是使用 apt-get
.
等包管理器的人
目前有两个可能的选项(可能还有更多)。
- 修改 catalina.sh 以添加 属性
-Djavax.net.ssl.trustStore
以包含所需的信任库文件。基本上,属性 和值附加到上述脚本中的 JAVA_OPTS
变量。例如。 JAVA_OPTS="$JAVA_OPTS -Djavax.net.ssl.trustStore=$JAVA_HOME/jre/lib/security/cacerts"
。但这只是一个快速修复。我不认为这是一个很好的解决方案,因为信任库正在全局添加。
- 将密钥库位置添加到
server.xml
配置文件中的连接器属性。可以在 here. 找到示例
我现在意识到这是一个非常简单的基本问题。但是为了支持学习者,我想到了留下问题和答案。请进一步改进此答案。
来自CAS docs:
PKIX path building errors are the most common SSL errors. The problem here is that the CAS client does not trust the certificate presented by the CAS server; most often this occurs because of using a self-signed certificate on the CAS server. To resolve this error, import the CAS server certificate into the system truststore of the CAS client. If the certificate is issued by your own PKI, it is better to import the root certificate of your PKI into the CAS client truststore.
By default the Java system truststore is at $JAVA_HOME/jre/lib/security/cacerts. The certificate to be imported MUST be a DER-encoded file.
所以,如果你有密钥库文件,比如说store.jks
,首先,导出服务器的证书:
keytool -exportcert -keystore store.jks -alias server -file server.crt
[请注意,您的密钥库中的别名可能不同]。接下来,将证书移动到 $JAVA_HOME/jre/lib/security/cacerts
目录中,并将其导入客户端的信任库(这里,客户端是您的 JVM):
keytool -import -keystore cacerts -file server.crt -alias server -storepass changeit
[最后一条命令必须以管理员权限调用!]
请注意,如果您 运行 在 localhost 上执行此操作,则证书的 CN 必须是“localhost”。
就是这样,现在启动服务器并享受吧。
我在我的计算机中配置了 CAS 以在特定域(比如 a.com
)上工作,效果很好。我有一对 .crt 和 .key 文件以及代码。现在需要更改域,所以我所做的是相应地更改源代码中的域(比如 b.com
)并导入我收到的 .crt 和 .key 文件。现在,当我访问 CAS 登录页面时,我可以访问它。但是当我提供登录凭据并单击登录按钮时,它失败并出现以下异常。
sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141)
sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126)
java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382)
sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292)
sun.security.validator.Validator.validate(Validator.java:260)
sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324)
sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229)
sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124)
sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1496)
sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)
sun.security.ssl.Handshaker.processLoop(Handshaker.java:1026)
sun.security.ssl.Handshaker.process_record(Handshaker.java:961)
sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)
sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)
sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1546)
sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1474)
sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:254)
org.jasig.cas.client.util.CommonUtils.getResponseFromServer(CommonUtils.java:429)
org.jasig.cas.client.validation.AbstractCasProtocolUrlBasedTicketValidator.retrieveResponseFromServer(AbstractCasProtocolUrlBasedTicketValidator.java:41)
org.jasig.cas.client.validation.AbstractUrlBasedTicketValidator.validate(AbstractUrlBasedTicketValidator.java:193)
org.springframework.security.cas.authentication.CasAuthenticationProvider.authenticateNow(CasAuthenticationProvider.java:158)
org.springframework.security.cas.authentication.CasAuthenticationProvider.authenticate(CasAuthenticationProvider.java:143)
org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:174)
org.springframework.security.cas.web.CasAuthenticationFilter.attemptAuthentication(CasAuthenticationFilter.java:270)
org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
org.jasig.cas.client.session.SingleSignOutFilter.doFilter(SingleSignOutFilter.java:97)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:121)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:121)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:66)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214)
org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177)
org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
谁能告诉我这到底是怎么回事?我见过很多类似的问题,但 none 似乎解决了我的情况。
原来是我的Tomcat配置有问题。即使我已将密钥导入密钥库,tomcat 仍未访问密钥库,导致无法读取证书。
似乎这适用于那些下载和提取 tomcat 发行版的二进制文件而不是使用 apt-get
.
目前有两个可能的选项(可能还有更多)。
- 修改 catalina.sh 以添加 属性
-Djavax.net.ssl.trustStore
以包含所需的信任库文件。基本上,属性 和值附加到上述脚本中的JAVA_OPTS
变量。例如。JAVA_OPTS="$JAVA_OPTS -Djavax.net.ssl.trustStore=$JAVA_HOME/jre/lib/security/cacerts"
。但这只是一个快速修复。我不认为这是一个很好的解决方案,因为信任库正在全局添加。 - 将密钥库位置添加到
server.xml
配置文件中的连接器属性。可以在 here. 找到示例
我现在意识到这是一个非常简单的基本问题。但是为了支持学习者,我想到了留下问题和答案。请进一步改进此答案。
来自CAS docs:
PKIX path building errors are the most common SSL errors. The problem here is that the CAS client does not trust the certificate presented by the CAS server; most often this occurs because of using a self-signed certificate on the CAS server. To resolve this error, import the CAS server certificate into the system truststore of the CAS client. If the certificate is issued by your own PKI, it is better to import the root certificate of your PKI into the CAS client truststore.
By default the Java system truststore is at $JAVA_HOME/jre/lib/security/cacerts. The certificate to be imported MUST be a DER-encoded file.
所以,如果你有密钥库文件,比如说store.jks
,首先,导出服务器的证书:
keytool -exportcert -keystore store.jks -alias server -file server.crt
[请注意,您的密钥库中的别名可能不同]。接下来,将证书移动到 $JAVA_HOME/jre/lib/security/cacerts
目录中,并将其导入客户端的信任库(这里,客户端是您的 JVM):
keytool -import -keystore cacerts -file server.crt -alias server -storepass changeit
[最后一条命令必须以管理员权限调用!]
请注意,如果您 运行 在 localhost 上执行此操作,则证书的 CN 必须是“localhost”。
就是这样,现在启动服务器并享受吧。