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

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或代理IP
  • webIgnoreMatchers/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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 01:51:07