spring 使用Mock JWT令牌测试JWT身份验证

bqf10yzr  于 2023-09-29  发布在  Spring
关注(0)|答案(1)|浏览(209)

我正在编写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));
}

这是我的SecurityConfig:

@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.使用此令牌是否存在任何安全问题?
4.是否有任何过滤器可以插入FilterChain中?
有人能回答我的问题,消除我的疑虑吗?
谢谢.

zsbz8rwp

zsbz8rwp1#

MockMvc测试DSL(特定于域的语言)中的jwt()方法用于在测试中模拟JWT身份验证。下面我们来一一解答您的疑问:
1.为什么我的端点可以使用此令牌访问?为什么我的资源服务器接受这个令牌?
当您在MockMvc测试的上下文中使用jwt().authorities(new SimpleGrantedAuthority("SCOPE_data.write"))时,您实际上是创建了一个模拟(模拟)的JWT身份验证来进行测试。它绕过了正常的JWT处理和验证(签名、过期、颁发者等),直接模拟使用具有给定权限的JWT进行身份验证的用户。只是为了测试在实际场景中,实际的JWT将根据资源服务器的配置进行处理和验证。
1.使用此令牌,任何用户都可以访问我的端点并因此访问数据库中的数据吗?
不可以,真实的用户不能使用“alg:在生产环境中使用“none”令牌来访问端点。这是一种只在MockMvc框架范围内有效的测试机制。在生产中,令牌将被拒绝,因为它是未签名的。值得注意的是,在真实的的JWT处理中允许“none”作为算法是一种安全风险,但这不是这里发生的事情。这仅适用于测试场景。
1.使用此令牌是否存在任何安全问题?
只要这个模拟的JWT身份验证严格地在测试环境的范围内使用,而不是在生产环境中使用,就不应该有安全问题。这是Spring Security提供的用于测试目的的实用程序。你基本上是在说,“让我们假设我们有一个有效的JWT与这些权威,看看系统的行为。”
但是,一些最佳实践和附加说明:

  • 确保在生产JWT处理中不使用“none”算法或类似的不安全配置。
  • 始终将测试配置与生产配置分开,以避免潜在的安全隐患。
  • 定期检查和更新安全配置和依赖项,以使用安全最佳实践和修补程序保持最新状态。

最后,当您的测试正在检查status().isOk时,实际端点在保存一本书时返回HttpStatus.CREATED(201)。您可能希望更新测试以检查status().isCreated()而不是isOk(),从而更准确地反映预期行为。

相关问题