In my project (Spring Boot + Security + Thymeleaf) I wanted to configure custom web security as is described in "getting started" article on the Spring's official web. I've followed steps in the article and created my custom configuration. But I forgot to add a
@EnableWebSecurity annotation. Everything seemed to work fine. Except for Thymeleaf's
By not specifying
@EnableWebSecurity annotation I didn't disable Spring Boot's default security auto-configuration in
SpringBootWebSecurityConfiguration.ApplicationWebSecurityConfigurerAdapter. This creates a security configuration (
HttpSecurity object) that disables all access to application for unauthorised users, except for some static resources, and creates a user with a role
ROLE_USER and generates some random password for testing purposes.
My configuration also created
HttpSecurity object with my own security configuration and my own user repository.
HttpSecurity configurations has been passed to
WebSecurity which is responsible for creating Spring Security Filter Chain. As you may know a security request goes through this chain until one of the filters "catches" it and process it.
Because my custom configuration bean had a higher priority, it was located "on a higher place" in security filter chain. So all requests has been caught and processed by my filter and not by the filter created by Spring Boot auto-configuration. So far so good.
Problem with two HttpSecurity configurations
When configured, the
WebSecurity object holds an instance of
FilterSecurityInterceptor. There is only one field that can hold the interceptor so no more than one interceptor can be held by
FilterSecurityInterceptor is the crucial part of the Spring Security project. Actually it is its parent class
AbstractSecurityInterceptor and its implementations that makes Spring Security breath.
ServletRequests and decides whether a current user has permission to proceed or not. The
FilterSecurityInterceptoruses a help of other classes like
SecurityContextHolder(holds information about current user, his security context),
AccessDecisionManager(evaluates a request against a current security context) and so on.
MethodSecurityInterceptorintercepts method calls similarly to
FilterSecurityInterceptor. Uses Spring's proxies.
MethodSecurityInterceptorwith support of
FilterSecurityInterceptor is based on information in
WebSecurityConfigurerAdapter.init method, the Spring populates
WebSecurity by the
FilterSecurityInterceptor instance. If more than one
FilterSecurityInterceptor are created later overwrites interceptor that is already present in
Thymeleaf-Spring Security integration gets the
WebSecurity and uses it to evaluate value of
sec:authorize-url attribute. Obviously, in this case it gets Spring Boot's default configuration which is not what I wanted.
So, don't forget to disable default configuration by adding
@EnableWebSecurity annotation to your security configuration class.