Мы бы хотели защитить конечную точку 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
:
В процессе производства: В тесте:
Разница в том, что в производстве мы имеем пять цепочек фильтров безопасности и в тесте шесть цепочек фильтров безопасности. Шестая цепочка фильтров отвечает за то, что тест не пройден, поскольку сначала он совпадает. Я думаю, что @Order
является причиной заказа в тесте. У меня вопрос, как я могу отключить этот шестой фильтр в моем тесте.