当前位置: 首页 > news >正文

使用token调用Spring OAuth2 Resource Server接口错误 insufficient_scope

1、场景

最近照着《Spring Security实战》学习,学到第18章,使用Keycloak作为授权服务器,使用

org.springframework.boot:spring-boot-starter-oauth2-resource-server

 实现资源服务器,调用资源服务器的接口返回403,具体错误信息如下:

WWW-Authenticate: Bearer error="insufficient_scope", error_description="The request requires higher privileges than provided by the access token.", error_uri="https://tools.ietf.org/html/rfc6750#section-3.1"

 那就检查scope吧

2、检查scope

2.1 查看access_token(JWK)

到这个网址查看明文的令牌:JSON Web Tokens - jwt.io

看看 scope 都有哪些值。

2.2 资源服务配置

    @Beanpublic SecurityFilterChain filterChain(HttpSecurity http) throws Exception {http.authorizeHttpRequests(authorize -> authorize
//                        .requestMatchers(HttpMethod.POST, "/workout/").hasAuthority("SCOPE_fitnessapp").requestMatchers(HttpMethod.POST, "/workout/").access(hasScope("fitnessapp")).requestMatchers(HttpMethod.DELETE, "/**").hasAuthority("fitnessadmin").anyRequest().authenticated()).oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults()));return http.build();}

上一步看到 scope 包含 fitnessapp,那就设置 

access(hasScope("fitnessapp"))

注:实际上资源服务器不设置 scope 也是可以的,因为根本原因不在 scope!!!

3、根本原因以及解决办法

3.1 开启 Spring Security 的日志

在 application.yml 添加配置:

logging:level:org.springframework.security: DEBUG 

再次调用接口,发现这样一段信息:

ExpressionAuthorizationDecision [granted=false, expressionAttribute=#workout.user == authentication.name] 

出问题的代码就是下面这个方法:

@PreAuthorize("#workout.user == authentication.name")
public void saveWorkout(Workout workout) {workoutRepository.save(workout);
}

于是打印看认证后获取的用户名

String name = SecurityContextHolder.getContext().getAuthentication().getName();
System.out.println("###  authentication.name=" + name);

 果然,name不是预期的用户名,而是一段UUID字符串,问DeepSeek这是怎么回事,接着再细看JWK的明文,name 就是token中的 sub 字段的值。

3.2 解决办法

登录Keycloak控制台添加映射器,Client scopes -> fitnessapp -> Mappers

 

 

 

然后重新获取token,看看 sub 字段的值是不是对应的用户名,是的话就没问题了。

最后使用新的token重新调用资源服务器接口,返回200,调用成功!

 

http://www.dtcms.com/a/282698.html

相关文章:

  • 服务攻防-Java组件安全数据处理FastJsonJackSonXStream自动BP插件CVE漏洞
  • 多级缓存架构与热点探测系统核心技术解析
  • 2025年C++后端开发高频面试题深度解析:线程安全LRU缓存设计与实现
  • 免费MCP服务:Excel CSV 转 JSON MCP by WTSolutions 文档
  • C++:现代 C++ 编程基石,C++11核心特性解析与实践
  • 软件开发:重塑商贸物流行业格局的核心力量
  • Zabbix监控K8S的PV信息详细教程!
  • AI产品经理面试宝典第25天:AI+机器人产品设计与技术落地面试题与答法
  • Xsens人形机器人拟人动作AI训练,提升机器人工作精度与效率
  • MySQL高并发高可用架构:分库分表实战与ShardingSphere中间件应用
  • JavaScript语言 Error对象及错误处理机制 原生错误类型
  • 芯谷科技--FET偏置控制器,为卫星通信系统提供稳定偏置D8400
  • 大模型智能体(Agent)工程化:AutoGen企业级落地方案全解析
  • exports使用 package.json字段控制如何访问你的 npm 包
  • A13 GMS应用预装
  • 微服务引擎 MSE 及云原生 API 网关 2025 年 5 月产品动态
  • Git 提交信息(Commit Message)的规范校验,husky + commitlint
  • Java全栈工程师面试实录:从电商场景到AIGC的深度技术挑战
  • 手动搭建PHP环境:步步为营,解锁Web开发
  • 【尝试】基于openai-whisper进行语音转文字windows版本
  • 【项目实践】SMBMS(Javaweb版)汇总版
  • flink sql如何对hive string类型的时间戳进行排序
  • python应用day11--requests爬虫详解
  • Dify工作流节点-Agent
  • 前端上传 pdf 文件 ,前端自己解析出来 生成界面 然后支持编辑
  • 数据降维方法:PCA
  • Vue2.x封装预览PDF组件
  • 利用pdfjs实现的pdf预览简单demo(包含翻页功能)
  • 从0开始学习R语言--Day48--Calibration Curves 评估模型
  • ByteToMessageDecoder详解