没有 csrf 或无效 csrf 的 mockmvc 发布请求没有失败
Posted
技术标签:
【中文标题】没有 csrf 或无效 csrf 的 mockmvc 发布请求没有失败【英文标题】:mockmvc post request without csrf or invalid csrf is not failing 【发布时间】:2021-09-05 22:57:39 【问题描述】:我有一个带有 spring security 5 的 spring boot-2.5.1 应用程序。
WebSecurityConfig 如下所示:
@Slf4j
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class WebSecurityConfig extends WebSecurityConfigurerAdapter
private final CustomProperties customProperties;
@Override
protected void configure(HttpSecurity http) throws Exception
if (customProperties.isEnabled())
log.info("authentication enabled.");
http.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.oauth2Login()
.redirectionEndpoint()
.baseUri(customProperties.getAuthorizationResponseUri())
.and()
.userInfoEndpoint(userInfo -> userInfo.userService(new CustomOAuth2UserService()::loadUser));
else
log.info("authentication disabled.");
http.authorizeRequests()
.anyRequest()
.permitAll();
public void configure(WebSecurity webSecurity)
webSecurity.ignoring()
.antMatchers("/actuator/info", "/actuator/health/*");
控制器如下所示:
@Controller
@RequiredArgsConstructor
public class UserController
private final UserService userService;
@PostMapping("/users")
public @ResponseBody Mono<Map<String, String>> saveUsers(@RequestBody List<UserDto> userDtos)
return userService.saveUser(userDtos);
上述控制器对应的JUnit:
@AutoConfigureMockMvc
@WebMvcTest(UserController.class)
class UserControllerTest
@Autowired
private MockMvc mockMvc;
@MockBean
private UserService userService;
@SneakyThrows
@Test
@WithMockTestUser
void shouldSaveUsers()
var userDtos = "...";
mockMvc.perform(post("/users")
.contentType(APPLICATION_JSON)
.content(userDtos))
.andDo(print())
.andExpect(status().isOk());
JUnit 没有 CSRF 的状态为 OK 而不是禁止的请求。 如果我调试,我可以看到,如果 csrf() 不包括在内,则不会生成令牌并分配给请求。但是,请求仍然通过。理想情况下,它应该抛出禁止的请求访问。
即使使用 csrf(),我也可以看到生成令牌并分配给参数。
在这两种情况下,我都没有看到任何地方正在验证 POST 请求是否包含 mockmvc 令牌。
mockmvc 是否需要任何额外的配置来验证 POST 请求是否包含 CSRF?
【问题讨论】:
【参考方案1】:您需要使用SecurityMockMvcConfigurers.springSecurity()
构建MockMvc
,而不是自动配置MockMvc
。
这会将名为“springSecurityFilterChain”的 Spring Bean 添加为过滤器,并确保每个请求都使用 TestSecurityContextHolder
。
@Autowired
private WebApplicationContext context;
private MockMvc mockMvc;
@Before
public void setup()
this.mockMvc = MockMvcBuilders
.webAppContextSetup(this.context)
.apply(springSecurity())
.build();
【讨论】:
我尝试了建议的方法。但是,如果添加或不添加 csrf,仍然不会调用 CsrfFilter。但是,我可以看到即使添加或不添加 csrf,仍然会调用 CsrfConfigurer。因此,post 请求仍然是成功的,而不是禁止访问 @user2800089WithMockTestUser
看起来像什么?如果你使用内置的@WithMockUser
,你会得到同样的结果吗?
@WithMockTestUser 是具有安全上下文 WithMockTestUserSecurityContextFactory 的注释。我对此进行了自定义,因为身份提供者不会将主体信息作为默认 oauth2 用户返回,因此我自定义了 userinfo,这就是自定义模拟 userinfo 的原因以上是关于没有 csrf 或无效 csrf 的 mockmvc 发布请求没有失败的主要内容,如果未能解决你的问题,请参考以下文章
在 Broadleaf 项目中 HTTP 状态 403 - 在请求参数“_csrf”或标头“X-CSRF-TOKEN”上发现无效的 CSRF 令牌“null”