Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

/api-url has an empty filter list in Spring Boot Security

A Spring Boot app with REST services has to allow public access to certain services, while restricting other services to only authorized users. When a configure(WebSecurity web) method is added to the SecurityConfig class as shown below, a 403 error is sent to the user's web browser, and the Spring Boot log files give an error stating that:

/registration-form has an empty filter list  

What specific changes need to be made to the code below to get the /registration-form service to be successfully served up to any user, including anonymous/un-authenticated users?

Here is the SecurityConfig class:

@Configuration
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
protected static class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(WebSecurity webSecurity) throws Exception {
        webSecurity.ignoring().antMatchers("/registration-form");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .formLogin()
                .and()
            .httpBasic().and()
            .authorizeRequests()
                .antMatchers("/login1").permitAll()
                .antMatchers("/login2").permitAll()
                .anyRequest().authenticated();
    }
}

And here is the complete log:

2016-04-07 16:42:18.548  INFO 8937 --- [nio-8001-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring FrameworkServlet 'dispatcherServlet'
2016-04-07 16:42:18.548  INFO 8937 --- [nio-8001-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization started
2016-04-07 16:42:18.656  INFO 8937 --- [nio-8001-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization completed in 108 ms
2016-04-07 16:42:18.702 DEBUG 8937 --- [nio-8001-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher  : Checking match of request : '/registration-form'; against '/css/**'
2016-04-07 16:42:18.702 DEBUG 8937 --- [nio-8001-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher  : Checking match of request : '/registration-form'; against '/js/**'
2016-04-07 16:42:18.702 DEBUG 8937 --- [nio-8001-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher  : Checking match of request : '/registration-form'; against '/images/**'
2016-04-07 16:42:18.702 DEBUG 8937 --- [nio-8001-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher  : Checking match of request : '/registration-form'; against '/**/favicon.ico'
2016-04-07 16:42:18.702 DEBUG 8937 --- [nio-8001-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher  : Checking match of request : '/registration-form'; against '/error'
2016-04-07 16:42:18.702 DEBUG 8937 --- [nio-8001-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher  : Checking match of request : '/registration-form'; against '/registration-form'
2016-04-07 16:42:18.702 DEBUG 8937 --- [nio-8001-exec-1] o.s.security.web.FilterChainProxy        : /registration-form has an empty filter list

In pom.xml, the only reference to security is the following:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>

I looked around for a version number in pom.xml, and the closest thing I could find was:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.3.0.RELEASE</version>
    <relativePath /> <!-- lookup parent from repository -->
</parent>

ONGOING RESEARCH:


1.) This other post gives a good explanation of the difference between WebSecurity and HttpSecurity, and thus explains why I included both WebSecurity and HttpSecurity in my code shown above.

2.) This 2012 post describes a similar error and solution, but is focused on an old version of Spring Security in general using xml configuration, and is not specific to Spring Boot with Java Configuration.

3.) This blog entry explains that old xml config files like web.xml are largely replaced by the new application.properties file in Spring Boot. I am therefore not sure whether the solution to the present problem is in adding something application.properties, or adding some Java Config for Spring Security.

4.) This blog entry describes using the @Bean annotation to inject a ServletContextInitializer bean which adds a filter to an end point that was described by @RequestMapping annotation in a Spring Boot Controller class. The example is a multi-part file filter, but I wonder if this approach could be used to add an appropriate filter to resolve the current OP error message.

5.) This 2014 posting describes two approaches to customizing the behavior of a ServletContextInitializer in Spring Boot. One approach is to have the Application.java class extend SpringBootServletInitializer and then override the configure() and onStartup() methods. The other approach shown is to add lines to the application.properties file using the server namespace. A list of common properties that can be set in application.properties is given at this link, but I could not determine which properties to set to resolve the problem defined by the current OP.

6.) @DaveSyer's answer to this related question suggests setting endpoints.info.sensitive=true in application.properties to make ALL endpoints open. This got me to find this documentation page from Spring about endpoints, which suggests setting the endpoints.name.sensitive=false in application.properties, where name is the name of the end point being altered. But setting endpoints.api-url.sensitive=false in application.properties does not resolve the problem, and eclipse gives a warning that endpoints.api-url.sensitive=false is an unknown property. Do I have to define the property mapping somewhere else, or perhaps add the / to make it endpoints./api-url.sensitive=false? How can I get the correct name to use for the /api-url endpoint, and is this the correct approach to solving this problem?

7.) I read this other posting, and used its example to create a Filter Registration Bean inside the main Application class of the Spring Boot app, but the debug logs still show the same message indicating that the /api-url has an empty filter list. Here is the code that I added to the Application class:

@Bean
public FilterRegistrationBean shallowEtagHeaderFilter() {
    FilterRegistrationBean registration = new FilterRegistrationBean();
    registration.setFilter(new ShallowEtagHeaderFilter());
    registration.setDispatcherTypes(EnumSet.allOf(DispatcherType.class));
    registration.addUrlPatterns("/api-url");
    return registration;
}

The possible approaches from this research include:

1.) adding something to `application.properties`   
2.) adding `@Bean` annotation to inject a `ServletContextInitializer`   
3.) adding some Spring Security config using Java Configuration.   
4.) having Application.java extend SpringBootServletInitializer and   
        then overriding methods.  
5.) adding @Bean annotation to add a filter registration bean
like image 998
CodeMed Avatar asked Apr 07 '16 23:04

CodeMed


2 Answers

This is what i have where i restrict some URLs and some are public

 @Override
        public void configure(HttpSecurity http) throws Exception {
            http.csrf().disable()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests() 
                .antMatchers(actuatorEndpoints()).hasRole(userConfig.getAdminRole())
                .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
                .antMatchers("/signup",
                             "/payment/confirm",
                             "/api/address/zipcodes/**",
                             "/user/password/reset",
                             "/user/password/change",
                             "/user/email/verify",
                             "/password/update",
                             "/email/verify",
                             "/new-products/**").permitAll()
                .antMatchers("/api/**", "/files/**").authenticated();
        }
like image 78
Puran Avatar answered Oct 12 '22 18:10

Puran


I think what you have done is made the /error view a protected resource. Either open it up or stop using @EnableWebSecurity (it switches off some stuff that spring boot would have done for you otherwise).

like image 25
Dave Syer Avatar answered Oct 12 '22 17:10

Dave Syer