Spring Security配置后鉴权未生效 可无认证访问后端如何排查
Spring Security 未生效、无凭证可直接访问接口修复方案
核心问题点
- 过滤器实例直接通过
new创建,未纳入Spring容器管理,内部依赖的jwtTokenUtil为null,请求进入过滤器时直接触发空指针,异常被过滤器链吞掉后直接放行,拦截逻辑完全失效 - 过滤器内逻辑错误:无token/ token非法时直接返回403,未对接Spring Security的未认证跳转逻辑;字符串比较用
==判断空值,逻辑判断失效;无论token是否合法都提前写入认证信息,存在越权风险 - 登录页配置方式错误:直接给
formLogin().loginPage()传绝对外部地址无法生效,且未配置认证失败的跳转逻辑 - 未排除过滤器重复注册问题:手动new的过滤器实例可能被Spring Boot自动注册到全局Servlet过滤器链,顺序错乱导致拦截不生效
修复步骤
1. 修正JWT过滤器实现,交给Spring容器管理
给过滤器加@Component注解,通过@Autowired注入依赖,调整校验逻辑顺序,无有效token时清空安全上下文后放行,交给后续认证流程判断是否需要跳转:
import com.corp.myproject.config.security.JwtTokenUtil; import com.corp.myproject.config.security.UserFromToken; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; @Component public class JwtAuthorizationFilter extends OncePerRequestFilter { @Autowired private JwtTokenUtil jwtTokenUtil; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String authorizationToken = request.getHeader("Authorization"); // 无token直接放行,交给后续认证规则处理 if (authorizationToken == null || !authorizationToken.startsWith("Bearer ")) { filterChain.doFilter(request, response); return; } String jwt = authorizationToken.substring(7); // token校验不通过直接清空上下文放行 if (!jwtTokenUtil.isTokenIntegritySafe(jwt) || !jwtTokenUtil.validateToken(jwt)) { SecurityContextHolder.clearContext(); filterChain.doFilter(request, response); return; } // 校验通过再写入认证信息 UserFromToken userFromToken = jwtTokenUtil.getUserFromToken(jwt); Collection<GrantedAuthority> authorities = new ArrayList<>(); for (String role : userFromToken.getRoles()) { authorities.add(new SimpleGrantedAuthority(role)); } UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(userFromToken.getName(), null, authorities); SecurityContextHolder.getContext().setAuthentication(authToken); filterChain.doFilter(request, response); } }
2. 修正安全配置类,注入容器管理的过滤器,配置跳转规则
不要手动new过滤器实例,直接注入Spring管理的Bean,通过authenticationEntryPoint配置未认证时的302跳转逻辑,关闭默认表单登录避免冲突:
import com.corp.myproject.config.security.filters.JwtAuthorizationFilter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; @Configuration @EnableWebSecurity public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter { @Autowired private JwtAuthorizationFilter jwtAuthorizationFilter; @Override protected void configure(HttpSecurity http) throws Exception { http.addFilterBefore(jwtAuthorizationFilter, UsernamePasswordAuthenticationFilter.class) .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() .exceptionHandling() // 未认证请求重定向到OpenID登录地址 .authenticationEntryPoint((req, resp, ex) -> resp.sendRedirect("http://localhost:8081/login/openidProvider")) .and() .authorizeRequests().anyRequest().authenticated() .and() .csrf().disable() .formLogin().disable(); } }
3. 校验项
- 确认
JwtTokenUtil已加@Component注解,可被Spring正常扫描注入 - 确认配置类、过滤器所在包在Spring Boot组件扫描路径下,避免Bean未加载
- 若使用Spring Boot 2.7+版本,可后续将废弃的
WebSecurityConfigurerAdapter写法迁移为SecurityFilterChainBean的配置方式,当前写法兼容可正常运行
内容的提问来源于stack exchange,提问作者LearnLearnLearn
相关产品推荐
相关产品推荐

