Тест интеграции Spring Boot с Oauth с использованием JWT и PreAuthorized
В настоящее время у меня есть конфигурация безопасности, использующая Spring Security с oauth2 resourcesServer. С токеном JWT все работает нормально. Моя цепочка фильтров безопасности выглядит так:
httpSecurity.authorizeRequests()
.anyRequest().authenticated()
.and().cors()
.and().csrf()
.and().oauth2ResourceServer().jwt();
Теперь мне нужно представить этот пользовательский bean-компонент userDetailsService, чтобы использовать аннотацию preAuthorized с настраиваемыми ролями и привилегиями:
@Bean
public UserDetailsService userDetailsService(IIUserService iiUserService) {
return new CustomUserDetailsService(new IIUserServiceFake());
}
public class CustomUserDetailsService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) {
//here I need to go to another micro-service to retrive the user roles/privileges and build a UserDetails Object
}
Допустим, у меня есть эта конечная точка:
@GetMapping("/custom")
@PreAuthorize( "hasRole('ROLE_ADMIN')")
public String getData(){
return "I was able to see this endpoint";
}
И мой интеграционный тест выглядит так:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ActiveProfiles("test")
public class ControllerTest {
@LocalServerPort
private int serverPort;
@Autowired
private TestRestTemplate testRestTemplate;
@Test
public void entitlementTest() {
String uri = UriComponentsBuilder.fromHttpUrl("http://localhost").port(serverPort).path("/custom")
.build().toUriString();
ResponseEntity<String> forEntity = testRestTemplate.getForEntity(uri, String.class);
assertEquals(200, forEntity.getStatusCodeValue());
}
}
Но теперь я хочу иметь возможность вводить роли/привилегии с помощью пользовательских UserDetailsService. Пара вопросов здесь:1. Как мне имитировать интеграцию JWT resourcesServer, чтобы при включении безопасности во время теста запрос выглядел аутентифицированным.2.- Используя эту пользовательскую реализацию UserDetailsService, как мне сообщить Spring, какое поле следует использовать, потому что в моем случае у меня есть настраиваемое поле, исходящее из токена, которое не вызывает «имя пользователя», скажем, оно называется «custom_user_name».
По сути, я хочу иметь возможность протестировать свой контроллер, который использует аутентификацию токена JWT с аннотацией PreAuthorized, используя SpringBootTest.
Я уже посмотрел это , но до сих пор не нашел чистого способа сделать это,
Опять же, я не хочу менять способ обработки аутентификации (JWT), но у меня есть собственный способ определить, есть ли у пользователя роли в моей БД, и иметь возможность проверить это с помощью интеграционного теста.
Спасибо
1 ответ
Теперь мне нужно представить этот пользовательский bean-компонент userDetailsService, чтобы использовать аннотацию preAuthorized с настраиваемыми ролями и привилегиями.
Все, что вам нужно, это прочитать руководство иConverter<Jwt, AbstractAuthenticationToken>
bean (например, при правильной настройке или собственной реализации).
В ваших тестах, если вы используетеMockMvc
вместоTestRestTemplate
, то вы можете использоватьSecurityMockMvcRequestPostProcessors.jwt()
для настройки контекста безопасности для вас (без запуска и работы сервера авторизации). Вы также можете взглянуть на эту библиотеку, которую я написал , она содержит тестовые аннотации, похожие на@WithMockUser
, но для OAuth2. Пример интеграционного теста взят оттуда :
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
class SampleApiIntegrationTest {
@Autowired
MockMvc api;
@Test
@WithAnonymousUser
void givenRequestIsAnonymous_whenGetGreet_thenUnauthorized() throws Exception {
api.perform(get("/greet")).andExpect(status().isUnauthorized());
}
@Test
@WithJwt("ch4mp.json")
void givenUserIsCh4mp_whenGetGreet_thenOk() throws Exception {
api.perform(get("/greet")).andExpect(content().string("Hello ch4mp! You are granted with [USER_ROLES_EDITOR, ROLE_AUTHORIZED_PERSONNEL]."));
}
}
The @WithJwt
выше использует преобразователь аутентификации (реализацияConverter<Jwt, ? extends AbstractAuthenticationToken>
,JwtAuthenticationConverter
по умолчанию в Spring Boot) для сборкиAuthentication
в позиции и заполнить контекст безопасности теста, используя полезную нагрузку JSON в пути к классам теста.