【问题标题】:Spring Boot JettyServerCustomizer | HTTPS port not opened | A ServletContext is required to configure default servlet handlingSpring Boot JettyServerCustomizer | HTTPS 端口未打开 |需要 ServletContext 来配置默认 servlet 处理
【发布时间】:2014-07-31 15:17:46
【问题描述】:

我正在尝试使用嵌入的 Spring Boot。我希望嵌入式 Jetty 在 443 打开一个 HTTPS 端口。

参考here的答案后,我想出了这个配置:-

import java.io.FileNotFoundException;

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ssl.SslSocketConnector;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.embedded.jetty.JettyServerCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity;
import org.springframework.util.ResourceUtils;

import com.samsoft.expunto.service.UserService;

/**
 * @author Kumar Sambhav Jain
 * 
 */
@Configuration
@EnableWebMvcSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserService userService;

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity.authorizeRequests().antMatchers("/", "/resources/**")
                .permitAll().anyRequest().authenticated().and().formLogin()
                .loginPage("/").defaultSuccessUrl("/home", false).and()
                .requiresChannel().anyRequest().requiresSecure().and().logout()
                .invalidateHttpSession(true).logoutUrl("/logout")
                .logoutSuccessUrl("/").and().userDetailsService(userService);
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth)
            throws Exception {
    }

    @Bean
    public JettyServerCustomizer jettyCutomizer() {
        return new JettyServerCustomizer() {

            @Override
            public void customize(Server server) {
                SslContextFactory sslContextFactory = new SslContextFactory();
                sslContextFactory.setKeyStorePassword("jetty6");
                try {
                    sslContextFactory.setKeyStorePath(ResourceUtils.getFile(
                            "classpath:jetty-ssl.keystore").getAbsolutePath());
                } catch (FileNotFoundException ex) {
                    throw new IllegalStateException("Could not load keystore",
                            ex);
                }
                SslSocketConnector sslConnector = new SslSocketConnector(
                        sslContextFactory);
                sslConnector.setPort(443);
                sslConnector.setMaxIdleTime(60000);
                server.addConnector(sslConnector);
            }
        };
    }
}

尝试使用 spring-boot:run 运行应用程序,我可以在日志中看到端口 80 已打开但没有 HTTPS 端口:-

2014-06-10 23:41:56.932 信息 196 --- [lication.main()] /
: 初始化 Spring FrameworkServlet 'dispatcherServlet' 2014-06-10 23:41:56.932 信息 196 --- [lication.main()] os.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet':初始化开始于 2014-06-10 23:41:56.960 信息 196 --- [lication.main()] os.web.servlet.DispatcherServlet
: FrameworkServlet 'dispatcherServlet': 初始化在 26 完成 毫秒 2014-06-10 23:41:57.037 信息 196 --- [lication.main()] o.e.jetty.server.AbstractConnector :已启动 SelectChannelConnector@0.0.0.0:80 2014-06-10 23:41:57.043 信息 196 --- [lication.main()] .s.b.c.e.j.JettyEmbeddedServletContainer:码头在端口开始:80 2014-06-10 23:41:57.045 INFO 196 --- [lication.main()] c.s.expunto.web.config.Application : 已启动 应用 7.628 秒(JVM 运行 16.509)

更新


使用这个配置:-

