java Spring安全- oauth2资源服务器测试

pftdvrlh  于 2023-02-02  发布在  Java
关注(0)|答案(2)|浏览(152)

我在使用@WebMvcTest和POST HTTP方法测试oauth2资源服务器时遇到了一些问题。
当我不发送csrf令牌时,我总是收到一个403状态码,即使当我使用不记名令牌时不需要该令牌。
下面是我想要测试的POST方法。

@PostMapping("/message")
public String createMessage(@RequestBody String message) {
    return String.format("Message was created. Content: %s", message);
}

下面是我的安全配置:

http.authorizeRequests(authorizeRequests -> authorizeRequests       
   .antMatchers("/message/**")
   .hasAuthority("SCOPE_message:read")
   .anyRequest().authenticated()
).oauth2ResourceServer(oauth2ResourceServer ->               
    oauth2ResourceServer
    .jwt(withDefaults())
);

我正在遵循spring-security示例中提供的测试。
以下测试本应通过,但由于请求中未发送csrf令牌,因此测试失败。

mockMvc.perform(post("/message").content("Hello message")
    .with(jwt(jwt -> jwt.claim("scope", "message:read")))
    .andExpect(status().isOk())
    .andExpect(content().string(is("Message was created. Content: Hello message")));

当我将csrf令牌添加到请求中时,测试通过:

mockMvc.perform(post("/message").content("Hello message")
    .with(jwt(jwt -> jwt.claim("scope", "message:read")))
    .with(csrf()))
    .andExpect(status().isOk())
    .andExpect(content().string(is("Message was created. Content: Hello message")));

当我运行应用程序时,不需要在POST请求中发送csrf令牌。
我已经派生了Spring Security GitHub存储库,这个测试失败的项目可以在link上找到。
有没有办法配置我的测试,这样我就不需要在POST请求中发送csrf令牌了?

jm2pwxwz

jm2pwxwz1#

为了让CSRF过滤器检测到您正在使用JWT令牌,您需要将JWT令牌作为Authorization头或请求参数包含在请求中。
您提到的测试有一个mock JwtDecoder,这意味着您可以使用任何字符串作为令牌并模拟解码后的值。
您的测试将变为:

Jwt jwt = Jwt.withTokenValue("token")
        .header("alg", "none")
        .claim("scope", "message:read")
        .build();
when(jwtDecoder.decode(anyString())).thenReturn(jwt);
mockMvc.perform(post("/message")
        .content("Hello message")
        .header("Authorization", "Bearer " + jwt.getTokenValue()))
        .andExpect(status().isOk())
        .andExpect(content().string(is("Message was created. Content: Hello message")));

如果您没有模拟JwtDecoder,那么您需要检索一个有效的承载令牌,并将其传递到Authorization报头中。

o75abkj4

o75abkj42#

首先,使用Bearer访问令牌,您可以禁用会话(STATELESS会话管理),从而禁用CSRF保护(CSRF攻击向量是会话)。
其次,有一个.csrf() MockMvc请求后处理器,如果您希望保留转让(和CSRF保护),它将模拟CSRF令牌。
最后,jwt()请求后处理器所做的是使用JwtAuthenticationToken示例直接配置安全上下文,而不是创建一个有效的JWT令牌集作为Bearer access-token。使用MockMvc,Authorization头不会解码,也不会转换为Authentication示例。=〉在执行MockMvc请求之前,您应该设置权限,而不是范围声明,以使测试通过:

.with(jwt(jwt -> jwt.authorities(List.of(new SimpleGrantedAuthority("SCOPE_message:read")))))

请注意,您也可以简单地用以下内容来修饰您的测试函数:

@WithMockJwtAuth("SCOPE_message:read")

this lib我维护

相关问题