【问题标题】:Spring Boot Jetty Auto Redirect HTTP (Port 80) requests to HTTPS (Port 8443)Spring Boot Jetty 自动将 HTTP(端口 80)请求重定向到 HTTPS(端口 8443)
【发布时间】:2018-08-23 07:12:51
【问题描述】:

我有以下代码来配置 Jetty 服务器:

@Configuration
public class RedirectHttpToHttpsOnJetty2Config {

    @Bean
    public ConfigurableServletWebServerFactory webServerFactory() {
        JettyServletWebServerFactory factory = new JettyServletWebServerFactory();
            factory.addServerCustomizers(new JettyServerCustomizer() {

                @Override
                public void customize(Server server) {
                    ServerConnector connector = new ServerConnector(server);
                    connector.setPort(80);
                    server.addConnector(connector);
                }
            });
        return factory;
    }
}

application.properties 为

server.port=8443
server.ssl.key-store=classpath:keystore
server.ssl.key-store-password=xyzxyzxyz
server.ssl.key-password=xyzxyzxyz

当我访问 localhost:8443 但无法访问 localhost:80 时,我的应用程序可以正常工作。 gradlew bootRun 提到

... Jetty 在端口 8443 (ssl, http/1.1)、80 (http/1.1) 上启动,上下文路径为“/” ...

但在访问http://localhost:80 时,我收到了消息

无法访问此站点... localhost 拒绝连接。

我正在寻找 http://localhost:80 被重定向到 https://localhost:8443

我让它在 Tomcat 中工作:

    @Bean
    public ServletWebServerFactory servletContainer(){
        TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory(){
            @Override
            protected void postProcessContext(Context context) {
                SecurityConstraint securityConstraint = new SecurityConstraint();
                 securityConstraint.setUserConstraint("CONFIDENTIAL");
                 SecurityCollection collection = new SecurityCollection();
                 collection.addPattern("/*");
                 securityConstraint.addCollection(collection);
                 context.addConstraint(securityConstraint);
             }
         };
         tomcat.addAdditionalTomcatConnectors(redirectConnector());
         return tomcat;
     }

    private Connector redirectConnector(){
        Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
        connector.setScheme("http");
        connector.setPort(80);
        connector.setSecure(false);
        connector.setRedirectPort(8443);
        return connector;
    }

但无法找到 Jetty 的等价物。任何指针都非常感谢。

【问题讨论】:

  • 您在您的ServerConnector 上缺少一个HttpConfiguration,该ServerConnector 需要存在以至少识别什么是端口(安全与非安全)。

标签: spring-boot embedded-jetty http-redirect


【解决方案1】:

以下配置将设置从 HTTP 到 HTTPS 的重定向。它假定你已经配置 Spring Boot 监听 443 端口并且 SSL 配置正确。

@Bean
public ConfigurableServletWebServerFactory webServerFactory() {
    JettyServletWebServerFactory factory = new JettyServletWebServerFactory();
    factory.addServerCustomizers(new JettyServerCustomizer() {
        @Override
        public void customize(Server server) {
            final HttpConnectionFactory httpConnectionFactory = server.getConnectors()[0].getConnectionFactory(HttpConnectionFactory.class);

            final ServerConnector httpConnector = new ServerConnector(server, httpConnectionFactory);
            httpConnector.setPort(80 /* HTTP */);
            server.addConnector(httpConnector);

            final HandlerList handlerList = new HandlerList();
            handlerList.addHandler(new SecuredRedirectHandler());
            for(Handler handler : server.getHandlers())
                handlerList.addHandler(handler);
            server.setHandler(handlerList);
        }
    });
    return factory;
}

【讨论】:

    【解决方案2】:

    您在端口 80 上缺少所需的 HttpConfiguration ServerConnector 来告诉 Jetty 您的安全端口和不安全端口是什么。

    Jetty 端 SecuredRedirectHandler 是重定向的实际功能。

    见:https://github.com/jetty-project/embedded-jetty-cookbook/blob/master/src/main/java/org/eclipse/jetty/cookbook/SecuredRedirectHandlerExample.java

    SecuredRedirectHandlerExample.java

    package org.eclipse.jetty.cookbook;
    
    import java.net.URL;
    
    import org.eclipse.jetty.cookbook.handlers.HelloHandler;
    import org.eclipse.jetty.server.HttpConfiguration;
    import org.eclipse.jetty.server.HttpConnectionFactory;
    import org.eclipse.jetty.server.SecureRequestCustomizer;
    import org.eclipse.jetty.server.Server;
    import org.eclipse.jetty.server.ServerConnector;
    import org.eclipse.jetty.server.SslConnectionFactory;
    import org.eclipse.jetty.server.handler.HandlerList;
    import org.eclipse.jetty.server.handler.SecuredRedirectHandler;
    import org.eclipse.jetty.util.ssl.SslContextFactory;
    
    public class SecuredRedirectHandlerExample
    {
        public static void main(String[] args) throws Exception
        {
            Server server = new Server();
            int httpPort = 8080;
            int httpsPort = 8443;
    
            // Setup HTTP Connector
            HttpConfiguration httpConf = new HttpConfiguration();
            httpConf.setSecurePort(httpsPort);
            httpConf.setSecureScheme("https");
    
            // Establish the HTTP ServerConnector
            ServerConnector httpConnector = new ServerConnector(server,
                    new HttpConnectionFactory(httpConf));
            httpConnector.setPort(httpPort);
            server.addConnector(httpConnector);
    
            // Find Keystore for SSL
            ClassLoader cl = SecuredRedirectHandlerExample.class.getClassLoader();
            String keystoreResource = "ssl/keystore";
            URL f = cl.getResource(keystoreResource);
            if (f == null)
            {
                throw new RuntimeException("Unable to find " + keystoreResource);
            }
    
            // Setup SSL
            SslContextFactory sslContextFactory = new SslContextFactory();
            sslContextFactory.setKeyStorePath(f.toExternalForm());
            sslContextFactory.setKeyStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4");
            sslContextFactory.setKeyManagerPassword("OBF:1u2u1wml1z7s1z7a1wnl1u2g");
    
            // Setup HTTPS Configuration
            HttpConfiguration httpsConf = new HttpConfiguration(httpConf);
            httpsConf.addCustomizer(new SecureRequestCustomizer()); // adds ssl info to request object
    
            // Establish the HTTPS ServerConnector
            ServerConnector httpsConnector = new ServerConnector(server,
                    new SslConnectionFactory(sslContextFactory,"http/1.1"),
                    new HttpConnectionFactory(httpsConf));
            httpsConnector.setPort(httpsPort);
    
            server.addConnector(httpsConnector);
    
            // Add a Handlers for requests
            HandlerList handlers = new HandlerList();
            handlers.addHandler(new SecuredRedirectHandler()); // always first
            handlers.addHandler(new HelloHandler("Hello Secure World"));
            handlers.addHandler(new DefaultHandler()); // always last
            server.setHandler(handlers);
    
            server.start();
            server.join();
        }
    }
    

    【讨论】:

    • 谢谢!这有帮助。虽然构建通过 server.start() 失败:“ConfigServletWebServerApplicationContext:在上下文初始化期间遇到异常 - 取消刷新尝试:org.springframework.context.ApplicationContextException:无法启动 Web 服务器;嵌套异常是 java.lang.IllegalStateException:无法启动服务器”。如果 server.start() 被注释,那么还有另一个:“BeanInstantiationException: Failed to instantiate ...servlet.HandlerMapping]: Factory method 'resourceHandlerMapping' throw IllegalStateException: No ServletContext set”。
    • 不错! SecuredRedirectHandler 的“永远第一”部分帮助了 :)
    猜你喜欢
    • 2014-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-02
    • 2021-05-02
    • 2021-01-31
    • 1970-01-01
    • 2013-10-26
    相关资源
    最近更新 更多