繁体   English   中英

使用 X.509 证书的 Tomcat 9.xx 客户端身份验证

[英]Tomcat 9.x.x Client Authentication using X.509 Certificates

我正在使用 Tomcat 9.0.19 并尝试为特定的 Web 应用程序启用基于 X.509 证书的客户端身份验证(AKA I&A)。

总之,Tomcat 适用于通过单向 TLS 启用基本 I&A 的应用程序。 当访问具有基于证书的 I&A 的 Web 应用程序时,Tomcat 似乎不会在发送 Server Hello Done 之前请求客户端证书作为 Server Hello 消息的一部分,并且稍后无法通过身份验证检查:

02-Jan-2020 13:00:40.371 FINE [https-jsse-nio-443-exec-10] org.apache.catalina.authenticator.SSLAuthenticator.doAuthenticate 查找证书 02-Jan-2020 13:00:40.830 FINE https-jsse-nio-443-exec-10] org.apache.catalina.authenticator.SSLAuthenticator.doAuthenticate 此请求中不包含证书

在 Wireshark 中追踪 TLS 流程并看到了 TLS 1.2 握手。 交换加密数据后不久,Tomcat 会发送“加密警报”消息并关闭套接字。 尝试从浏览器联系 Tomcat,执行 GET。 浏览器没有提示我选择证书,这似乎也指向 Tomcat 没有从浏览器请求它。

任何帮助将不胜感激!

更多细节:

我们有一组 Tomcat 和客户端的证书,由中间 CA 颁发,由根 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不会请求客户端证书的任何想法?

当你有:

<Connector ...>
  <SSLHostConfig>
    <Certificate A=1 B=2 C=3 />
    D=4 E=5 F=6
  </SSLHostConfig>
</Connector>

那么 A、B、C 是 Certificate 对象的属性,但 D、​​E、F 不是 SSLHostConfig 对象的属性——它们是不同的 XML内容 需要在标签中放入属性:

<Connector ... >
  <SSLHostConfig certificateVerification="required" truststoreFile=... >
    <Certificate ...keystore... />
  </SSLHostConfig>
</Connector>

并且根据需要在初始握手时执行证书请求(对我来说,在 tomcat 9.0.14 上测试过)。

我发现的第一个问题是 Tomcat 忽略了信任库的 Connector->SSLHostConfig 设置,并且无论如何都使用了 JRE 默认信任库。 我发现它的方法是让浏览器将协商的 TLS 会话密钥保存到文件 (Google SSLKEYLOGFILE),然后配置 Wireshark 以使用该文件,捕获浏览器-Tomcat 会话,然后能够以明文形式查看每条消息。

接下来,我发现 Tomcat 实际上是在请求客户端证书。但是它发送的接受的根 CA 列表来自默认的 JRE cacerts 文件,而不是来自 truststoreFile 属性指定的文件。 通过将 setenv.sh 文件添加到具有 Java 属性的 Tomcat bin 目录以覆盖默认信任存储位置,可以让 Tomcat 全面使用不同的文件。

现在,我在做生意,浏览器能够完成 TLS 握手,但随后身份验证和授权步骤失败了。 我终于确定了提供证书的正确方法。 tomcat_users.xml 文件中的主题字段不是“CN=OU Client, OU=Control Systems, O=IoTOY, L=Scottsdale, S=AZ , C=US”,而是“CN=OU Client, OU=Control Systems, O =IoTOY,L=斯科茨代尔, ST=AZ ,C=US”。 最后,我有 2-way TLS 工作。

要记住的一件事是,如果在 Tomcat 上运行的任何东西尝试通过 TLS 连接到另一个使用商业 CA 证书的系统,它将失败,因为您现在使用的信任库没有商业根 CA 的证书。 修复它的一种方法是制作默认 JRE cacerts 文件的副本,并将特定于系统的 CA 证书添加到其中,并从上面提到的 setenv.sh 文件中指向它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM