Tag Archives: Spring

Avoid unwanted component scanning of Spring Configuration

twitterrss

Facebooktwitterredditlinkedinmail

I came through interesting problem on Stack Overflow. Brett Ryan had problem that Spring Security configuration was initialized twice. When I was looking into his code I spot the problem. Let me show show the code.

He has pretty standard Spring application (not using Spring Boot). Uses more modern Java servlet Configuration based on Spring’s AbstractAnnotationConfigDispatcherServletInitializer.

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class AppInitializer extends
		AbstractAnnotationConfigDispatcherServletInitializer {


    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{SecurityConfig.class};
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{WebConfig.class};
    }

    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }

}

As you can see, there are two configuration classes:

  • SecurityConfig – holds Spring Security configuration
  • WebConfig – main Spring’s IoC container configuration
package net.lkrnac.blog.dontscanconfigurations;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity;

@Configuration
@EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        System.out.println("Spring Security init...");
        auth
                .inMemoryAuthentication()
                .withUser("user").password("password").roles("USER");
    }

}
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "net.lkrnac.blog.dontscanconfigurations")
public class WebConfig extends WebMvcConfigurerAdapter {

}

Pay attention to the component scanning in WebConfig. It is scanning package where all three classes are located. When you run this on servlet container, text “Spring Security init…” is written to console twice. It mean mean SecurityConfig configuration is loaded twice. It was loaded

  1. During initialization of servlet container in method AppInitializer.getRootConfigClasses()
  2. By component scan in class WebConfig

Why? I found this explanation in Spring’s documentation:

Remember that @Configuration classes are meta-annotated with @Component, so they are candidates for component-scanning!

So this is feature of Spring and therefore we want to avoid component scanning of Spring @Configuration used by Servlet configuration. Brett Ryan independently found this problem and showed his solution in mentioned Stack Overflow question:

@ComponentScan(basePackages = "com.acme.app",
               excludeFilters = {
                   @Filter(type = ASSIGNABLE_TYPE,
                           value = {
                               WebConfig.class,
                               SecurityConfig.class
                           })
               })

I don’t like this solution. Annotation is too verbose for me. Also some developer can create new @Configuration class and forget to include it into this filter. I would rather specify special package that would be excluded from Spring’s component scanning.

I created sample project on Github so that you can play with it.

 

twitterrss

Spring Security Misconfiguration

twitterrss

Facebooktwitterredditlinkedinmail

I recently saw Mike Wienser’s SpringOne2GX talk about Application Security Pitfalls. It is very informative and worth watching if you are using Spring’s stack on servlet container.

It reminded me one serious Spring Security Misconfiguration I was facing once. Going to explain it on Spring’s Guide Project called Securing a Web Application. This project uses Spring Boot, Spring Integration and Spring MVC.

Project uses these views:

@Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {
    
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/home").setViewName("home");
        registry.addViewController("/").setViewName("home");
        registry.addViewController("/hello").setViewName("hello");
        registry.addViewController("/login").setViewName("login");
    }

}

Where “/home”, “/” and “/login” URLs should be publicly accessible and “/hello” should be accessible only to authenticated user. Here is original Spring Security configuration from Guide:

@Configuration
@EnableWebMvcSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/", "/home").permitAll()
                .anyRequest().authenticated();
        http
            .formLogin()
                .loginPage("/login")
                .permitAll()
                .and()
            .logout()
                .permitAll();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .inMemoryAuthentication()
                .withUser("user").password("password").roles("USER");
    }
}

Nice and explanatory as all Spring’s Guides are. First “configure” method registers “/” and “home” as public and specifies that everything else should be authenticated. It also registers login URL. Second “configure” method specifies authentication method for role “USER”. Of course you don’t want to use it like this in production :).

Now I am going to slightly amend this code.

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //!!! Don't use this example !!!
        http
            .authorizeRequests()              
                .antMatchers("/hello").hasRole("USER");
        
        //... same as above ...
    }

Everything is public and private endpoints have to be listed. You can see that my amended code have the same behavior as original. In fact it saved one line of code.

But there is serious problem with this. What if my I need to introduce new private endpoint? Let’s say I am not aware of the fact that it needs to be registered in Spring Security configuration. My new endpoint would be public. Such misconfiguration is really hard to catch and can lead to unwanted exposure of URLs.

So conclusion is: Always authenticate all endpoints by default.

twitterrss

Load implementors of an interface into list with Spring

twitterrss

Facebooktwitterredditlinkedinmail

Last week I wrote a blog post how to load complete inheritance tree of Spring beans into list. Similar feature can be used for autowiring all implementors of certain interface.

Let’s have this structure of Spring beans. Notice that Bear is abstract class, therefore it’s not a Spring bean. So we have three beas: Wolf, PolarBear and Grizzly.

implementors

Now let’s load implementors into list with constructor injection:

@Service
public class Nature {
	List<Runner> runners;

	@Autowired
	public Nature(List<Runner> runners) {
		this.runners = runners;
	}

	public void showRunners() {
		runners.forEach(System.out::println);
	}
}

Method showRunners is using Java 8 forEach method that consumes method reference.  This construct outputs loaded beans into console. You would find a lot of reading about these new Java 8 features these days.

Spring context is loaded by this main class:

public class Main {
	public static void main(String[] args) {
		AnnotationConfigApplicationContext context =
				new AnnotationConfigApplicationContext(SpringContext.class);

		Nature nature = context.getBean(Nature.class);
		nature.showRunners();
	}
}

Console output:

PolarBear []
Wolf []
Grizzly []

This feature can be handy sometimes. Source code of this short example is on Github.

twitterrss

Load inheritance tree into List with Spring

twitterrss

Facebooktwitterredditlinkedinmail

I noticed interesting Spring feature. One of my colleagues used it for loading whole inheritance tree of Spring beans into list. Missed that when I was studying Spring docs.

Let’s have this inheritance tree of Spring beans:

animals-class-diagram

Not let’s load inheritance tree of beans into list with constructor injection:

@Component
public class Nature {
	List<Animal> animals;

	@Autowired
	public Nature(List<Animal> animals) {
		this.animals = animals;
	}

	public void showAnimals() {
		animals.forEach(animal -> System.out.println(animal));
	}
}

Method showAnimals is using Java 8 lambda expression to output loaded beans into console. You would find a lot of reading about this new Java 8 feature these days.

Spring context is loaded by this main class:

public class Main {
	public static void main(String[] args) {
		AnnotationConfigApplicationContext context =
				new AnnotationConfigApplicationContext(SpringContext.class);

		Nature nature = context.getBean(Nature.class);
		nature.showAnimals();
	}
}

Console output:

PolarBear []
Wolf []
Animal []
Grizzly []
Bear []

This feature can be handy sometimes. Source code of this short example is on Github.

twitterrss

Promoting constructor over field injection

twitterrss

Facebooktwitterredditlinkedinmail

I wrote blog post about testing field injection with Mockito (using @InjectMocks/@Mock/@Spy). It describes how to inject dependencies into testing object. But I didn’t pay attention to thinking about problems of field injection itself. Let me summarize few arguments against field injections that convinced me to treat it as bad practice:

  1. Field injection hides class dependencies. Constructor injection on the other hand exposes them. So it’s enough to look at class API.
  2. Constructor injection doesn’t allow creation of circular dependencies.
  3. Constructor injection uses standard Java features to inject dependencies. It is definitely much cleaner than field injection which involves using reflection twice under the hood:
    1. Spring must use reflection to inject private field
    2. Mockito (during the test) must use reflection to inject mocks into testing object
  4. Developer would need to create awful non-default constructor with a lot of parameters for tightly coupled class. Nobody likes huge amount of parameters. So constructor injection naturally forces him to think about decoupling and reducing dependencies for the class. This is biggest advantage of constructor injection for me.

So I am another member of Constructor injection camp now. This nice Petri Kainulainen’s blog post gathers more reading about pros and cons of both approaches.

twitterrss