我一直在尝试在 Tomcat 8 中设置 SSL/TLS 握手。我已成功完成所有配置,但我在使用 CRL/OCSP 时遇到了一些问题。
我需要解决方案:this
我有几个问题,请耐心等待。非常感谢任何帮助。
- 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 配置来实现吗?
- 我找到了一种方法来完成上述任务,我通过操作 Java 代码找到了 here!
这个问题是我必须在握手时发送客户端证书到这个 java 代码,并根据这个代码的回复接受/拒绝证书。我不知道该怎么做。任何帮助都会有很大用处。 第二个原因是我更愿意使用 tomcat 配置而不是自定义代码来完成任务 1,因为自定义代码可能会遗漏某些方面。
我可以在不重新启动 tomcat 服务器的情况下从 CRL 分发 URL 中动态选择更新的 CRL 吗?具有上述配置的当前方案会在服务器打开时选择一次 CRL 文件,然后即使 URL 上可用的 CRL 列表已更改,它也仅使用该副本。
我们可以在连接器中配置多个 CRL 端点吗? Tomcat 将检查所有这些并根据所有 URL 的组合列表接受/拒绝客户端证书。
- 如果已配置,我能否以类似于缓存 CRL 列表的方式缓存 OCSP 响应?
提前致谢。请随时询问我可能遗漏的任何细节。
最佳答案
回答我自己的问题。
我可以找到一种缓存 CRL 的方法。我所做的是使 server.xml 中连接器的 crlFile 指向本地计算机上的 CRL 文件。我不时使用 CRON 作业更新此文件。
从 Tomcat v8.5.24 开始,添加了一个新的 API 来刷新整个 SSL 配置,而无需重新启动 Tomcat 服务器。我也时不时地调用这些 API 以从本地计算机中选择更新的 CRL 文件。
他们介绍了 2 个名为:
- reloadSslHostConfig(String hostName) - 重新加载特定主机
- reloadSslHostConfigs() - 重新加载所有
可以通过多种方式调用它们:
- 使用jmx
- 使用经理服务
- 通过制定自定义协议(protocol) - 我在研究过程中发现了这种方式
方式 1 和方式 2 的详细信息很容易在线获得。
关于如何使用方式 3 的详细信息:
- 创建一个类来扩展您选择的协议(protocol),例如。 Http11Nio协议(protocol)
- 覆盖所需的方法并在其中调用 super 以保持默认行为
- 在该类中创建一个线程,定时调用reloadSslHostConfigs方法
- 把这个类打包成一个jar,然后把那个jar放到tomcat的lib文件夹中
- 在 server.xml 的连接器中编辑协议(protocol)以使用此自定义协议(protocol)
在下面找到示例代码:
主要协议(protocol)类:
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 中的连接器应该将此作为协议(protocol)提及:
<Connector protocol="com.myown.connector.ReloadProtocol"
..........
希望这对某人有帮助。
关于java - 如何在 SSL 配置的 tomcat 中缓存和更新 CRL(证书撤销列表)/OCSP 响应?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51402661/