我正在尝试配置 CAS 身份验证。它要求 CAS 和客户端应用程序都使用 HTTPS 协议。不幸的是,我们应该使用自签名证书(与我们的服务器没有任何共同点的 CN)。此外,服务器位于防火墙后面,我们只有两个可见的端口(ssh 和 https)。由于有几个应用程序应该在外部可见,我们使用 Apache 向这些应用程序发送 ajp 反向代理请求。安全连接由 Apache 管理,并且所有 Tomcat 都未配置为使用 SSL。但我在身份验证时获得了异常,因此决定在 CATALINA_OPTS 中设置密钥库:
export CATALINA_OPTS="-Djavax.net.ssl.keyStore=/path/to/tomcat/ssl/cert.pfx -Djavax.net.ssl.keyStoreType=PKCS12 -Djavax.net.ssl.keyStorePassword=password -Djavax.net.ssl.keyAlias=alias -Djavax.net.debug=ssl"
cert.pfx 是从 Apache HTTP Server 使用的证书和密钥获得的:
$ openssl pkcs12 -export -out /path/to/tomcat/ssl/cert.pfx -inkey /path/to/apache2/ssl/server-key.pem -in /path/to/apache2/ssl/server-cert.pem
当我尝试验证用户身份时出现以下异常:
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:174) ~[na:1.6.0_32]
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:238) ~[na:1.6.0_32]
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:318) ~[na:1.6.0_32]
同时,我可以在 catalina.out 中看到 Tomcat 在 cert.pfx 中看到证书,它与身份验证时使用的证书相同:
09:11:38.886 [http-bio-8080-exec-2] DEBUG o.j.c.c.v.Cas20ProxyTicketValidator - Constructing validation url: https://external-ip/cas/proxyValidate?pgtUrl=https%3A%2F%2Fexternal-ip%2Fclient%2Fj_spring_cas_security_proxyreceptor&ticket=ST-17-PN26WtdsZqNmpUBS59RC-cas&service=https%3A%2F%2Fexternal-ip%2Fclient%2Fj_spring_cas_security_check
09:11:38.886 [http-bio-8080-exec-2] DEBUG o.j.c.c.v.Cas20ProxyTicketValidator - Retrieving response from server.
keyStore is : /path/to/tomcat/ssl/cert.pfx
keyStore type is : PKCS12
keyStore provider is :
init keystore
init keymanager of type SunX509
***
found key for : 1
chain [0] = [
[
Version: V1
Subject: CN=wrong.domain.name, O=Our organization, L=Location, ST=State, C=Country
Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5
Key: Sun RSA public key, 1024 bits
modulus: 13??a lot of digits here??19
public exponent: ????7
Validity: [From: Tue Apr 24 16:32:18 CEST 2012,
To: Wed Apr 24 16:32:18 CEST 2013]
Issuer: CN=wrong.domain.name, O=Our organization, L=Location, ST=State, C=Country
SerialNumber: [ d??????? ????????]
]
Algorithm: [SHA1withRSA]
Signature:
0000: 65
Signature is here
0070: 96 .
]
***
trustStore is: /jdk-home-folder/jre/lib/security/cacerts
Here is a lot of trusted CAs. Here is nothing related to our certicate or our (not trusted) CA.
...
09:11:39.731 [http-bio-8080-exec-4] DEBUG o.j.c.c.v.Cas20ProxyTicketValidator - Retrieving response from server.
Allow unsafe renegotiation: false
Allow legacy hello messages: true
Is initial handshake: true
Is secure renegotiation: false
%% No cached client session
*** ClientHello, TLSv1
RandomCookie: GMT: 1347433643 bytes = { 63, 239, 180, 32, 103, 140, 83, 7, 109, 149, 177, 80, 223, 79, 243, 244, 60, 191, 124, 139, 108, 5, 122, 238, 146, 1, 54, 218 }
Session ID: {}
Cipher Suites: [SSL_RSA_WITH_RC4_128_MD5, SSL_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_DES_CBC_SHA, SSL_DHE_RSA_WITH_DES_CBC_SHA, SSL_DHE_DSS_WITH_DES_CBC_SHA, SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
Compression Methods: { 0 }
***
http-bio-8080-exec-4, WRITE: TLSv1 Handshake, length = 75
http-bio-8080-exec-4, WRITE: SSLv2 client hello message, length = 101
http-bio-8080-exec-4, READ: TLSv1 Handshake, length = 81
*** ServerHello, TLSv1
RandomCookie: GMT: 1347433643 bytes = { 145, 237, 232, 63, 240, 104, 234, 201, 148, 235, 12, 222, 60, 75, 174, 0, 103, 38, 196, 181, 27, 226, 243, 61, 34, 7, 107, 72 }
Session ID: {79, 202, 117, 79, 130, 216, 168, 38, 68, 29, 182, 82, 16, 25, 251, 66, 93, 108, 49, 133, 92, 108, 198, 23, 120, 120, 135, 151, 15, 13, 199, 87}
Cipher Suite: SSL_RSA_WITH_RC4_128_SHA
Compression Method: 0
Extension renegotiation_info, renegotiated_connection: <empty>
***
%% Created: [Session-2, SSL_RSA_WITH_RC4_128_SHA]
** SSL_RSA_WITH_RC4_128_SHA
http-bio-8080-exec-4, READ: TLSv1 Handshake, length = 609
*** Certificate chain
chain [0] = [
[
Version: V1
Subject: CN=wrong.domain.name, O=Our organization, L=Location, ST=State, C=Country
Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5
Key: Sun RSA public key, 1024 bits
modulus: 13??a lot of digits here??19
public exponent: ????7
Validity: [From: Tue Apr 24 16:32:18 CEST 2012,
To: Wed Apr 24 16:32:18 CEST 2013]
Issuer: CN=wrong.domain.name, O=Our organization, L=Location, ST=State, C=Country
SerialNumber: [ d??????? ????????]
]
Algorithm: [SHA1withRSA]
Signature:
0000: 65
Signature is here
0070: 96 .
]
***
http-bio-8080-exec-4, SEND TLSv1 ALERT: fatal, description = certificate_unknown
http-bio-8080-exec-4, WRITE: TLSv1 Alert, length = 2
http-bio-8080-exec-4, called closeSocket()
http-bio-8080-exec-4, handling exception: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
我尝试将我们的 pem 证书转换为 der 格式,并将其导入到 TrustedKeyStore (cacerts)(没有私钥),但没有任何变化。但我不确定我是否做对了。
另外我必须通知您,我不知道我们的 servier-key.pem 文件的密码,并且它可能与我创建的密钥库的密码不同。
操作系统:CentOS 6.2
架构:x64
Tomcat 版本:7
Apache HTTP Server 版本:2.4
有什么办法可以让 Tomcat 接受我们的证书吗?
答案1
通过将证书添加到 trustStore 而不是 keyStore 解决了该问题。我将 pem 证书转换为 der 格式,并使用 keytool 将其添加到 Java 信任库 ($JAVA_HOME/jre/lib/security/cacerts)。然后我将 keyStore 参数更改为 CATALINA_OPTS 中相应的 trustStore 参数。重新启动 Tomcat 服务后,一切正常。