嵌入式Jetty无法识别Spring MVC安全性


问题内容

我正在开发一个启动嵌入式Jetty服务器的Spring应用程序。然后,它将Spring MVC Web应用程序“部署”到此Jetty服务器。

所有人都可以在多个控制器上正常工作,但是我无法将Spring
Security添加到Web应用程序中。我使用基于程序和基于注释的配置,并且Jetty服务器的配置如下:

Server server = new Server(8080);
server.setStopAtShutdown(true);
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.setConfigLocation("com.mypackage.web");
context.setParent(mainContext);

ServletContextHandler contextHandler = new ServletContextHandler();
contextHandler.setErrorHandler(null);
contextHandler.setContextPath("/");

DispatcherServlet dispatcherServlet = new DispatcherServlet(context);
DefaultServlet staticServlet = new DefaultServlet();

contextHandler.addServlet(new ServletHolder(dispatcherServlet), "/");
contextHandler.addServlet(new ServletHolder("staticServlet", staticServlet), "/res");
contextHandler.addEventListener(new ContextLoaderListener(context));
contextHandler.setResourceBase("webapp");

server.setHandler(contextHandler);

我还创建了com.mypackage.web.SecurityConfig类,该类扩展WebSecurityConfigurerAdapter并覆盖了configure方法,如下所示:

@Configuration
@EnableWebMvcSecurity  
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .anyRequest().authenticated()
                .and()
            .formLogin().and()
            .httpBasic();
    }
}

据我了解的文档,这应该足以“锁定”我的应用程序。当我以调试模式启动应用程序时,在configure方法中会遇到一个断点,因此Spring似乎会检测到config类。

但是,我仍然可以访问应用程序中的任何页面,而无需重定向到默认登录表单。

我需要告诉Jetty Servlet容器有关此配置的信息吗?


问题答案:

好的,所以我想念的是我需要将Spring的DelegatingFilterProxy添加到Jetty的ServletContextHandler中。Spring常用的方法是扩展AbstractSecurityWebApplicationInitializer,这将添加筛选器代理。不幸的是,这也不适用于Jetty。

不过,您可以手动将过滤器代理添加到Jetty,并在此注释说明一个调用:

import static org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME;
...
ServletContextHandler contextHandler = new ServletContextHandler();
...
contextHandler.addFilter(
    new FilterHolder( new DelegatingFilterProxy( DEFAULT_FILTER_NAME ) ),
    "/*",
    EnumSet.allOf( DispatcherType.class ));

我也不得不启用码头会话处理,但这是很好的解释在这里。