Spring 安全 - oauth2 资源服务器测试
Spring security - oauth2 resource server tests
我在使用@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令牌。
我已经 fork 了 Spring 安全 GitHub 存储库,这个测试失败的项目可以在 link.
有没有办法让我配置我的测试,这样我就不需要在 POST 请求中发送 csrf 令牌?
为了让 CSRF 过滤器检测到您使用的是 JWT 令牌,您需要将 JWT 令牌作为 Authorization
header 或请求参数包含在您的请求中.
您提到的测试有一个模拟 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
header.
我在使用@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令牌。
我已经 fork 了 Spring 安全 GitHub 存储库,这个测试失败的项目可以在 link.
有没有办法让我配置我的测试,这样我就不需要在 POST 请求中发送 csrf 令牌?
为了让 CSRF 过滤器检测到您使用的是 JWT 令牌,您需要将 JWT 令牌作为 Authorization
header 或请求参数包含在您的请求中.
您提到的测试有一个模拟 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
header.