java - MockMvc 在执行请求后似乎很清楚 SecurityContext (java.lang.IllegalArgumentException : Authentication object cannot be null)

标签 java spring spring-data spring-data-mongodb mockmvc

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

我已经简化并通用化了代码,但它应该能够通过以下测试重现该行为。

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

出于此处问题的目的,我已将测试简化为一个 GET,然后调用 findAll()

问题

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

java.lang.IllegalArgumentException: 身份验证对象不能为空

图书资料库.java

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

BookCustomRepositoryIntegrationTest.java

/**
 * 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


    }

}

最佳答案

您的案例不起作用,因为 SecurityContextPersistenceFilter 和 FilterChainProxy 过滤器清除了 SecurityContextHolder,但 TestSecurityContextHolder(由 WithSecurityContextTestExecutionListener 填充)仍然包含 SecurityContext。

试试这个方法:

@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();
}

关于java - MockMvc 在执行请求后似乎很清楚 SecurityContext (java.lang.IllegalArgumentException : Authentication object cannot be null),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51622300/

相关文章:

java - 具有固定纳米值长度的 DateTimeFormatter

java - 在 Spring Boot 中为 @WebMvcTest 禁用 Spring Security 配置类

java - Mockito测试抛出 "URI is not absolute"错误

spring-data-mongo 使用 MappingMongoConverter 更新文档中的空值

java - IllegalArgumentException 和 BeanCreationException : No property found for type error

java - SpringData MongoDB 查询嵌套对象和列表对象

java - 接口(interface)除了拥有正确的方法之外还有其他意义吗

Java:更新 jar 文件时加载类

Spring组件扫描自定义过滤器

java - Apache commons io Tailer : Handle log rotation