【问题标题】:Tomcat 9.x.x Client Authentication using X.509 Certificates使用 X.509 证书的 Tomcat 9.x.x 客户端身份验证
【发布时间】:2020-01-02 21:02:38
【问题描述】:

我正在使用 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>    

在 Tomcat-Users.xml 中设置了 OTService 角色,以及一个用户帐户:

现在,server.xml中的Connector配置如下:

   <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 不会请求客户端证书?

【问题讨论】:

  • 我认为clientAuth 没有true 值。它是三值的。检查连接器文档。注意 CertificateRequest 消息不是 ServerHello 消息的一部分。
  • 正确。应该是requiredoptionalnone
  • clientAuth 值的要点。将其更改为 required 并没有任何区别。
  • 根据 RFC 5246:如果适用于所选密码套件,非匿名服务器可以选择从客户端请求证书。此消息如果发送,将立即跟随 ServerKeyExchange 消息(如果已发送;否则,此消息将跟随服务器的证书消息)。
  • 我在 Wireshark 中看到的是服务器(Tomcat)发送的 ServerHello 消息包含:“Server Hello,Certificate(chain),Server Key Exchange,Server Hello Done。所以,我会预计此时会看到证书请求。来自服务器的下一条消息是更改密码规范。

标签: authentication ssl tomcat two-way


【解决方案1】:

我发现的第一个问题是 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=控制系统, O=IoTOY, L=Scottsdale, ST=AZ, C=US"。最后,我有 2-way TLS 工作。

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

【讨论】:

  • 因此,即使您使用默认的 cacerts 文件,您也确实获得了 CertificateRequest。
  • 是的,但是我的 CA 证书 DN 列表有误,因此浏览器没有返回单个客户端/用户证书作为响应。
【解决方案2】:

当你有:

<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 content。属性需要放在标签中:

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

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

【讨论】:

    猜你喜欢
    • 2021-03-13
    • 1970-01-01
    • 1970-01-01
    • 2015-12-12
    • 2012-06-10
    • 2017-12-26
    • 2011-04-09
    • 2013-10-07
    • 1970-01-01
    相关资源
    最近更新 更多