Тест интеграции 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 в пути к классам теста.

Другие вопросы по тегам