SpringBoot从2.1.7升级至2.1.8后WebSecurity出现401无报错问题
问题描述
- 将SpringBoot版本从2.1.7升级至2.1.8后,所有接口返回401状态码,但无任何错误日志输出
- 仅执行版本升级操作,未修改任何业务代码或配置文件
- 本地Ubuntu 22.04环境运行正常,部署到CentOS 7.9预生产环境时出现该问题
- 技术栈:Java 8、Tomcat,采用OAuth2资源服务器JWT认证方案
WebSecurity配置代码
import java.util.List; import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; @Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { private static final Logger logger = Logger.getLogger(WebSecurityConfig.class); @Value("${roles}") public String roles; @Value("${security.allowed.ip}") private String allowedIp; @Value("${web.security.config.web.ignore.matchers}") private List<String> webIgnoreMatchers; @Value("${web.security.config.http.cors.matchers}") private List<String> httpCorsMatchers; @Override public void configure(WebSecurity web) { try { web.ignoring() .antMatchers(webIgnoreMatchers.stream().toArray(String[]::new)); } catch (Exception e) { logger.error(e.getMessage(), e); } } @Override protected void configure(HttpSecurity http) { try { http.csrf().disable().cors().and().authorizeRequests() .antMatchers("/someendpoint").hasIpAddress(allowedIp) .antMatchers(httpCorsMatchers.stream().toArray(String[]::new)) .permitAll() .mvcMatchers("/**") .hasAnyAuthority(roles).anyRequest().authenticated().and() .oauth2ResourceServer().jwt().jwtAuthenticationConverter(new CustomJwtAuthenticationConverter()); } catch (Exception e) { logger.error(e.getMessage(), e); } } }
排查及解决方案
1. 开启Spring Security调试日志
当前无错误日志无法定位问题,需开启Spring Security的DEBUG级别日志:
在应用配置文件(application.properties/yml)中添加:
logging.level.org.springframework.security=DEBUG
部署后重新请求接口,通过日志查看认证流程的详细步骤,定位401触发点。
2. 验证预生产环境配置参数
本地与预生产环境配置可能存在差异,需确认以下配置项取值:
roles:是否为正确的权限字符串(如ROLE_ADMIN,ROLE_USER,注意逗号分隔无空格)security.allowed.ip:是否包含预生产环境中请求接口的客户端IP或代理IPwebIgnoreMatchers/httpCorsMatchers:路径匹配规则是否覆盖了需要放行的接口
3. 修复客户端IP获取逻辑
预生产环境通常会部署反向代理(如Nginx),若未配置Tomcat的IP转发逻辑,Spring Security会将代理IP识别为客户端IP,导致hasIpAddress(allowedIp)校验失败:
- 在SpringBoot配置中添加:
server.tomcat.remoteip.remote-ip-header=X-Forwarded-For server.tomcat.remoteip.protocol-header=X-Forwarded-Proto - 或在Tomcat的
server.xml中配置RemoteIpValve:<Valve className="org.apache.catalina.valves.RemoteIpValve" remoteIpHeader="X-Forwarded-For" protocolHeader="X-Forwarded-Proto" protocolHeaderHttpsValue="https"/>
4. 排查CustomJwtAuthenticationConverter异常
配置中try-catch捕获了所有异常但仅输出日志,若预生产环境log4j配置未正确输出该日志,会导致异常被隐藏:
- 临时移除
configure(HttpSecurity)方法中的try-catch,让异常直接抛出便于定位 - 或在
CustomJwtAuthenticationConverter的convert方法中添加详细日志,排查JWT解析或权限转换是否存在异常
5. 对比SpringBoot版本差异
查看SpringBoot 2.1.8官方发布说明,确认是否存在OAuth2资源服务器或IP认证相关的微小变更,比如IP地址匹配规则调整、JWT解析默认配置变化等,针对性调整配置代码
内容的提问来源于stack exchange,提问作者Sherif Mo Shalaby
相关产品推荐
相关产品推荐

