首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >执行request后,MockMvc似乎已清除SecurityContext (java.lang.IllegalArgumentException:鉴权对象不能为空)

执行request后,MockMvc似乎已清除SecurityContext (java.lang.IllegalArgumentException:鉴权对象不能为空)
EN

Stack Overflow用户
提问于 2018-08-01 05:25:06
回答 2查看 1.6K关注 0票数 4

我正在尝试使用SpringBoot + Spring Data Mongo + SpringMVC运行一些集成测试

我已经简化和泛化了代码,但它应该能够通过下面的测试重现该行为。

正如您在BookRepository界面中看到的那样,我希望用户只能检索他拥有的图书(@Query("{ 'ownerName' : '?#{principal?.username})),并且我正在编写一个测试来执行POST来保存图书,然后验证图书的所有者设置是否正确。

为了解决这里的问题,我将测试简化为只使用GET,然后调用findAll()

问题

执行任何MockMvc请求后,使用ThreadLocalSecurityContextHolderStrategy#clearContext()清除SecurityContext,这会导致在我尝试调用repository.findAll();时抛出以下异常

java.lang.IllegalArgumentException: Authentication object cannot be null

BookRepository.java

代码语言:javascript
复制
@RepositoryRestResource
public interface BookRepository extends MongoRepository<Book, String> {
      
    @Query("{ 'ownerName' : ?#{principal?.username} }")
    List<Book> findAll();  
 
}

BookCustomRepositoryIntegrationTest.java

代码语言:javascript
复制
/**
 * Integrate data mongo + mvc
 */
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class BookCustomRepositoryIntegrationTest {
    
    @Autowired
    BookRepository repository;

    @Autowired
    MockMvc mockMvc;  

    @Test
    @WithMockUser
    public void reproduceBug() throws Exception {

        repository.findAll(); //Runs allright

        mockMvc.perform(get("/books")
                .contentType(APPLICATION_JSON_UTF8))
                .andExpect(status().isOk());

        repository.findAll(); //Throws exception: java.lang.IllegalArgumentException: Authentication object cannot be null


    }

}
EN

回答 2

Stack Overflow用户

发布于 2018-08-18 00:18:27

您的情况不起作用,因为SecurityContextPersistenceFilter和FilterChainProxy筛选器清除了SecurityContextHolder,但TestSecurityContextHolder (由WithSecurityContextTestExecutionListener填充)仍包含SecurityContext。

尝试以下方法:

代码语言:javascript
复制
@Test
@WithMockUser
public void reproduceBug() throws Exception {
    repository.findAll();
    mockMvc.perform(get("/books")
            .contentType(APPLICATION_JSON_UTF8))
            .andExpect(status().isOk());
    SecurityContextHolder.setContext(TestSecurityContextHolder.getContext());
    repository.findAll();
}
票数 9
EN

Stack Overflow用户

发布于 2021-03-31 15:47:19

我刚刚找到了这个问题的一个很好的解决方案。您可以在测试配置中注册MockMvcBuilderCustomizer bean,一切工作正常。

代码语言:javascript
复制
public class MockMvcTestSecurityContextPropagationCustomizer implements MockMvcBuilderCustomizer {

@Override
public void customize(ConfigurableMockMvcBuilder<?> builder) {
    builder.alwaysDo(result -> {
        log.debug("resetting SecurityContextHolder to TestSecurityContextHolder");
        SecurityContextHolder.setContext(TestSecurityContextHolder.getContext());
    });
}

}

弹簧靴

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51622300

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档