Мой сервер авторизации представляет собой автономный экземпляр keycloak, который я предпочитаю протестировать, чем получить доступ к реальному. Теперь я определил свой фильтр безопасности следующим образом:
@Bean
public SecurityFilterChain securityFilterChain (HttpSecurity http) throws Exception{
http.csrf(AbstractHttpConfigurer::disable);
http.authorizeHttpRequests(requests -> requests
.anyRequest().hasRole("USER")
);
http.oauth2ResourceServer(oauth2 -> {
oauth2.jwt(jwt -> jwt.jwtAuthenticationConverter(jwtAuthConverter));
oauth2.authenticationEntryPoint(unauthorizedHandler);
}
);
// http.addFilterAfter()
http.exceptionHandling(exception -> {
exception.accessDeniedHandler(accessDeniedHandler);
});
return http.build();
}
Теперь я высмеивал авторизацию JWT следующим образом:
@Bean
public SecurityMockMvcRequestPostProcessors.JwtRequestPostProcessor jwtRequestPostProcessor() {
SecurityMockMvcRequestPostProcessors.JwtRequestPostProcessor data = jwt().jwt(builder -> {
builder.issuer("http://auth.localhost/realms/CompetitionManager");
builder.claim("azp", "competition-manager-web");
builder.claim("preferred_username", "testUser");
builder.claim("email", "[email protected]");
builder.claim("resource_access", Map.of("competition-manager-web", Map.of("roles", List.of("USER"))));
});
return data;
}
Предположительно, отсутствуют ключи, но, согласно документации, это будет обработано системой безопасности Spring. А тест выглядит так:
@SpringJUnitConfig(classes = {JwtTestConfig.class})
public class ContestControllerTest {
/* Autowiring JPA repositories & interfaces */
@Autowired
private SecurityMockMvcRequestPostProcessors.JwtRequestPostProcessor defaultJwt;
@Test
@Order(2)
public void getListOfContests_then200() throws Exception {
mockMvc.perform(get("/contests/list").with(defaultJwt))
.andDo(print())
.andExpect(status().isOk())
.andExpect(jsonPath("$").isArray())
.andExpect(jsonPath("$", hasSize(2)))
.andExpect(jsonPath("$[*]", containsInAnyOrder("visible test contest 1", "visible test contest 2")));
}
Однако, как указано в документации, это не проходит. Токен передан правильно, это точно, так как я получаю 403, а не 401, а в других тестовых случаях доступ к preferred_username осуществляется и используется, но он не проходит через фильтры авторизации, и я получаю только короткое сообщение «Доступ запрещен». без каких-либо подробностей.
Я что-то упустил в определении токена?




При использовании SecurityMockMvcRequestPostProcessors ваш jwtAuthConverter bean-компонент не используется. Постпроцессор сам строит JwtAuthenticationToken.
Два варианта:
@WhithJwt или @WithMockJwtAuth из Spring-addons-oauth2-test . Оба будут использовать ваш jwtAuthConverter, если он представлен как @Bean. Использование в репозитории проекта Github или в этой статье BaeldungЯ написал все это (включая SecurityMockMvcRequestPostProcessors для OAuth2 в spring-security-test).