Jetty嵌入式+ Spring MVC + Spring安全性+ Https

时间:2017-04-24 10:16:23

标签: spring spring-mvc spring-security https embedded-jetty

我正在配置具有此要求的系统:

  • Spring MVC
  • Jetty 9 embedded
  • Spring Https安全

Spring Boot可能是一个很好的起点,但由于我们的旧硬件而无法正常工作。我们需要使用这些部分配置Spring。

我有一个使用Spring MVC,Jetty和Spring Security的工作代码但是通过Http:

Spring Security:

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Value("${web.security.http.username1}") private String webUser1;
    @Value("${web.security.http.password1}") private String webPassword1;

    private static String REALM = "MY_TEST_REALM";

    @Autowired
    protected void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception, BadCredentialsException {

        auth.inMemoryAuthentication()
            .withUser( webUser1 ).password( webPassword1 ).roles("USER");
    }

    /**
     * Ignored resources
     */
    @Override
    public void configure(WebSecurity web) throws Exception {
        web
        .ignoring().antMatchers("/css/**", "/js/**", "/webjars/**")
        .and()
        .ignoring().antMatchers(HttpMethod.OPTIONS, "/**");
    }  

    @Override
    protected void configure(HttpSecurity http) throws Exception {

      http      
        .authorizeRequests()
        .antMatchers("/**").hasRole("USER")
        .and()
            .csrf()        
        .and()
            .httpBasic().authenticationEntryPoint(entryPoint())
        .and()
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).sessionFixation().none()
        .and()
            .headers()
                .xssProtection()
            .and()
                .frameOptions()
            .and()
                .httpStrictTransportSecurity()
                .includeSubDomains(true)
                .maxAgeInSeconds(60 * 60)               
            .and()
                .contentTypeOptions()
            .and()
                .contentSecurityPolicy(""
                            + "default-src 'self'; " 
                            + "script-src 'self'; "
                            + "connect-src 'self'; "
                            + "img-src 'self'; "
                            + "font-src 'self'; "
                            + "frame-ancestors 'none'; "
                            + "base-uri 'self'; "
                            + "form-action 'self'; "
                            + "style-src 'self' 'unsafe-inline' 'unsafe-eval'; ")
            .and()
                // internet explorer
                .addHeaderWriter(new StaticHeadersWriter("X-Content-Security-Policy","sandbox"));   
    }

    @Bean
    public BasicAuthenticationEntryPoint entryPoint() {
        BasicAuthenticationEntryPoint entryPoint = new BasicAuthenticationEntryPoint();
        entryPoint.setRealmName(REALM);
        return entryPoint;
    }
}

码头配置:

@Bean
    public WebAppContext jettyWebAppContext() throws IOException {

        WebAppContext webUiContext = new WebAppContext();
        webUiContext.setContextPath(jettyContextPath);
        webUiContext.setWar(new ClassPathResource("webapp").getURI().toString());
        webUiContext.setInitParameter("dirAllowed", "false");
        webUiContext.setParentLoaderPriority(true);

        GenericWebApplicationContext webApplicationContext = new GenericWebApplicationContext();
        webApplicationContext.setParent(applicationContext);
        webApplicationContext.refresh();
        webUiContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, webApplicationContext);
        webUiContext.addEventListener(new WebMvcContextInit());
        webUiContext.addFilter(
            new FilterHolder( new DelegatingFilterProxy( 
                    AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME ) ), 
                    "/*", EnumSet.allOf( DispatcherType.class )
        );

        return webUiContext;
    }



@Bean(initMethod = "start", destroyMethod = "stop")
    public Server jettyServer() throws IOException {

JettyConfigurationMapper mappedFile = readJettyAccessConfigurationMapper();
            Server server = new Server(new InetSocketAddress(jettyHost, jettyPort));
            InetAccessHandler inetAccessHandler = buildInetAccessHandler(mappedFile);
            server.setHandler(inetAccessHandler);
            inetAccessHandler.setHandler(jettyWebAppContext());
            return server;
}

当我使用以下代码将jetty配置更改为https时,我只在浏览器中看到403 Forbidden,其中包含任何安全表单(http basic auth):

@Bean(initMethod = "start", destroyMethod = "stop")
    public Server jettyServer() throws IOException {

        System.setProperty("jsse.enableSNIExtension", "false");

            HttpConfiguration httpConfig = new HttpConfiguration();         
            httpConfig.setSecureScheme("https");
            httpConfig.setSecurePort(jettyPort);

            HttpConfiguration httpsConfig = new HttpConfiguration(httpConfig);
            httpsConfig.addCustomizer(new SecureRequestCustomizer());

            Resource jksFile = resourceLoader.getResource("classpath:" + myKeystoreJks);
            SslContextFactory sslContextFactory = new SslContextFactory();
            sslContextFactory.setKeyStorePath(jksFile.getURL().toExternalForm());
            sslContextFactory.setKeyStorePassword(myKeystorePassword);

            Server server = new Server(new InetSocketAddress(jettyHost, 8080));
            ServerConnector sslConnector = new ServerConnector(server, new SslConnectionFactory(sslContextFactory, "http/1.1"), 
                    new HttpConnectionFactory(httpsConfig));
            sslConnector.setPort(jettyPort);
            server.setConnectors(new Connector[] { sslConnector });
            JettyConfigurationMapper mappedFile = readJettyAccessConfigurationMapper();
            InetAccessHandler inetAccessHandler = buildInetAccessHandler(mappedFile);
            server.setHandler(inetAccessHandler);
            inetAccessHandler.setHandler(jettyWebAppContext());

            return server;
    }

1 个答案:

答案 0 :(得分:1)

我使用服务器连接器而不是服务器构造函数解决了问题。这适用于Https。

来自

Server server = new Server(new InetSocketAddress(jettyHost, 8080));
ServerConnector sslConnector = new ServerConnector(server, new SslConnectionFactory(sslContextFactory, "http/1.1"), 
new HttpConnectionFactory(httpsConfig));
sslConnector.setPort(jettyPort);

要:

Server server = new Server();
ServerConnector sslConnector = new ServerConnector(server, new SslConnectionFactory(sslContextFactory, "http/1.1"), 
new HttpConnectionFactory(httpsConfig));
sslConnector.setPort(jettyPort);
sslConnector.setHost(jettyHost);