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

Spring Security OAuth2 JWT权限异常:已认证用户仍遭403拒绝

问题分析与解决方案

从你提供的堆栈日志能直接定位核心问题:认证后的用户实际持有的权限是SCOPE_USER,但你的配置要求的是USER权限,两者不匹配导致403拒绝访问。

日志里的关键信息:

Granted Authorities=[SCOPE_USER]

这说明Spring Security从JWT令牌中解析出的权限是SCOPE_USER,而你在Web Security配置中要求的是.hasAuthority("USER"),自然无法通过权限校验。


解决步骤

1. 确保JWT生成时正确写入用户权限

你的登录接口生成JWT时,需要把数据库中用户的权限(比如USER或ROLE_USER)写入JWT的Claims字段中。示例代码如下:

@PostMapping("/loginrest")
public ResponseEntity<?> login(@RequestBody LoginRequest request) {
    // 用户认证逻辑
    Authentication authentication = authenticationManager.authenticate(
        new UsernamePasswordAuthenticationToken(request.getUsername(), request.getPassword())
    );
    SecurityContextHolder.getContext().setAuthentication(authentication);

    // 提取用户权限
    List<String> authorities = authentication.getAuthorities().stream()
        .map(GrantedAuthority::getAuthority)
        .collect(Collectors.toList());

    // 构建JWT Claims,写入权限
    Instant now = Instant.now();
    JwtClaimsSet claims = JwtClaimsSet.builder()
        .issuer("your-app")
        .issuedAt(now)
        .expiresAt(now.plus(1, ChronoUnit.HOURS))
        .subject(authentication.getName())
        .claim("authorities", authorities) // 将权限写入JWT
        .build();

    String jwt = jwtEncoder.encode(JwtEncoderParameters.from(claims)).getTokenValue();
    return ResponseEntity.ok(new JwtResponse(jwt));
}

2. 配置JWT权限转换器

Spring Security默认会从JWT的scope或scp字段提取权限,并自动添加SCOPE_前缀。如果你的权限存在于自定义字段(比如上面的authorities),需要自定义JwtAuthenticationConverter来正确解析:

@Bean
public JwtAuthenticationConverter jwtAuthenticationConverter() {
    JwtGrantedAuthoritiesConverter grantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
    // 设置从JWT的"authorities"字段提取权限
    grantedAuthoritiesConverter.setAuthoritiesClaimName("authorities");
    // 如果不需要前缀,清空默认的"SCOPE_"前缀
    grantedAuthoritiesConverter.setAuthorityPrefix("");

    JwtAuthenticationConverter converter = new JwtAuthenticationConverter();
    converter.setJwtGrantedAuthoritiesConverter(grantedAuthoritiesConverter);
    return converter;
}

然后在SecurityFilterChain中配置这个转换器:

.oauth2ResourceServer(oauth2 -> oauth2
    .jwt(jwt -> jwt
        .jwtAuthenticationConverter(jwtAuthenticationConverter())
    )
)

3. 对齐权限规则与实际权限

  • 如果数据库中用户权限是USER,配置用.hasAuthority("USER")
  • 如果数据库中用户权限是ROLE_USER,配置用.hasRole("USER")(hasRole会自动拼接ROLE_前缀)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 08:30:51