应用同时支持HTTP和HTTPS
生成证书:keytool -genkeypair -keystore test.jks -alias test -keyalg RSA -keysize 2048 -validity 3650
应用配置:
server:
port: 18081 #https
http-port: 8081 #http
ssl:
key-store: /test.jks # 密钥库路径
key-store-password: ENC(djVg6Ri/rp7cHwh9ZTmq/Q==) # 密钥库密码
key-alias: test # 密钥库别名
enabled: true
NettyServer、Tomcat、Undertow,可将以下内容下沉至公共包,根据项目引用的包自动加载需要的类:
import cn.hutool.extra.spring.SpringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory;
import org.springframework.boot.web.server.WebServer;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.http.server.reactive.HttpHandler;
import org.springframework.stereotype.Component;
import java.util.Objects;
@Slf4j
@Component
@ConditionalOnProperty(value = "server.ssl.enabled", havingValue = "true")
@ConditionalOnClass({NettyReactiveWebServerFactory.class, HttpHandler.class, WebServer.class})
public class NettyServerCustomer implements WebServerFactoryCustomizer<NettyReactiveWebServerFactory> {
@Override
public void customize(NettyReactiveWebServerFactory factory) {
Integer httpPort = SpringUtil.getProperty("server.http-port", Integer.class, null);
if (Objects.nonNull(httpPort)) {
HttpHandler httpHandler = SpringUtil.getBean(HttpHandler.class);
NettyReactiveWebServerFactory httpFactory = new NettyReactiveWebServerFactory(httpPort);
WebServer webServer = httpFactory.getWebServer(httpHandler);
webServer.start();
log.info("Netty Server Started, HTTP Port: {}", httpPort);
}
}
}
import cn.hutool.extra.spring.SpringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.connector.Connector;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.stereotype.Component;
import java.util.Objects;
@Slf4j
@Component
@ConditionalOnProperty(value = "server.ssl.enabled", havingValue = "true")
@ConditionalOnClass({TomcatServletWebServerFactory.class, Connector.class})
public class TomcatServerCustomer implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> {
@Override
public void customize(TomcatServletWebServerFactory factory) {
Integer httpPort = SpringUtil.getProperty("server.http-port", Integer.class, null);
if (Objects.nonNull(httpPort)) {
Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
connector.setPort(httpPort);
connector.setScheme("http");
factory.addAdditionalTomcatConnectors(connector);
log.info("Tomcat Server Started, HTTP Port: {}", httpPort);
}
}
}
import cn.hutool.extra.spring.SpringUtil;
import io.undertow.Undertow;
import io.undertow.UndertowOptions;
import io.undertow.servlet.api.SecurityConstraint;
import io.undertow.servlet.api.SecurityInfo;
import io.undertow.servlet.api.TransportGuaranteeType;
import io.undertow.servlet.api.WebResourceCollection;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.stereotype.Component;
import java.util.Objects;
@Slf4j
@Component
@ConditionalOnProperty(value = "server.ssl.enabled", havingValue = "true")
@ConditionalOnClass({UndertowServletWebServerFactory.class, SecurityConstraint.class, Undertow.class})
public class UndertowServerCustomer implements WebServerFactoryCustomizer<UndertowServletWebServerFactory> {
@Override
public void customize(UndertowServletWebServerFactory factory) {
Integer httpPort = SpringUtil.getProperty("server.http-port", Integer.class, null);
Integer httpsPort = SpringUtil.getProperty("server.port", Integer.class, null);
if (Objects.nonNull(httpPort) && Objects.nonNull(httpsPort)) {
factory.addBuilderCustomizers(builder -> {
builder.addHttpListener(httpPort, "0.0.0.0");
builder.setServerOption(UndertowOptions.ENABLE_HTTP2, true);
});
factory.addDeploymentInfoCustomizers(deploymentInfo ->
deploymentInfo.addSecurityConstraint(
new SecurityConstraint()
.addWebResourceCollection(new WebResourceCollection().addUrlPatterns("/*"))
.setTransportGuaranteeType(TransportGuaranteeType.CONFIDENTIAL)
.setEmptyRoleSemantic(SecurityInfo.EmptyRoleSemantic.PERMIT))
.setConfidentialPortManager(e -> httpsPort));
log.info("Undertow Server Started, HTTP Port: {}", httpPort);
}
}
}
此时应用启动后,支持http与https;
注册中心注册的端口时https,若以http为主,则还需修改 FeignClient、RestTemplate配置以支持https;
若要以http为主,则修改注册中心注册端口
spring: cloud: consul: discovery: port: ${server.http-port:${server.port}} nacos: discovery: port: ${server.http-port:${server.port}}
若不想启停https时来回修改端口
import cn.hutool.core.util.BooleanUtil; import org.springframework.boot.SpringApplication; import org.springframework.boot.env.EnvironmentPostProcessor; import org.springframework.core.Ordered; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.MutablePropertySources; import org.springframework.core.env.PropertiesPropertySource; import java.util.Properties; /**
* 将该类加入spring.factories
* org.springframework.boot.env.EnvironmentPostProcessor=com.leadingtek.arteryf.gateway.config.ServerPortEnvPostProcessor
*
*/
public class ServerPortEnvPostProcessor implements EnvironmentPostProcessor, Ordered {
@Override public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { String sslPortEnable = environment.getProperty("server.ssl.enabled"); Integer httpPort = environment.getProperty("server.http-port", Integer.class); if (!BooleanUtil.toBoolean(sslPortEnable) && httpPort != null) { Properties properties = new Properties(); properties.put("server.port", httpPort); MutablePropertySources propertySources = environment.getPropertySources(); propertySources.addFirst(new PropertiesPropertySource("server-port-properties", properties)); } } @Override public int getOrder() { return Integer.MAX_VALUE; } }