Конфигурация Sping Boot DefaultSecurityFilterChain отличается в тестовой версии от рабочей - PullRequest
0 голосов
/ 30 марта 2020

Мы бы хотели защитить конечную точку HTTP metrics, которая является встроенной конечной точкой Spring Boot. Поэтому мы пишем собственный WebSecurityConfigurerAdapter, см. Ниже

    @Configuration
    @Order(95)
    public class MetricsWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {

        @Value("${metrics.username}")
        private String metricsUsername;

        @Value("${metrics.password}")
        private String metricsPassword;

        @Autowired
        private MyAuthenticationEntryPoint authenticationEntryPoint;

        @Autowired
        public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
            auth.inMemoryAuthentication()
              .withUser(metricsUsername).password("{noop}" + metricsPassword)
              .roles("METRICS");
        }

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.csrf().disable(); // disable csrf for our requests.
            http
                .antMatcher("/metrics") //
                .httpBasic()    //
                .authenticationEntryPoint(authenticationEntryPoint) //
                .and()  //
                .authorizeRequests()    //
                .antMatchers("/metrics").authenticated();   //
        }

    }   

Мой тест Spring Boot для проверки подлинности:

@ExtendWith(SpringExtension.class)
@SpringBootTest
@TestPropertySource(locations = "classpath:test.properties")
@AutoConfigureMockMvc
public class MetricsEndpointTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void testGetMetricsForbidden() throws Exception {
        mockMvc.perform(get("/metrics"))
                .andExpect(status().isForbidden());
    }

    @Test
    public void testGetMetrics() throws Exception {
        mockMvc.perform(get("/metrics")
                .header("Authorization", "Basic " + getBasicAuthentication("testmetricsuser", "testmetricspass")))
                .andExpect(status().isOk());
    }

    private static String getBasicAuthentication(String user, String password) {
        String token = user + ":" + password;
        try {
            return DatatypeConverter.printBase64Binary(token.getBytes("UTF-8"));
        } catch (UnsupportedEncodingException ex) {
            throw new IllegalStateException("Cannot encode with UTF-8", ex);
        }
    }

}

Проверка testGetMetricsForbidden не проходит. Когда я отлаживал класс WebSecurity во время тестового прогона и в процессе производства, я обнаружил следующую разницу в переменной securityFilterChains:

В процессе производства: enter image description here В тесте: enter image description here

Разница в том, что в производстве мы имеем пять цепочек фильтров безопасности и в тесте шесть цепочек фильтров безопасности. Шестая цепочка фильтров отвечает за то, что тест не пройден, поскольку сначала он совпадает. Я думаю, что @Order является причиной заказа в тесте. У меня вопрос, как я могу отключить этот шестой фильтр в моем тесте.

...