我正在使用Tomcat 9.0.19,并尝试为特定的Web应用程序启用基于X.509证书的客户端身份验证(AKA I&A)。
总之,Tomcat适用于通过单向TLS启用了基本I&A的应用程序。当访问具有基于证书的I&A的Web应用程序时,Tomcat在发送Server Hello Done之前似乎并没有将客户端证书作为Server Hello消息的一部分,后来它通过了身份验证检查:
2020年1月2日13:00:40.371精细[https-jsse-nio-443-exec-10] org.apache.catalina.authenticator.SSLAuthenticator.doAuthenticate查找证书2020年1月2日13:00:40.830精细[https-jsse-nio-443-exec-10] org.apache.catalina.authenticator.SSLAuthenticator.doAuthenticate此请求中不包含证书
[在Wireshark中处理了TLS流程,并看到了TLS 1.2握手。交换加密数据后不久,Tomcat发送“加密警报”消息,并关闭套接字。尝试从浏览器联系Tomcat,执行GET。浏览器没有提示我选择证书,这似乎也表明Tomcat没有从浏览器请求证书。
任何帮助将不胜感激!
更多详细信息:
我们有一组由中间CA颁发的Tomcat和客户端证书,由根CA签名(颁发)。双方(客户端和服务器)都已经设置了信任库,以及在其中具有正确的证书/密钥的密钥库。 Web应用程序设置为需要证书I&A(web.xml):
<security-constraint>
<web-resource-collection>
<web-resource-name>All by default</web-resource-name>
<url-pattern>/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>OTService</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
<login-config>
<auth-method>CLIENT-CERT</auth-method>
<realm-name>certificate</realm-name>
</login-config>
OTService角色是在Tomcat-Users.xml中设置的,还有一个用户帐户:
现在,server.xml中的连接器配置如下:
<Connector port="443" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="100" SSLEnabled="true" scheme="https" secure="true">
<SSLHostConfig>
<Certificate certificateKeystoreFile="/apache-tomcat-9.0.19/conf/km/keyStore.jks"
certificateKeystorePassword="PASSWORD"
certificateKeyAlias="tomcat"
type="RSA" />
truststoreFile="/apache-tomcat-9.0.19/conf/km/trust_store.jks"
truststorePass="PASSWORD"
truststoreType="JKS"
certificateVerification="required"
clientAuth="true"
protocols="TLSv1.2"
</SSLHostConfig>
</Connector>
关于Tomcat为什么不要求客户端证书的任何想法?
我发现的第一个问题是Tomcat忽略了信任库的Connector-> SSLHostConfig设置,并且仍然使用了JRE默认信任库。我发现它的方法是使用浏览器将协商的TLS会话密钥保存到文件(Google SSLKEYLOGFILE),然后将Wireshark配置为使用该文件,将浏览器捕获到Tomcat会话,然后能够以纯文本格式查看每条消息。
[接下来,我发现Tomcat正在请求客户端证书。但是,它提供的接受的根CA列表来自默认的cacerts文件,而不是truststoreFile属性的值。通过将setenv.sh文件添加到具有Java属性的Tomcat bin目录中以覆盖默认信任存储位置,可以使Tomcat整体上使用其他文件。
现在,我在经商,该浏览器能够完成TLS握手,但是随后的身份验证和授权步骤失败了。我最终确定提供证书的正确方法。主题字段不是“ CN = OU客户,OU =控制系统,O = IoTOY,L = Scottsdale,S = AZ,C = US”,而是“ CN = OU客户,OU =控制系统,O = IoTOY,L =斯科茨代尔,ST = AZ,C =美国”。最后,我使用了2路TLS。
要记住的一件事是,如果Tomcat上运行的任何内容都试图通过TLS连接到使用商业CA证书的另一个系统,则它将失败,因为您现在使用的信任库没有商业CA的证书。修复它的一种方法是,复制默认的JRE cacerts文件,并向其中添加系统特定的CA证书,并从上述setenv.sh文件中指向该文件。