Spring Security角色认证失败:Get User API返回403 Forbidden问题排查
从你提供的日志能直接看出核心问题:认证后的用户权限仅包含SCOPE_email和SCOPE_profile,完全没有ROLE_PROF——这就是调用接口返回403的根本原因,你的JwtAuthConverter没有从JWT中正确提取到PROF角色。
排查与修复步骤
1. 先确认JWT的实际内容
解析你用来调用接口的JWT令牌,检查resource_access字段的结构是否符合预期。正确的结构应该类似:
{ "resource_access": { "你的resource-id配置值": { "roles": ["PROF"] } } }
如果该字段不存在、resource-id与配置不匹配,或者roles数组里没有PROF,角色肯定提取失败。
2. 检查配置文件参数
确认application.properties/application.yml中jwt.auth.converter.resource-id的取值,是否和JWT里resource_access下的key完全一致(大小写敏感)。比如JWT里是user-api,配置里就不能写成User-API。
3. 修复JwtAuthConverter的防御性逻辑
你的extractResourceRoles方法缺少空值和类型校验,容易因为JWT字段格式问题导致角色提取失败,修改后的方法可以更健壮:
private Collection<? extends GrantedAuthority> extractResourceRoles(Jwt jwt) { Map<String, Object> resourceAccess = jwt.getClaim("resource_access"); if (resourceAccess == null || resourceAccess.isEmpty()) { return Set.of(); } Object resourceObj = resourceAccess.get(resourceId); if (!(resourceObj instanceof Map)) { return Set.of(); } Map<String, Object> resource = (Map<String, Object>) resourceObj; Object rolesObj = resource.get("roles"); if (!(rolesObj instanceof Collection)) { return Set.of(); } Collection<String> resourceRoles = (Collection<String>) rolesObj; return resourceRoles.stream() .map(role -> new SimpleGrantedAuthority("ROLE_" + role)) .collect(Collectors.toSet()); }
4. 调整SecurityConfig的授权规则
你当前的securityFilterChain设置了anyRequest().permitAll(),这会让所有请求默认被允许,虽然@PreAuthorize仍会生效,但建议改为更严谨的规则:
http.authorizeHttpRequests() .anyRequest().authenticated();
确保所有请求都需要先通过认证,避免权限规则冲突。
验证方法
修改后重启服务,再次调用接口并查看debug日志,确认认证后的Granted Authorities中包含ROLE_PROF。如果存在该权限,@PreAuthorize("hasRole('PROF')")就能正常通过授权。
内容的提问来源于stack exchange,提问作者Nouhaila Khaouti

