当前位置: 首页 > 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.lryc.cn/news/590583.html

相关文章:

  • Scrapy无缝集成Splash:轻量级动态渲染爬虫终极解决方案
  • Oracle 数据库常见等待事件参数详解
  • 16路串口光纤通信FPGA项目实现指南 - 第二部分(上)
  • FPGA基础 -- Verilog 访问寄存器数组的指定位示例
  • 从函数调用到进程通信:Linux下的多语言协作实践
  • 识别装甲板
  • 【Jupyter】个人开发常见命令
  • HugeGraph 【图数据库】JAVA调用SDK
  • ByteToMessageDecoder详解
  • Spring AI快速入门
  • VisualVM监控远程Linux的java进程
  • 【SpringBoot】实战-开发接口-用户-注册
  • matlab的伯德图为何从360度显示?应如何修改解决?
  • 基于大数据的网络文学推荐分析系统的设计与实现【海量书籍、自动爬虫】
  • Redis1:高并发与微服务中的键值存储利器
  • mongodb操作巨鹿
  • DHTMLX Suite 9.2 重磅发布:支持历史记录、类Excel交互、剪贴板、拖放增强等多项升级
  • Qt小组件 - 6 异步运行函数
  • Redis深度解析:从缓存到分布式系统的核心引擎
  • Java高并发编程(2)
  • beautiful-react-hooks库——入门实践常用hook详解
  • React之旅-09 useMemo,优化计算性能的利器
  • React 源码7:Lane、React和schedule优先级转换
  • WPF 多窗口分文件实现方案
  • 【MAC】nacos 2.5.1容器docker安装
  • QT——事件系统详解
  • 多语言json文件内\n换行不生效问题
  • React -自定义hooks - 封装双向数据绑定
  • React 中 props 的最常用用法精选+useContext
  • H3CNE综合实验之机器人