Spring Security基于用户角色的请求授权失效问题排查
问题分析与解决方案
核心问题定位
从调试日志里的JWT内容能直接揪出关键问题:"roles":[]——生成的JWT里完全没包含用户的角色信息,导致授权过滤器解析后拿到的角色集合是空的,自然无法通过权限校验,返回403。
另外还有两个次要问题影响功能:
- 安全规则的匹配顺序逻辑错误
- 部分请求路径配置缺失开头的斜杠
具体修复步骤
1. 修复JWT生成逻辑(最关键)
检查你的CustomAuthenticationFilter(登录过滤器),确保登录成功生成JWT时,正确将用户角色写入roles声明。示例代码参考:
// 登录成功后生成JWT的核心代码片段 UserDetails userDetails = ...; // 获取当前登录用户的UserDetails实例 String[] roles = userDetails.getAuthorities().stream() .map(GrantedAuthority::getAuthority) .toArray(String[]::new); // 生成JWT时必须正确写入roles字段 String token = JWT.create() .withSubject(userDetails.getUsername()) .withArrayClaim("roles", roles) .withExpiresAt(new Date(System.currentTimeMillis() + 86400000)) // 示例过期时间 .sign(Algorithm.HMAC256(secretKey.getBytes()));
2. 调整安全规则匹配顺序
Spring Security的规则是从上到下匹配,一旦匹配就停止后续规则判断。你当前的配置里,ROLE_USER的GET规则会先匹配/api/v1/movies/**,导致ROLE_ADMIN的同路径规则永远不会生效。需要把权限要求更高的规则放在前面:
@Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { AbstractAuthenticationProcessingFilter filter = new CustomAuthenticationFilter(authenticationManager()); filter.setFilterProcessesUrl("/api/v1/login"); http.csrf().disable(); http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); // 开放接口配置 http.authorizeHttpRequests() .requestMatchers("/api/v1/login/**", "/api/token/refresh/**").permitAll() .requestMatchers(GET, "/api/v1/user/**").permitAll() // 先配置ADMIN的规则,再配置USER的规则 .requestMatchers(GET, "/api/v1/movies/**", "/api/v1/reviews", "/api/v1/user").hasAnyAuthority("ROLE_ADMIN") .requestMatchers(GET, "/api/v1/movies/**", "/api/v1/reviews").hasAnyAuthority("ROLE_USER") // 修复路径开头缺失的斜杠 .requestMatchers(POST, "/api/v1/movies/**", "/api/v1/reviews/**", "/api/v1/user/**").hasAuthority("ROLE_ADMIN") .requestMatchers(PUT, "/api/v1/movies/**", "/api/v1/reviews/**", "/api/v1/user/**").hasAuthority("ROLE_ADMIN") .requestMatchers(DELETE, "/api/v1/movies/**", "/api/v1/reviews/**", "/api/v1/user/**").hasAuthority("ROLE_SUPER_ADMIN") .anyRequest().authenticated(); http.addFilter(filter); http.addFilterBefore(new CustomAuthorizationFilter(), UsernamePasswordAuthenticationFilter.class); return http.build(); }
3. 修复路径配置错误
你当前的POST/PUT/DELETE规则里,部分路径少了开头的/(比如api/v1/movies/**),这会导致规则匹配失效,所有路径都要统一写成/api/v1/movies/**这种完整格式。
验证建议
- 登录后解码JWT,确认
roles字段包含正确的角色值(比如["ROLE_USER"]或["ROLE_ADMIN"]) - 用不同角色的用户测试对应端点,观察授权是否正常
- 可以在
CustomAuthorizationFilter里添加日志,打印解析后的authorityCollections,确认角色是否正确加载
内容的提问来源于stack exchange,提问作者ABAB
相关产品推荐
相关产品推荐

