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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 10:09:17