@Configuration
@EnableWebMvcSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter
        implements EmbeddedServletContainerCustomizer {

    @Autowired
    private UserService userService;

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity.authorizeRequests().antMatchers("/", "/resources/**")
                .permitAll().anyRequest().authenticated().and().formLogin()
                .loginPage("/").defaultSuccessUrl("/home", false).and()
                .requiresChannel().anyRequest().requiresSecure().and().logout()
                .invalidateHttpSession(true).logoutUrl("/logout")
                .logoutSuccessUrl("/").and().userDetailsService(userService);
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth)
            throws Exception {
    }

    public JettyServerCustomizer jettyServerCustomizer() {
        return new JettyServerCustomizer() {

            @Override
            public void customize(Server server) {
                SslContextFactory sslContextFactory = new SslContextFactory();
                sslContextFactory.setKeyStorePassword("jetty6");
                try {
                    sslContextFactory.setKeyStorePath(ResourceUtils.getFile(
                            "classpath:jetty-ssl.keystore").getAbsolutePath());
                } catch (FileNotFoundException ex) {
                    throw new IllegalStateException("Could not load keystore",
                            ex);
                }
                SslSocketConnector sslConnector = new SslSocketConnector(
                        sslContextFactory);
                sslConnector.setPort(443);
                sslConnector.setMaxIdleTime(60000);
                server.addConnector(sslConnector);
            }
        };
    }

    public void customizeJetty(
            JettyEmbeddedServletContainerFactory containerFactory) {
        containerFactory.addServerCustomizers(jettyServerCustomizer());
    }

    @Override
    public void customize(ConfigurableEmbeddedServletContainer container) {
        if (container instanceof JettyEmbeddedServletContainerFactory) {
            customizeJetty((JettyEmbeddedServletContainerFactory) container);
        }
        container.setContextPath("");
    }
}

我得到这个错误:-

: java.lang.IllegalArgumentException: A ServletContext is required to configure default servlet handling
    at org.springframework.util.Assert.notNull(Assert.java:112)
    at org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer.<init>(DefaultServletHandlerConfigurer.java:54)
    at org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport.defaultServletHandlerMapping(WebMvcConfigurationSupport.java:346)
    at org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration$$EnhancerBySpringCGLIB$$d7014349.CGLIB$defaultServletHandlerMapping$24(<generated>)
    at org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration$$EnhancerBySpringCGLIB$$d7014349$$FastClassBySpringCGLIB$$ec8be680.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:312)
    at org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration$$EnhancerBySpringCGLIB$$d7014349.defaultServletHandlerMapping(<generated>)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:166)

【问题讨论】:

  • 没有什么可以阻止您使用简单的 @Bean 注释方法使其工作。尝试将该方法与内部类放在使用@EnableAutoConfiguration 配置的@Configuration 类中。
  • 将其移至使用 @EnableAutoConfiguration 注释的类已修复!

标签: https embedded-jetty spring-boot


【解决方案1】:

根据 M. Deinum 的建议,将定制器移动到使用 @EnableAutoConfiguration 注释的类就可以了。

这对我有用:-

@Configuration

@EnableAutoConfiguration
public class Application implements EmbeddedServletContainerCustomizer {

    public static void main(String[] args) {
        SpringApplication.run(Application.class);
    }

    @Bean
    public JettyServerCustomizer jettyServerCustomizer() {
        return new JettyServerCustomizer() {

            @Override
            public void customize(Server server) {
                SslContextFactory sslContextFactory = new SslContextFactory();
                sslContextFactory.setKeyStorePassword("jetty6");
                try {
                    sslContextFactory.setKeyStorePath(ResourceUtils.getFile(
                            "classpath:jetty-ssl.keystore").getAbsolutePath());
                } catch (FileNotFoundException ex) {
                    throw new IllegalStateException("Could not load keystore",
                            ex);
                }
                SslSocketConnector sslConnector = new SslSocketConnector(
                        sslContextFactory);
                sslConnector.setPort(443);
                sslConnector.setMaxIdleTime(60000);
                server.addConnector(sslConnector);
            }
        };
    }

    public void customizeJetty(
            JettyEmbeddedServletContainerFactory containerFactory) {
        containerFactory.addServerCustomizers(jettyServerCustomizer());
    }

    @Override
    public void customize(ConfigurableEmbeddedServletContainer container) {
        if (container instanceof JettyEmbeddedServletContainerFactory) {
            customizeJetty((JettyEmbeddedServletContainerFactory) container);
        }
    }
}

【讨论】:

  • 太好了。小说明:它不起作用,因为您的 servlet 容器是在 @EnableAutoConfiguration 中定制的,它起作用是因为定制是在安全配置器中完成的not(Spring Security 是 Filter 所以它必须是设置在容器生命周期中的特殊位置)。
猜你喜欢
  • 2016-07-28
  • 2014-02-26
  • 2014-11-10
  • 2017-02-10
  • 2017-06-02
  • 2014-05-25
  • 2016-02-23
  • 2019-03-10
  • 2020-12-12
相关资源
最近更新 更多