【问题标题】:mockmvc post request without csrf or invalid csrf is not failing没有 csrf 或无效 csrf 的 mockmvc 发布请求没有失败
【发布时间】:2021-09-05 22:57:39
【问题描述】:

我有一个带有 spring security 5spring 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

【问题讨论】:

    标签: spring-boot spring-security csrf spring-test mockmvc


    【解决方案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 请求仍然是成功的,而不是禁止访问
    • @user2800089 WithMockTestUser 看起来像什么?如果你使用内置的@WithMockUser,你会得到同样的结果吗?
    • @WithMockTestUser 是具有安全上下文 WithMockTestUserSecurityContextFactory 的注释。我对此进行了自定义,因为身份提供者不会将主体信息作为默认 oauth2 用户返回,因此我自定义了 userinfo,这就是自定义模拟 userinfo 的原因
    猜你喜欢
    • 2017-08-12
    • 1970-01-01
    • 2021-11-25
    • 1970-01-01
    • 2017-07-10
    • 2014-08-17
    • 2020-12-02
    • 2015-04-29
    • 2011-09-21
    相关资源
    最近更新 更多