簡體   English   中英

在 Spring 引導中與 OAuth2 一起使用時無法模擬 @PreAuthorize

[英]Cannot mock @PreAuthorize when using with OAuth2 in Spring Boot

我正在嘗試為我的所有服務類編寫單元測試,但我找不到關於如何在我的 controller 方法之上模擬@PreAuthorize的解決方案。 舉個例子:

我在 controller 中有這個 function:

@GetMapping("/users")
@PreAuthorize("hasAuthority('ADMIN')")
public ResponseEntity<List<User>> getUsers() {
    return service.getUsers();
}

這在我的服務 class 中:

public ResponseEntity<List<User>> getUsers() {
    return new ResponseEntity<>(userRepository.findAll(), HttpStatus.OK);
}

網絡安全 class:

protected void configure(HttpSecurity http) throws Exception {
    http = http.cors().and().csrf().disable();
    http = http
            .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and();
    http = http
            .exceptionHandling()
            .authenticationEntryPoint(
                    (request, response, ex) -> response.sendError(
                            HttpServletResponse.SC_UNAUTHORIZED,
                            ex.getMessage()
                    )
            )
            .and();

    http.authorizeRequests()
            .antMatchers(HttpMethod.GET, "/").permitAll()
            .anyRequest().authenticated();

    http.oauth2ResourceServer().jwt().jwtAuthenticationConverter(jwtAuthenticationConverter());
}

public JwtAuthenticationConverter jwtAuthenticationConverter() {
    JwtAuthenticationConverter converter = new JwtAuthenticationConverter();

    converter.setJwtGrantedAuthoritiesConverter(jwt ->
            Optional.ofNullable(jwt.getClaimAsStringList("permissions"))
                    .stream()
                    .flatMap(Collection::stream)
                    .map(SimpleGrantedAuthority::new)
                    .collect(Collectors.toList())
    );

    return converter;
}

現在我正在嘗試編寫一個單元測試:

@Test
public void getAllUsers_shouldBeSuccess() throws Exception {
    ArrayList<User> users = new ArrayList<>();
    users.add(new User("0", true, new Role("USER")));

    when(userService.getUsers()).thenReturn(new ResponseEntity<>(users, HttpStatus.OK));

    mvc.perform(get("/users").with(jwt().jwt(jwt -> jwt.claim("permissions", "[ADMIN]"))))
            .andExpect(status().isOk())
            .andExpect(content().json(String.valueOf(users)));
}

但我收到一個錯誤:

java.lang.NoClassDefFoundError: `org/springframework/security/web/context/SecurityContextHolderFilter`

遺憾的是,spring-security 團隊選擇僅在測試框架中包含 MockMvc 請求后處理器和 WebTestClient 請求突變器,這限制了 OAuth2 身份驗證 mocking 僅在控制器單元測試中。

希望我將測試注釋的工作保留在我在 maven-central 上發布的一組庫中: https://github.com/ch4mpy/spring-addons 您可以使用它測試任何@Component (示例取自此處):

@Import(MessageServiceTests.TestConfig.class)
@ExtendWith(SpringExtension.class)
class MessageServiceTests {

    @Autowired
    private MessageService messageService;

    @Test()
    void greetWitoutAuthentication() {
        assertThrows(Exception.class, () -> messageService.getSecret());
    }

    @Test
    @WithMockJwtAuth(authorities = "ROLE_AUTHORIZED_PERSONNEL", claims = @OpenIdClaims(preferredUsername = "ch4mpy"))
    void greetWithMockJwtAuth() {
        final JwtAuthenticationToken auth = (JwtAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();

        assertThat(messageService.greet(auth)).isEqualTo("Hello ch4mpy! You are granted with [ROLE_AUTHORIZED_PERSONNEL].");
    }

    @TestConfiguration(proxyBeanMethods = false)
    @EnableGlobalMethodSecurity(prePostEnabled = true)
    @Import({ MessageService.class })
    static class TestConfig {
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM