Spring Boot集成CXF JAX-WS与Security出现401异常
问题本质
引入Spring Security后,其内置的Servlet过滤器优先级远高于CXF的请求处理链,所有请求会先被Spring Security的默认拦截规则处理。未做路径区分的场景下,SOAP请求会在到达CXF自定义拦截器之前就被Spring Security拦截,直接返回401,根本不会触发BasicAuthAuthorizationInterceptor的逻辑。
解决方案
1. 配置Spring Security规则,跳过CXF路径的默认拦截
将你实际使用的CXF服务暴露路径(默认值为/services/**,可在配置文件中修改)加入Spring Security的放行列表,让这类请求直接绕开Spring Security的过滤器,进入CXF的拦截处理链。
以Spring Security 5+(Spring Boot 2.7及以上版本适配)的配置为例:
@Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .csrf(csrf -> csrf.disable()) .authorizeHttpRequests(auth -> auth // 匹配规则和你的实际CXF路径保持完全一致 .requestMatchers("/services/**").permitAll() // 其余REST接口保留Spring Security认证能力 .anyRequest().authenticated() ) .httpBasic(withDefaults()); return http.build(); } }
同步检查配置文件中的CXF路径配置,保证和上面的匹配规则完全一致:
cxf: path: /services
2. 验证CXF拦截器的注册逻辑
确认BasicAuthAuthorizationInterceptor被正确加入CXF端点的入站拦截链,常见的注册示例如下:
@Configuration public class CxfServiceConfig { // 初始化自定义认证拦截器,注入合法用户凭证 @Bean public BasicAuthAuthorizationInterceptor basicAuthInterceptor() { BasicAuthAuthorizationInterceptor interceptor = new BasicAuthAuthorizationInterceptor(); Map<String, String> validUsers = new HashMap<>(); validUsers.put("soap_user", "soap_pass_123"); interceptor.setUsers(validUsers); return interceptor; } // 发布SOAP端点时绑定拦截器 @Bean public Endpoint soapEndpoint(Bus cxfBus, BasicAuthAuthorizationInterceptor basicAuthInterceptor) { EndpointImpl endpoint = new EndpointImpl(cxfBus, new YourSoapServiceImpl()); endpoint.publish("/your-service"); // 入站拦截链加入自定义认证逻辑 endpoint.getInInterceptors().add(basicAuthInterceptor); return endpoint; } }
3. 可选优化:复用统一认证体系
如果不需要SOAP接口走独立的认证逻辑,可以直接复用Spring Security的认证能力,避免双轨校验:
- 移除自定义的
BasicAuthAuthorizationInterceptor - 将Spring Security配置中CXF路径的规则从
permitAll()调整为.authenticated(),让SOAP请求和REST接口共用同一套基础认证规则 - 配置CXF路径为无状态会话模式,避免多余的Session生成:
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
常见踩坑提醒
- 路径匹配偏差:如果实际CXF路径和Spring Security配置的匹配路径不一致(比如实际是
/soap/**却配置了/services/**),依然会被Spring Security拦截返回401,需要逐字符核对路径 - 拦截器挂载位置错误:自定义认证拦截器必须加入
endpoint.getInInterceptors()入站链,挂载到出站链(getOutInterceptors())时不会在请求接收阶段触发 - 权限配置冲突:如果给放行的CXF路径配置了其他权限校验规则,也会导致请求被拦截,需要保证路径规则为
permitAll()后再放行。
内容的提问来源于stack exchange,提问作者Manuel Demanuel Rodríguez
相关产品推荐
相关产品推荐

