You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义Spring Security过滤器测试返回401如何解决?

问题排查与解决方案

1. 检查自定义过滤器的认证Token有效性

你的示例过滤器中使用UsernamePasswordAuthenticationToken的三参数构造器,理论上会标记为已认证,但如果实际过滤器未正确设置认证状态或权限,会导致后续授权失败:

  • 确保校验通过时,创建的Authentication对象满足:
    • 使用三参数构造器(principal, credentials, authorities),此时isAuthenticated()会返回true
    • 权限集合即使为空,也需传入空集合而非null
    // 正确示例
    Collection<GrantedAuthority> authorities = Collections.emptyList();
    UsernamePasswordAuthenticationToken authentication = 
        new UsernamePasswordAuthenticationToken("principal@springboot.com", null, authorities);
    

2. 修正MockMVC请求头的类型错误

HTTP请求头的值必须是字符串,测试中传递整数类型的companyId会导致过滤器无法正确解析参数,触发校验失败:

// 修改前
.header("companyId", 1438)
// 修改后
.header("companyId", "1438")

3. 确保过滤器与安全配置在测试环境中被加载

  • 检查TestApplication的组件扫描范围是否包含WebSecurityConfig和AuthGatewayFilter,若测试用TestApplication是独立配置,需显式导入:
    @SpringBootApplication(scanBasePackageClasses = {WebSecurityConfig.class, AuthGatewayFilter.class})
    public class TestApplication { /* ... */ }
    
  • 或在测试类中直接指定加载的配置类:
    @SpringBootTest(classes = {WebSecurityConfig.class, AuthGatewayFilter.class, TestApplication.class})
    

4. 验证过滤器是否被正确执行

在AuthGatewayFilter的doFilterInternal方法中添加日志,确认测试时过滤器是否触发:

@Override
protected void doFilterInternal(...) throws ServletException, IOException {
    log.info("AuthGatewayFilter processing request: {}", request.getRequestURI());
    // 原有逻辑...
}

若日志未输出,说明安全配置未被正确加载,需检查@EnableWebSecurity和SecurityFilterChain的注册是否生效。

5. 显式配置MockMVC启用Spring Security支持

虽然@AutoConfigureMockMvc默认集成Spring Security,但手动配置可确保安全过滤器链被正确应用:

@Autowired
private WebApplicationContext context;

private MockMvc mockMvc;

@BeforeEach
void setUp() {
    mockMvc = MockMvcBuilders.webAppContextSetup(context)
            .apply(springSecurity()) // 显式启用Spring Security支持
            .build();
}

6. Mock过滤器逻辑(用于单元测试)

如果不想依赖真实的JWT校验逻辑,可在测试中替换AuthGatewayFilter为Mock实现:

@SpringBootTest
@ContextConfiguration(classes = TestApplication.class)
@AutoConfigureMockMvc
class Auth0IntegrationControllerTest {

    @MockBean
    private AuthGatewayFilter authGatewayFilter;

    @Autowired
    MockMvc mockMvc;

    @BeforeEach
    void setUp() throws Exception {
        // Mock过滤器逻辑,直接设置认证
        doAnswer(invocation -> {
            HttpServletRequest request = invocation.getArgument(0);
            UsernamePasswordAuthenticationToken authentication = 
                new UsernamePasswordAuthenticationToken("principal@springboot.com", null, Collections.emptyList());
            authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
            SecurityContextHolder.getContext().setAuthentication(authentication);
            FilterChain chain = invocation.getArgument(2);
            chain.doFilter(request, invocation.getArgument(1));
            return null;
        }).when(authGatewayFilter).doFilterInternal(any(), any(), any());
    }

    // 测试方法...
}

内容的提问来源于stack exchange,提问作者Lorenzo De Francesco

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 12:07:46