401(未经授权)JUnit 测试

问题描述 投票:0回答:1

我有以下 Spring Security 6 配置:

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {

    httpSecurity
            .authorizeHttpRequests(registry -> registry
                    .requestMatchers("/admin/**").hasRole("ADMIN")
                    .requestMatchers("/public/**").permitAll()
                    .anyRequest().authenticated()
            )
            .oauth2ResourceServer(oauth2Configurer -> oauth2Configurer.jwt(jwtConfigurer -> jwtConfigurer.jwtAuthenticationConverter(jwt -> {
                Map<String, Collection<String>> realmAccess = jwt.getClaim("realm_access");
                Collection<String> roles = realmAccess.get("roles");
                var grantedAuthorities = roles.stream()
                        .map(role -> new SimpleGrantedAuthority(role))
                        .collect(Collectors.toList());
                return new JwtAuthenticationToken(jwt, grantedAuthorities);
            })));
    httpSecurity.sessionManagement(sess -> sess.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
    httpSecurity.csrf(CsrfConfigurer::disable);

    // Disable anonymous
    httpSecurity.anonymous(AnonymousConfigurer::disable);

    return httpSecurity.build();
}

无需授权即可使用的公共端点:

@RestController
@RequestMapping(value = "/uaa/")
public class ApikeyAuthController {

......
    @PostMapping(value = "/public", produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<?> apiKey(@RequestBody MultiValueMap<String, String> requestBody)
    {
        .......
        return new ResponseEntity<>(HttpStatus.OK);
    }

}

JUnit 测试:

@AutoConfigureMockMvc
@ContextConfiguration(classes = {ApikeyAuthController.class})
@WebMvcTest
public class ApikeyAuthControllerTest {

    @MockBean
    private ApiKeyService service;

    @MockBean
    private TokenService tokenService;

    @MockBean
    private ApiKeyAuthValidator apiKeyAuthValidator;

    @Autowired
    private MockMvc mockMvc;

    @Autowired
    private WebApplicationContext webApplicationContext;

    @BeforeEach
    public void setUp() {
        mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
    }

    @Test
    public void apiKeyTest() throws Exception
    {
        when(service.getSummary(any(), any())).thenReturn(Optional.of(List.of(SummaryDTO.builder()
                .date(LocalDateTime.of(2021, Month.MAY, 1, 12, 13))
                .enabled(12)
                .disabled(5)
                .build())));

        MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<>();
        requestBody.add("key", "password");

        this.mockMvc.perform(MockMvcRequestBuilders
                        .post("/public")
                        .contentType(MediaType.APPLICATION_FORM_URLENCODED_VALUE)
                        .content(requestBody.toString()))
                .andExpect(MockMvcResultMatchers.status().isOk());
    }
}

我总是收到 http 代码 401(未经授权)。 您知道如何配置 /public 端点以在未经授权的情况下接受上述端点的请求吗?

spring-boot spring-security junit5 spring-boot-test
1个回答
0
投票

有多种方法可以选择模拟安全功能,例如使用

SecurityMockMvcRequestPostProcessors
中的
spring-security-test
,或如所描述的
@WithMockUser
,例如在文档中这里

我个人更喜欢嘲笑

SecurityFilterChain
bean:

@WebMvcTest(ApikeyAuthController.class)
@MockBean(SecurityFilterChain.class)
class ApikeyAuthControllerTest {

   @Autowired
   private MockMvc mockMvc;
}

顺便说一下:

  1. 不要使用
    @ContextConfiguration
    来指定被测试的控制器,在@WebMvcTest注释中设置它。
  2. 除了上面的
    mockMvc
    注释之外,您不需要初始化
    @Autowired
    ,因此您可以删除
    @BeforeEach
    方法。
© www.soinside.com 2019 - 2024. All rights reserved.