I have a Spring Boot + Spring Security application that has severalantMatchers
paths; some fullyAuthenticated()
, some permitAll()
.
How to I write a test that verifies SecurityConfiguration
has my endpoints under /api/**
(and ultimately others) secured correctly?
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
//...
.antMatchers("/api/**").fullyAuthenticated()
}
}
Using spring-boot-1.5.2.RELEASE
, spring-security-core-4.2.2-release
.
Clarification1: I want to as-directly-as-possible test the SecurityConfiguration
, as opposed to transitively testing via one of the /api/**
endpoints, which may have their own @PreAuthorize
security.
Clarification2: I would like something similar to this WebSecurityConfigurerAdapterTests.
Clarification3: I would like to @Autowire
something at the Spring Security layer, ideally HttpSecurity
, to test.
The type WebSecurityConfigurerAdapter is deprecatedWell, it's because the developers of Spring framework encourage users to move towards a component-based security configuration.
So you want to ensure that if someone changes .antMatchers("/api/**")
to .antMatchers("/WRONG_PATH/**")
then you have a test that will figure it out ?
The rules you define using HttpSecurity
will end up configuring a FilterChainProxy
with one or more SecurityFilterChain
, each with a list of filters. Each filter, such as UsernamePasswordAuthenticationFilter
(used for form-based login), will have a RequestMatcher
defined in the super class AbstractAuthenticationProcessingFilter
. The problem is that RequestMatcher
is an interface which currently have 12 different implementations, and this includes AndRequestMatcher
and OrRequestMatcher
, so the matching logic is not always simple. And most importantly RequestMatcher
only has one method boolean matches(HttpServletRequest request)
, and the implementation often does not expose the configuration, so you will have to use reflection to access the private configurations of each RequestMatcher
implementation (which could change in the future).
If you go down this path, and autowire FilterChainProxy
into a test and use reflection to reverse-engineer the configuration, you have to consider all the implementation dependencies you have. For instance WebSecurityConfigurerAdapter
has a default list of filters, which may change between releases, and unless disable it, and when it is disabled you have to define every filter explicitly. In addition new filters and RequestMatchers
could be added over time, or the filter chain generated by HttpSecurity
in one version of Spring Security may be slightly different in the next version (maybe not likely, but still possible).
Writing a generic test for your spring security configuration, is technically possible, but it is not exactly an easy thing to do, and the Spring Security filters certainly were not designed to support this. I have worked extensively with Spring Security since 2010, and I have never had the need for such a test, and personally I think it would be a waste of time trying to implement it. I think the time will be much better spent writing a test framework that makes it easy to write integration tests, which will implicitly test the security layer as well as the business logic.
I see below test case can help you achieve what you want. It is an Integration Test to test the Web Security configuration and we have similar testing done for all our code that is TDD driven.
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
@WebAppConfiguration
public class WebConfigIT {
private MockMvc mockMvc;
@Autowired
private WebApplicationContext webApplicationContext;
@Autowired
private FilterChainProxy springSecurityFilterChain;
@Before
public void setup() throws Exception {
mockMvc = webAppContextSetup(webApplicationContext)
.addFilter(springSecurityFilterChain)
.build();
}
@Test
public void testAuthenticationAtAPIURI() throws Exception {
mockMvc.perform(get("/api/xyz"))
.andExpect(status.is3xxRedirection());
}
This though looks like doing an explicit testing of the end-point (which is anyways a testing one have to do if doing TDD) but this is also bringing the Spring Security Filter Chain in context to enable you test the Security Context for the APP.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With