有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java以编程方式更新tomcat 8中的证书,而无需重新启动服务器

为了更新用于服务器SSL的证书,我有一个代码来执行我需要的导入\导出和验证

它工作得很好,但是为了使更改生效,我必须重新启动tomcat
我希望避免重新启动,并在不使用外部工具(例如keytool)的情况下更新它
我查找了一些类似的问题,并找到了一个解决方案-重新启动443连接器。我可以这样做,连接器正在停止和启动,但证书未更新。只有服务器重新启动才能真正更新它

是否有我遗漏的连接器初始化程序
一些我应该清除的系统缓存或对象

这是我用于重新启动连接器的代码:

MBeanServer mbeanServer = null;
ObjectName objectName = null;
final ObjectName objectNameQuery = new ObjectName("*:type=Connector,port=443,*");
for (final MBeanServer server : (ArrayList<MBeanServer>) MBeanServerFactory.findMBeanServer(null)) {
    if (server.queryNames(objectNameQuery, null).size() > 0) {
        mbeanServer = server;
        objectName = (ObjectName) server.queryNames(objectNameQuery,null).toArray()[0];
        break;
    }
}

mbeanServer.invoke(objectName, "stop", null, null);
Thread.sleep(1000);
mbeanServer.invoke(objectName, "start", null, null);  

我在tomcat日志中看到了连接器重启的以下痕迹:
23-Apr-2017 15:42:00.292 INFO [BG-Task RestartTomcatConnector] org.apache.coyote.AbstractProtocol.stop Stopping ProtocolHandler ["http-nio-443"]
23-Apr-2017 15:42:01.349 INFO [BG-Task RestartTomcatConnector] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["http-nio-443"]


共 (1) 个答案

  1. # 1 楼答案

    问题已解决,以下是组件:

    1. 服务器。xml必须包含bindOnInit="false"。这是我使用的配置

      <Connector protocol="org.apache.coyote.http11.Http11NioProtocol"
              port="443" SSLEnabled="true" maxThreads="150"
              acceptCount="2000" scheme="https" secure="true"
              ciphers="TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, TLS_DHE_RSA_WITH_AES_256_CBC_SHA"
              keystoreFile="webapps/ServerKeyStore"
              keystorePass="***"
              clientAuth="false" sslProtocol="TLS"
              sslEnabledProtocols="TLSv1.1,TLSv1.2" compression="on"
              compressableMimeType="text/html,text/xml,application/xml,application/json,application/javascript,text/css,text/plain"
              server="Portal" useSendfile="false"
              compressionMinSize="1024" bindOnInit="false"
      />
      
    2. 重新启动连接器的Java代码:

      public class TomcatConnectorRestarter implements Callable<Boolean> {
      
          private final int waitSeconds = 3;
          private final static ReentrantLock rl = new ReentrantLock();
      
          @Override
          public Boolean call() throws Exception {
              restartConnector();
              return true;
          }
      
          protected void restartConnector() throws Exception {
              try {
                  if (tryLock()){
                      mLogger.info("Acquired lock");
                      try {
                          HTTPSConnectorMBean httpsConnector = null;
                          MBeanServer mbeanServer = null;
                          ObjectName objectName = null;
                          final ObjectName objectNameQuery = new ObjectName("*:type=Connector,port=443,*");
      
                          for (final MBeanServer server : (ArrayList<MBeanServer>) MBeanServerFactory.findMBeanServer(null)) {
                              if (server.queryNames(objectNameQuery, null).size() > 0) {
                                  mbeanServer = server;
                                  objectName = (ObjectName) server.queryNames(objectNameQuery, null).toArray()[0];
                                  httpsConnector = new HTTPSConnectorMBean(objectName, mbeanServer);
                                  break;
                              }
                          }
      
                          if (Objects.nonNull(httpsConnector)) {
                              mLogger.info("Stopping connector");
                              httpsConnector.stop();
                              mLogger.info("Waiting "+waitSeconds+" seconds after "+"stop"+" ...");
                              Thread.sleep(waitSeconds*1000);
                              mLogger.info("Starting connector");
                              httpsConnector.start();
                          }
                          else {
                              mLogger.error("Could not find connector object");
                          }
                      }
                      catch (Exception e) {
                          mLogger.error("Failed restarting connector",e);
                      }
                  }
                  else {
                      mLogger.warn("Operation is in process");
                  }
              }
              finally {
                  unlock();
              }
          }
      
          private void unlock() {
              if (rl.isHeldByCurrentThread()) {
                  mLogger.debug("Releasing lock");
                  rl.unlock();
              }
          }
      
          private boolean tryLock() {
              return !rl.isHeldByCurrentThread() && rl.tryLock();
          }
      
          private enum MBeanConnectorAction {
              start,stop,getState;
          }
      
          private abstract class MBeansObjectAction {
              private final ObjectName on;
              private final MBeanServer server;
      
              public MBeansObjectAction(ObjectName on, MBeanServer server) {
                  this.on = on;
                  this.server = server;
              }
      
              protected Object invoke(MBeanConnectorAction cmd) throws InstanceNotFoundException, ReflectionException, MBeanException {
                  return server.invoke(on, cmd.toString(), null, null);
              }
          }
      
          private class HTTPSConnectorMBean extends MBeansObjectAction {
      
              public HTTPSConnectorMBean(ObjectName on, MBeanServer server) {
                  super(on, server);
              }
      
              public void start() throws InstanceNotFoundException, ReflectionException, MBeanException {
                  invoke(MBeanConnectorAction.start);
              }
              public void stop() throws InstanceNotFoundException, ReflectionException, MBeanException {
                  invoke(MBeanConnectorAction.stop);
              }
              public Object status() throws InstanceNotFoundException, ReflectionException, MBeanException {
                  return invoke(MBeanConnectorAction.getState);
              }
          }
      }