Spring Security AD认证Tomcat正常 Open/WAS Liberty返回403
问题根因
这个问题和Spring Security代码逻辑无关,完全是容器环境差异导致的,核心诱因有3个:
- 路径匹配错位:嵌入式Tomcat默认把应用部署在根上下文,你配置的
/auth路径规则可以直接命中;Open/WAS Liberty默认给应用分配带版本/应用名的上下文前缀(你当前请求的前缀是/myapi/v1),你写死的antMatchers("/auth")和过滤器拦截路径/auth匹配不到实际请求地址,请求直接走到anyRequest().authenticated()规则,被判定为未授权访问返回403。 - Liberty自带安全过滤器前置拦截:Liberty默认启用Java EE安全特性(appSecurity),服务器级别的安全过滤器优先级高于Spring Security过滤器链,会在Spring逻辑执行前先做权限校验,直接拦截未在服务器配置中声明为公开的接口返回403。
- 过滤器顺序不确定:你手动注册两个自定义过滤器时没有显式指定顺序,Liberty的Servlet容器过滤器加载顺序和嵌入式Tomcat不一致,可能出现授权过滤器先执行、权限校验逻辑提前触发的问题。
修复步骤
按顺序调整即可解决问题:
- 统一上下文路径配置
两种方案二选一:- 方案A:在Spring Boot配置文件中显式指定上下文路径,和Liberty部署路径对齐:
# application.properties server.servlet.context-path=/myapi/v1 - 方案B:修改Liberty的
server.xml,把应用直接挂载到根上下文,彻底消除路径前缀差异:<webApplication location="你的应用包.war" contextRoot="/" />
antMatchers替换为mvcMatchers,后者会自动适配上下文路径,避免硬编码路径导致的匹配问题,并且显式指定自定义过滤器的注册顺序:@Override protected void configure(HttpSecurity http) throws Exception { http .cors(Customizer.withDefaults()) .csrf().disable() .authorizeRequests() // 替换antMatchers为mvcMatchers,显式指定POST方法 .mvcMatchers(HttpMethod.POST, "/auth").permitAll() .anyRequest() .authenticated() .and() // 显式指定过滤器顺序,和Spring默认过滤器链对齐 .addFilterAfter(getAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class) .addFilterAfter(new AuthorizationFilter(authenticationManager()), AuthenticationFilter.class) .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); } - 方案A:在Spring Boot配置文件中显式指定上下文路径,和Liberty部署路径对齐:
- 关闭Liberty自带的安全拦截
打开Liberty的server.xml配置:- 如果不需要使用Liberty提供的Java EE安全能力,直接删掉配置中的
appSecurity-3.0/appSecurity-4.0特性项,从根源避免服务器级过滤器拦截。 - 如果必须保留appSecurity特性,需要在应用的
web.xml中添加安全约束,声明所有接口不受服务器安全管控:<security-constraint> <web-resource-collection> <web-resource-name>All endpoints</web-resource-name> <url-pattern>/*</url-pattern> </web-resource-collection> </security-constraint>
- 如果不需要使用Liberty提供的Java EE安全能力,直接删掉配置中的
- 补全自定义认证过滤器的匹配规则
自定义AuthenticationFilter除了设置处理URL,还要显式指定只拦截POST方法的对应路径,避免容器环境下的路径匹配异常:private AuthenticationFilter getAuthenticationFilter() throws Exception { final AuthenticationFilter filter = new AuthenticationFilter(authenticationManager()); filter.setFilterProcessesUrl("/auth"); // 显式配置请求匹配规则,只拦截POST方法的/auth请求 filter.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/auth", "POST")); return filter; } - (可选)关闭Liberty默认CSRF防护
部分版本Liberty默认开启服务器级CSRF校验,会直接拦截非可信来源的POST请求返回403,如果前面三步配置完成后仍有问题,在server.xml中添加配置关闭该功能:<webContainer disableCsrfProtection="true"/>
内容的提问来源于stack exchange,提问作者pixel
相关产品推荐
相关产品推荐

