将Tomcat从8.0迁移到8.5,客户端证书身份验证不起作用

时间:2020-01-22 14:34:33

标签: java ssl tomcat networking certificate

我们正在将Tomcat服务器从8.0升级到8.5。我们的服务器应使用tomcat JSSE选项的默认值来支持https,包括相互认证certificateVerification。 当前似乎相互身份验证不起作用,因为服务器无法验证 客户证书。

tomcat中的Connector配置如下:

<Connector port="443" protocol="org.apache.coyote.http11.Http11NioProtocol"
               maxThreads="150" SSLEnabled="true" scheme="https" secure="true" >
         <SSLHostConfig truststoreFile="/opt/allot/conf/infra.truststore" truststoreType="JKS" truststorePassword="****"
                         certificateVerification="required" sslProtocol="TLS" protocols="TLSv1.2,+TLSv1.1,+TLSv1.0">
            <Certificate certificateKeystoreFile="/opt/allot/conf/infra.keystore"
                         certificateKeystoreType="JKS"
                         certificateKeystorePassword="****"
                         certificateKeyAlias="****" />
        </SSLHostConfig>
</Connector>

我使用了WireShark嗅探器,输出为:

No. Time    Source  Destination Protocol    Length  Info
260 5.228627    172.19.2.30 10.110.108.74   TCP 66  55710 → 443 [SYN] Seq=0 Win=64240 Len=0 MSS=1460 WS=256 SACK_PERM=1
261 5.230733    10.110.108.74   172.19.2.30 TCP 66  443 → 55710 [SYN, ACK] Seq=0 Ack=1 Win=29200 Len=0 MSS=1387 SACK_PERM=1 WS=128
262 5.230831    172.19.2.30 10.110.108.74   TCP 54  55710 → 443 [ACK] Seq=1 Ack=1 Win=131584 Len=0
263 5.252688    172.19.2.30 10.110.108.74   TLSv1.2 238 Client Hello
264 5.254772    10.110.108.74   172.19.2.30 TCP 56  443 → 55710 [ACK] Seq=1 Ack=185 Win=30336 Len=0
265 5.268445    10.110.108.74   172.19.2.30 TCP 1441    443 → 55710 [ACK] Seq=1 Ack=185 Win=30336 Len=1387 [TCP segment of a reassembled PDU]
266 5.268564    10.110.108.74   172.19.2.30 TLSv1.2 887 Server Hello, Certificate, Server Key Exchange, Certificate Request, Server Hello Done
267 5.268607    172.19.2.30 10.110.108.74   TCP 54  55710 → 443 [ACK] Seq=185 Ack=2221 Win=131584 Len=0
268 5.329682    172.19.2.30 10.110.108.74   TLSv1.2 136 Certificate, Client Key Exchange
269 5.333364    10.110.108.74   172.19.2.30 TLSv1.2 61  Alert (Level: Fatal, Description: Bad Certificate)
270 5.333365    10.110.108.74   172.19.2.30 TCP 56  443 → 55710 [FIN, ACK] Seq=2228 Ack=267 Win=30336 Len=0
271 5.333456    172.19.2.30 10.110.108.74   TCP 54  55710 → 443 [ACK] Seq=267 Ack=2229 Win=131584 Len=0
273 5.365042    172.19.2.30 10.110.108.74   TLSv1.2 60  Change Cipher Spec
274 5.366449    10.110.108.74   172.19.2.30 TCP 56  443 → 55710 [RST] Seq=2229 Win=0 Len=0

这是我第一次进行相互身份验证,我很想听听您的建议,当然,我会尽快分享解决方案。

修改 我附加了我用Java写的测试客户端,这部分代码适用于tomcat 8.0.28,但不适用于Tomcat 8.5.50

public static void main(String[] args) throws IOException, KeyManagementException, NoSuchAlgorithmException {
        disableSslVerification();
        System.setProperty("javax.net.ssl.keyStoreType", "JKS");
        System.setProperty("javax.net.ssl.trustStoreType", "JKS");
        System.setProperty("javax.net.ssl.keyStore", "path/to/trustStoreFile");
        System.setProperty("javax.net.ssl.trustStore", "path/to/keyStoreFile");
        System.setProperty("javax.net.debug", "all");
        System.setProperty("javax.net.ssl.keyStorePassword", "****");
        System.setProperty("javax.net.ssl.trustStorePassword", "****");

        SSLSocketFactory sslSocketFactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
        URL url = new URL("https://10.110.108.74/webui");
        HttpsURLConnection connection = (HttpsURLConnection)url.openConnection();
        connection.setSSLSocketFactory(sslSocketFactory);

        InputStream in = connection.getInputStream();
        InputStreamReader reader = new InputStreamReader(in);
        BufferedReader bufferedReader = new BufferedReader(reader);

        String str = null;
        while ((str = bufferedReader.readLine()) != null) {
            System.out.println(str);
        }
        System.exit(0);
    }

    private static void disableSslVerification() throws NoSuchAlgorithmException, KeyManagementException {
        // Create a trust manager that does not validate certificate chains
        TrustManager[] trustAllCerts = new TrustManager[] {new X509TrustManager() {
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return null;
            }
            public void checkClientTrusted(X509Certificate[] certs, String authType) {
            }
            public void checkServerTrusted(X509Certificate[] certs, String authType) {
            }
        }
        };

        // Install the all-trusting trust manager
        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, new java.security.SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

        // Create all-trusting host name verifier
        HostnameVerifier allHostsValid = new HostnameVerifier() {
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        };

        // Install the all-trusting host verifier
        HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
    }

1 个答案:

答案 0 :(得分:0)

好的,我努力弄清楚。 问题出在我们的信任库文件中,证书是用PrivateKeyEntry而不是TrustedCeritciateEntry添加的。 因此,Tomcat服务器在没有我们内部CA的情况下发送了证书请求。

向那些可能会反抗的人求助。