以编程方式更新tomcat 8中的证书而无需重新启动服务器 [英] Programmatically update certificates in tomcat 8 without server restart

查看:74
本文介绍了以编程方式更新tomcat 8中的证书而无需重新启动服务器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了更新用于服务器的SSL的证书,我有一个代码可以执行所需的import \ export和验证.

In order to update the certificate that I use for SSL for my server I have a code that does the import\export and validation that I need.

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

It works well, but In order for the changes to take effect I have to restart the tomcat.
I wish to avoid the restart, and update it without using external tools (keytool for example).
I looked up for some similar questions, and found a solution - restarting the 443 connector. I'm able to do so, and the connector is stopping and starting, but the certificate was not updated. Only server restart actually updates it.

我缺少一些连接器初始化过程吗?
我应该清除一些系统缓存或对象吗?

Is there some connector initialisation procedure that I'm missing?
Some system cache or objects that I should clear?

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

This is the code that I use for restarting the connector:

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信息[BG-任务重启Tomcat连接器] org.apache.coyote.AbstractProtocol.stop正在停止ProtocolHandler ["http-nio-443"]
2017年4月23日15:42:01.349信息[BG-任务重启Tomcat连接器] org.apache.coyote.AbstractProtocol.start启动ProtocolHandler ["http-nio-443"]

I see in the tomcat logs the following traces of the connector restart:
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"]

推荐答案

问题已解决,这些是组件:

The problem was solved, these are the components:

  1. server.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"
/>

  • 用于重新启动连接器的Java代码:

  • The Java code for the connector restart:

    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);
            }
        }
    }
    

  • 这篇关于以编程方式更新tomcat 8中的证书而无需重新启动服务器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