使用模拟 JWT 令牌测试 JWT 身份验证

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

我正在编写 jUnit 测试来测试我的资源服务器的端点。
现在,这些端点通过 @PreAuthorized (和类似的)注释进行保护,如下所示:

@PreAuthorize("hasAuthority('SCOPE_data.write')")
@PostMapping("/save")
public ResponseEntity<Book> saveBook(
        @io.swagger.v3.oas.annotations.parameters.RequestBody(
                description = "Save book",
                required = true,
                content = @Content(schema = @Schema(implementation = Book.class))) 
        @Valid @org.springframework.web.bind.annotation.RequestBody Book book){
    try {
        Book _book = bookRepo.save(new Book(book.getID(), vehicle.getTitle(), vehicle.getAuthor()));
        return new ResponseEntity<>(_book, HttpStatus.CREATED);
    }catch (Exception e) {
        return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

我的单元测试将是这样的:

@Test
public void testSaveBook() throws Exception {
        
    this.mockMvc.perform(
            post("/book/save")
                .contentType(MediaType.APPLICATION_JSON)
                .content(bookToSave))
        .with(jwt().authorities(new SimpleGrantedAuthority("SCOPE_data.write")))
        .andDo(print())
        .andExpect(status().isOk));
}

这是我的安全配置:

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http
        .authorizeHttpRequests(exchanges -> exchanges
            .antMatchers("/v3/api-docs/**", "/swagger-ui/**", "/swagger-ui.html").permitAll()
            .anyRequest().authenticated())
        .csrf().disable()
        .oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults()));
    return http.build();
} 

我担心的是 jwt() 指令。就像官方文档中所写的那样,该指令将创建一个带有 "headers" : { "alg" : "none" } 的 jwt 令牌

我的问题如下:
1. 为什么我的端点可以使用此令牌访问?为什么我的资源服务器接受这个令牌?
2. 使用此令牌,任何用户都可以访问我的端点,从而可以访问数据库内的数据?
3、该Token的使用是否存在安全问题?
4. FilterChain 中是否需要插入任何过滤器?

有人可以回答我的问题并消除我的疑虑吗?
谢谢。
spring spring-boot spring-security junit5
1个回答
-1
投票

jwt()
测试DSL(域特定语言)中的
MockMvc
方法用于在测试中模拟JWT身份验证。让我们一一回答您的问题:

  1. 为什么我的端点可以使用此令牌访问?为什么我的资源服务器接受这个令牌?

    当您在

    jwt().authorities(new SimpleGrantedAuthority("SCOPE_data.write"))
    测试上下文中使用
    MockMvc
    时,您实际上是在创建一个模拟(模拟)JWT 身份验证以进行测试。它绕过正常的 JWT 处理和验证(签名、过期、颁发者等),并直接模拟使用具有给定权限的 JWT 进行身份验证的用户。这只是为了测试;在现实场景中,实际的 JWT 将根据您的资源服务器的配置进行处理和验证。

  2. 有了这个令牌,任何用户都可以访问我的端点,从而访问数据库内的数据吗?

    不可以,真实用户无法在生产环境中使用“alg: none”令牌来访问您的端点。这是一种仅在

    MockMvc
    框架范围内有效的测试机制。在生产中,令牌将被拒绝,因为它未签名。值得注意的是,在真正的 JWT 处理中允许“none”作为算法存在安全风险,但这并不是这里发生的情况。这仅适用于测试场景。

  3. 该代币的使用是否存在安全问题?

    只要这个模拟的 JWT 身份验证严格在测试环境范围内使用,而不是在生产中使用,就不应该有安全问题。这是 Spring Security 提供的用于测试目的的实用程序。你本质上是在说,“让我们假设我们与这些机构有一个有效的 JWT,然后看看系统的行为如何。”

但是,一些最佳实践和附加说明:

  • 确保您在生产 JWT 处理中不使用“无”算法或类似的不安全配置。
  • 始终将测试配置与生产配置分开,以避免潜在的安全陷阱。
  • 定期检查和更新您的安全配置和依赖项,以随时了解安全最佳实践和补丁。

最后,当您的测试检查

status().isOk
时,实际端点会在保存书籍时返回
HttpStatus.CREATED
(201)。您可能需要更新测试以检查
status().isCreated()
而不是
isOk()
,以更准确地反映预期行为。

© www.soinside.com 2019 - 2024. All rights reserved.