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

Spring Security集成JWT后无法认证登录问题求助

登录认证失败排查与修复方案

1. 自定义AuthenticationProvider未注册到Security链

你的CustomAuthenticationProvider虽标注了@Service,但未被加入Spring Security的认证体系,默认会使用内置的DaoAuthenticationProvider,导致自定义认证逻辑根本没执行。

修复方法:在SecurityConfig中注入并配置自定义认证提供者:

@Configuration
public class SecurityConfig {

    @Autowired
    private CustomAuthenticationProvider customAuthenticationProvider;

    @Bean
    SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
        // ... 原有配置 ...
        http.authenticationProvider(customAuthenticationProvider); // 添加这行注册自定义Provider
        // ... 原有配置 ...
    }

    // ... 其他Bean定义 ...
}

2. 无状态会话与表单登录的冲突

你配置了session.sessionCreationPolicy(SessionCreationPolicy.STATELESS),但Spring Security默认表单登录依赖会话保存认证状态。无状态模式下不会创建会话,登录成功后无法维持认证状态,导致后续请求直接跳回登录页。

修复方案二选一:

  • 保留表单登录:修改会话策略为IF_REQUIRED
    http.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED))
    
  • 坚持无状态:弃用默认表单登录,改用API接口(如POST /login)登录,登录成功后返回JWT,前端后续请求携带JWT请求头。

3. JWT生成时机错误

JWTTokenGeneratorFilter的shouldNotFilter方法限定只有请求/user时才生成Token,但默认表单登录成功后不会自动请求/user,导致登录后无法获取JWT,后续请求无认证凭证,被拦截跳回登录页。

修复方法:调整过滤器触发条件,或添加登录成功处理器直接生成Token:

方式一:修改过滤器触发逻辑

@Override
protected boolean shouldNotFilter(HttpServletRequest request) {
    // 让登录请求和/user请求都触发Token生成
    return !request.getServletPath().equals("/login") && !request.getServletPath().equals("/user");
}

方式二:添加登录成功处理器(更推荐)

// 在SecurityConfig的formLogin配置中添加
.formLogin(form -> form
    .successHandler((request, response, authentication) -> {
        // 复制JWTTokenGeneratorFilter中的Token生成逻辑
        SecretKey key = Keys.hmacShaKeyFor(SecurityConstants.JWT_KEY.getBytes(StandardCharsets.UTF_8));
        String jwt = Jwts.builder().setIssuer("Eazy Bank").setSubject("JWT Token")
                .claim("username", authentication.getName())
                .claim("authorities", populateAuthorities(authentication.getAuthorities()))
                .setIssuedAt(new Date())
                .setExpiration(new Date((new Date()).getTime() + 30000000))
                .signWith(key).compact();
        response.setHeader(SecurityConstants.JWT_HEADER, jwt);
        // 返回JSON格式的Token
        response.setContentType("application/json");
        response.getWriter().write("{\"token\":\"" + jwt + "\"}");
    })
)

注:需将populateAuthorities方法提取为公共方法,方便复用

4. 角色权限匹配问题

/customerList配置了.hasRole("USER"),但CustomAuthenticationProvider返回的是SimpleGrantedAuthority(auth.getName())。Spring Security的hasRole会自动给权限添加ROLE_前缀,即只有权限为ROLE_USER时才能访问该接口;若数据库中存储的权限是USER,会导致权限不匹配,被拦截跳回登录页。

修复方案二选一:

  • 修改数据库中的权限为ROLE_USER,保持hasRole配置不变;
  • 将hasRole("USER")改为hasAuthority("USER"),直接匹配原始权限名:
    .requestMatchers("/customerList").hasAuthority("USER")
    

内容的提问来源于stack exchange,提问作者Tara

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 19:40:40