Embedded Jetty doesn't recognise Spring MVC Se

2019-03-17 01:40发布

问题:

I am developing a Spring application that starts an embedded Jetty Server. It then "deploys" a Spring MVC web app to this Jetty server.

All is working well with multiple controllers, but I fail to add Spring Security to the web app. I use programmatic and annotation-based configuration and the Jetty server is configured like this:

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);

I also created a class com.mypackage.web.SecurityConfig that extends WebSecurityConfigurerAdapter and overrides the configure method like so:

@Configuration
@EnableWebMvcSecurity  
public class SecurityConfig extends WebSecurityConfigurerAdapter {

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

As far as I understand the documentation, this should be enough to "lock down" my application. When I start the application in debug mode, a breakpoint gets hit in the configure method, so Spring seems to detect the config class.

However, I can still access any page in my application without getting redirected to the default login form.

Do I need to tell the Jetty Servlet container about this config or am I missing something else?

回答1:

Okay, so what I missed is that I need to add Spring's DelegatingFilterProxy to Jetty's ServletContextHandler. The usual Spring way is to extend AbstractSecurityWebApplicationInitializer, which will add the Filter Proxy. This unfortunately also didn't work with Jetty.

One can add the Filter Proxy manually to Jetty, though, with a call explained in this comment:

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 ));

I also had to enable Session-Handling in Jetty, but this is explained very well here.