0

我一直在尝试在 Tomcat 8 中设置 SSL/TLS 握手。我已经成功完成了所有配置,但是我在使用 CRL/OCSP 时遇到了一些问题。

我需要解决方案:这个

我有几个问题,所以请耐心等待。任何帮助将非常感激。

  1. tomcat 8 是否允许我们缓存从 CRL 分发点获得的 CRL 文件?通过缓存我的意思是如果网络不可用并且我们启动服务器,我不希望tomcat默认允许所有用户访问(它确实如此),因为CRL分发点不可用。我希望它缓存最后一个可用列表并在现在无法下载 CRL 时使用它。如果可以下载,则更新现有缓存。

我在 server.xml 中配置了以下连接器。

<Connector protocol="org.apache.coyote.http11.Http11NioProtocol" 
	port="8443" maxThreads="2000" clientAuth="want" scheme="https"
	keepAliveTimeout="-1" connectionTimeout="900000" compression="on" 
	noCompressionUserAgents="gozilla, traviata" 
	compressableMimeType="text/html,text/xml,text/css,text/javascript,image/jpg,image/ico,image/png,image/jpeg,image/tiff,image/tif" 

	secure="true" SSLEnabled="true" sslProtocol="TLS" sessionTimeout="30" 

	truststoreFile="D:\Certs\server.truststore" truststorePass="123456"
  
	keystoreFile="D:\Certs\keystore.pkcs12" keystorePass="password" keystoreType="PKCS12"

	crlFile="http://127.0.0.1:8600/getCRLFile/"

	maxKeepAliveRequests="200" sslEnabledProtocols= "TLSv1,TLSv1.1,TLSv1.2" 
	maxHttpHeaderSize="65536" maxPostSize="4194304" 
	ciphers="TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA"/>

我可以使用任何 tomcat 配置来实现这一点吗?

  1. 我找到了一种方法来完成上述任务,我在这里操作了一个 Java 代码!

问题在于,我必须在与此 java 代码握手时发送客户端证书,并根据此代码的回复接受/拒绝证书。我不知道该怎么做。任何帮助都会大有裨益。第二个原因是我更愿意使用 tomcat 配置而不是自定义代码来完成任务 1,因为自定义代码可能会遗漏某些方面。

  1. 我可以在不重新启动 tomcat 服务器的情况下从 CRL 分发 URL 中动态选择更新的 CRL 吗?具有上述配置的当前方案在服务器打开时选择一次 CRL 文件,然后它仅使用该副本,即使 URL 上可用的 CRL 列表已更改。

  2. 我们可以在连接器中配置多个 CRL 端点吗?Tomcat 将检查它们并根据所有 URL 的组合列表接受/拒绝客户端证书。

    1. 如果已配置,我能否以与缓存 CRL 列表类似的方式缓存 OCSP 响应?

提前致谢。请随时询问我可能错过的任何细节。

4

1 回答 1

1

回答我自己的问题。

我可以找到一种缓存 CRL 的方法。我所做的是使 server.xml 中连接器的 crlFile 指向本地计算机上的 CRL 文件。我不时使用 CRON 作业更新此文件。

从 Tomcat v8.5.24 开始,添加了一个新的 API 来刷新整个 SSL 配置,而无需重新启动 Tomcat 服务器。我也时常调用这些 API 以从本地计算机中选择更新的 CRL 文件。

他们引入了 2 种方法,命名为:

  1. reloadSslHostConfig(String hostName) - 重新加载特定主机
  2. reloadSslHostConfigs() - 重新加载所有

可以通过多种方式调用它们:

  1. 使用 jmx
  2. 使用经理服务
  3. 通过制作自定义协议 - 我在研究期间发现了这种方式

方式 1 和方式 2 的详细信息可轻松在线获得。

如何使用方式3的详细信息:

  1. 制作一个扩展您选择的协议的类,例如。Http11Nio协议
  2. 覆盖所需的方法并在其中调用 super 以保持默认行为
  3. 在这个类中创建一个线程来定时调用 reloadSslHostConfigs 方法
  4. 把这个类打包到一个jar中,然后把那个jar放到tomcat的lib文件夹中
  5. 在 server.xml 的连接器中编辑协议以使用此自定义协议

在下面找到示例代码:

主要协议类:

    package com.myown.connector;

    import java.io.File;
    import java.io.InputStream;
    import java.lang.reflect.Field;
    import java.net.URL;
    import java.net.URLConnection;
    import java.nio.file.StandardCopyOption;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.ConcurrentMap;

    import javax.management.MalformedObjectNameException;
    import javax.management.ObjectName;
    import javax.net.ssl.SSLSessionContext;

    import org.apache.coyote.http11.Http11NioProtocol;
    import org.apache.juli.logging.Log;
    import org.apache.juli.logging.LogFactory;
    import org.apache.tomcat.util.modeler.Registry;
    import org.apache.tomcat.util.net.AbstractEndpoint;
    import org.apache.tomcat.util.net.AbstractJsseEndpoint;
    import org.apache.tomcat.util.net.GetSslConfig;
    import org.apache.tomcat.util.net.SSLContext;
    import org.apache.tomcat.util.net.SSLHostConfig;
    import org.apache.tomcat.util.net.SSLHostConfigCertificate;
    import org.apache.tomcat.util.net.SSLImplementation;
    import org.apache.tomcat.util.net.SSLUtil;

    public class ReloadProtocol extends Http11NioProtocol {

        private static final Log log = LogFactory.getLog(Http12ProtocolSSL.class);

        public ReloadProtocol() {
            super();
            RefreshSslConfigThread refresher = new 
                  RefreshSslConfigThread(this.getEndpoint(), this);
            refresher.start();
        }

        @Override
        public void setKeystorePass(String s) {
            super.setKeystorePass(s);
        }

        @Override
        public void setKeyPass(String s) {
            super.setKeyPass(s);
        }

        @Override
        public void setTruststorePass(String p) {
            super.setTruststorePass(p);
        }

        class RefreshSslConfigThread extends Thread {

            AbstractJsseEndpoint<?> abstractJsseEndpoint = null;
            Http11NioProtocol protocol = null;

            public RefreshSslConfigThread(AbstractJsseEndpoint<?> abstractJsseEndpoint, Http11NioProtocol protocol) {
                this.abstractJsseEndpoint = abstractJsseEndpoint;
                this.protocol = protocol;
            }

            public void run() {
                int timeBetweenRefreshesInt = 1000000; // time in milli-seconds
                while (true) {
                    try {
                            abstractJsseEndpoint.reloadSslHostConfigs();
                            System.out.println("Config Updated");
                    } catch (Exception e) {
                        System.out.println("Problem while reloading.");
                    }
                    try {
                        Thread.sleep(timeBetweenRefreshesInt);
                    } catch (InterruptedException e) {
                        System.out.println("Error while sleeping");
                    }
                }
            }
       }
}

server.xml 中的连接器应将此作为协议提及:

<Connector protocol="com.myown.connector.ReloadProtocol"
 ..........

希望这可以帮助某人。

于 2018-07-27T06:52:56.120 回答