diff --git a/hutool-http/pom.xml b/hutool-http/pom.xml index b89cbf499..cd77fa84b 100755 --- a/hutool-http/pom.xml +++ b/hutool-http/pom.xml @@ -142,7 +142,7 @@ org.slf4j slf4j-simple - 2.0.9 + 1.7.36 test diff --git a/hutool-http/src/main/java/org/dromara/hutool/http/server/engine/tomcat/JSSESSLContext.java b/hutool-http/src/main/java/org/dromara/hutool/http/server/engine/tomcat/JSSESSLContext.java new file mode 100644 index 000000000..fea5db83b --- /dev/null +++ b/hutool-http/src/main/java/org/dromara/hutool/http/server/engine/tomcat/JSSESSLContext.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2024 Hutool Team and hutool.cn + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.dromara.hutool.http.server.engine.tomcat; + +import org.apache.tomcat.util.net.SSLContext; + +import javax.net.ssl.*; +import java.security.KeyManagementException; +import java.security.SecureRandom; +import java.security.cert.X509Certificate; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +/** + * Tomcat SSLContext实现 + * + * @author looly + * @since 6.0.0 + */ +public class JSSESSLContext implements SSLContext { + + private final javax.net.ssl.SSLContext context; + private KeyManager[] kms; + private TrustManager[] tms; + + /** + * 构造 + * + * @param context SSLContext + */ + public JSSESSLContext(final javax.net.ssl.SSLContext context) { + this.context = context; + } + + @Override + public void init(final KeyManager[] kms, final TrustManager[] tms, final SecureRandom sr) + throws KeyManagementException { + this.kms = kms; + this.tms = tms; + context.init(kms, tms, sr); + } + + @Override + public void destroy() { + } + + @Override + public SSLSessionContext getServerSessionContext() { + return context.getServerSessionContext(); + } + + @Override + public SSLEngine createSSLEngine() { + return context.createSSLEngine(); + } + + @Override + public SSLServerSocketFactory getServerSocketFactory() { + return context.getServerSocketFactory(); + } + + @Override + public SSLParameters getSupportedSSLParameters() { + return context.getSupportedSSLParameters(); + } + + @Override + public X509Certificate[] getCertificateChain(final String alias) { + X509Certificate[] result = null; + if (kms != null) { + for (int i = 0; i < kms.length && result == null; i++) { + if (kms[i] instanceof X509KeyManager) { + result = ((X509KeyManager) kms[i]).getCertificateChain(alias); + } + } + } + return result; + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + final Set certs = new HashSet<>(); + if (tms != null) { + for (final TrustManager tm : tms) { + if (tm instanceof X509TrustManager) { + final X509Certificate[] accepted = ((X509TrustManager) tm).getAcceptedIssuers(); + certs.addAll(Arrays.asList(accepted)); + } + } + } + return certs.toArray(new X509Certificate[0]); + } +} diff --git a/hutool-http/src/main/java/org/dromara/hutool/http/server/engine/tomcat/TomcatEngine.java b/hutool-http/src/main/java/org/dromara/hutool/http/server/engine/tomcat/TomcatEngine.java index 8b35b8fdb..209152291 100644 --- a/hutool-http/src/main/java/org/dromara/hutool/http/server/engine/tomcat/TomcatEngine.java +++ b/hutool-http/src/main/java/org/dromara/hutool/http/server/engine/tomcat/TomcatEngine.java @@ -24,12 +24,16 @@ import org.apache.catalina.connector.Response; import org.apache.catalina.startup.Tomcat; import org.apache.catalina.valves.ValveBase; import org.apache.coyote.http11.Http11NioProtocol; +import org.apache.tomcat.util.net.SSLHostConfig; +import org.apache.tomcat.util.net.SSLHostConfigCertificate; import org.dromara.hutool.core.lang.Assert; import org.dromara.hutool.core.text.StrUtil; import org.dromara.hutool.http.HttpException; import org.dromara.hutool.http.server.ServerConfig; import org.dromara.hutool.http.server.engine.AbstractServerEngine; +import javax.net.ssl.SSLContext; + /** * Tomcat引擎实现 * @@ -88,20 +92,18 @@ public class TomcatEngine extends AbstractServerEngine { tomcat.setHostname(config.getHost()); tomcat.setBaseDir(config.getRoot()); - initConnector(tomcat); + tomcat.setConnector(createConnector()); initContext(tomcat); - // TODO 配置支持HTTPS - this.tomcat = tomcat; } /** - * 初始化Connector + * 创建Connector * - * @param tomcat Tomcat + * @return Connector */ - private void initConnector(final Tomcat tomcat) { + private Connector createConnector() { final ServerConfig config = this.config; final Http11NioProtocol protocol = new Http11NioProtocol(); final int maxHeaderSize = config.getMaxHeaderSize(); @@ -120,7 +122,21 @@ public class TomcatEngine extends AbstractServerEngine { connector.setMaxPostSize(maxBodySize); } - tomcat.setConnector(connector); + // SSL配置 + final SSLContext sslContext = config.getSslContext(); + if(null != sslContext){ + final SSLHostConfig sslHostConfig = new SSLHostConfig(); + final SSLHostConfigCertificate sslHostConfigCertificate = + new SSLHostConfigCertificate(sslHostConfig, SSLHostConfigCertificate.Type.RSA); + sslHostConfigCertificate.setSslContext(new JSSESSLContext(sslContext)); + sslHostConfig.addCertificate(sslHostConfigCertificate); + connector.addSslHostConfig(sslHostConfig); + connector.setScheme("https"); + connector.setSecure(true); + connector.setPort(config.getPort()); + } + + return connector; } /**