100 spring-security 中 /oauth/token 发送请求不携带参数 报错 “401 Unauthorized“

前言

最近存在这样的一个问题, 大致的复现方式是 访问 /oauth/token 接口, 然后不携带任何参数, 结果 服务器抛出了一个 "401 Unauthorized" 

针对这个 401, 这里 梳理一下这个流程, 也会衍生出一些其他的问题 

 

 

测试用例

客户端这边大致的情况是 构造参数, 然后发送请求, 上面两个 参数封装到查询字符串的请求是可以正常处理 

后面两个 未携带参数 的请求发送, 报错 "401 Unauthorized" 

我们这里主要关心 这里的未携带参数 的异常场景, 以及 造成这个问题的整个流程 

3. 具体的 ignore-urls 的业务层面的使用

主要是在 FilterSecurityInterceptor, 这里面我们核心需要关注几个部分

    3.1 this.obtainSecurityMetadataSource().getAttributes(object) 根据当前 request 获取认证属性

    3.2 Authentication authenticated = authenticateIfRequired(); 根据请求头里面拿到的 token, 访问 auth 服务, 获取用户以及关联信息, 封装 Authentication

    3.3 accessDecisionManager.decide 结合 认证属性 和 Authentication 来判断是否有权限

 

/*** Test11TestRestClient** @author Jerry.X.He* @version 1.0* @date 2022/5/19 17:44*/
public class Test11TestRestClient {/// Test11TestRestClientpublic static void main(String[] args) {String username = "xxx";String password = "xxx";String grantType = "password";Map<String, String> queryParams = new LinkedHashMap<>();queryParams.put("username", username);queryParams.put("password", password);queryParams.put("grant_type", grantType);queryParams.put("scope", "server");queryParams.put("client_id", "xxx");queryParams.put("client_secret", "xxx");RestTemplate restTemplate = new RestTemplate();String queryString = Tools.encapQueryString(queryParams);//        String loginUrl = "http://10.60.50.50:9999/auth/oauth/token?" + queryString;
//        Map result = restTemplate.postForObject(loginUrl, null, Map.class);
//        Map result = restTemplate.getForObject(loginUrl, Map.class);String loginUrl = "http://10.60.50.50:9999/auth/oauth/token";Map result = restTemplate.postForObject(loginUrl, null, Map.class);// todo, getForObject 的时候 查询字符串 未拼接 到 uri 中
//        Map result = restTemplate.getForObject(loginUrl, Map.class, queryParams);int x = 0;}}

 

 

问题的调试

来到认证被拒绝的地方, 可以看到的是 /oauth/token  请求是需要 fullyAuthenticated 的 

cffec01b9c7a41cca0c410587e6d16ca.png

 

 

fullyAuthenticated  的条件是 不是匿名用户 并且 xxx, 这里我们的 authentication 因为没有携带参数信息, 然后 匿名过滤器填充了一个 匿名的 authentication 

83da41b181384cc08113d50beeb5a87a.png

 

 

假设是在客户端正常携带了参数的场景下面, 是怎么过验证的呢? 

这里走的是 ClientCredentialsTokenEndpointFilter 走的一个 自定义的处理, 获取认证信息, 这里能够正常的拿到认证信息, 因此能够正常认证通过 

0c75731afd854139befc922551783293.png

 

 

我准备临时处理一下, 去掉 /oauth/token 的需要认证的处理, 于是在 WebSecurityConfigurer 中增加了 antMatchers("/oauth/token").permitAll() 但是, 从 this.obtainSecurityMetadataSource().getAttributes(object) 拿到的 attributes 还是 fullyAuthenticated, 而不是我这里配置的 permitAll 

我们这里会出现几点疑问 

  1. 为什么 /oauth/token 配置的是 fullyAuthenticated 
  2. 为什么 我配置了 antMatchers("/oauth/token").permitAll(), 但是没有生效 

 

 

为什么 /oauth/token 配置的是 fullyAuthenticated 

AuthorizationServerSecurityConfiguration 中 init 的时候初始化的时候配置 /oauth/token 为 fullyAuthenticated 

AuthorizationServerSecurityConfiguration  是继承自 SecurityConfigurer, 是 spring-security 中自带的 XXConfiguration, 业务上面的限定 一般还存在一个 WebSecurityConfigurer 

b296d8244a68429aaab8d4d73616d200.png

 

 

为什么 我配置了 antMatchers("/oauth/token").permitAll(), 但是没有生效 

这里 AuthorizationServerSecurityConfiguration 的限定的是 "/oauth/token", "/oauth/token_key", "/oauth/check_token" 
WebSecurityConfigurer 限定的是 其他的业务上的大部分的请求, 我这里添加了一个 /oauth/token -> permitAll 但是没有生效 

这里需要 回溯一下 FilterSecurityInterceptor 的这一系列的整个流程 

这里 正向剖析一下这个流程, 反向回溯的过程 着实开销不小 

 

WebSecurityConfiguration.springSecurityFilterChain 创建了一个 FilterChainProxy, 注册于 spring 容器中 

并且添加到了 tomcat 的 applicationFilterChain, 因此和具体的 http 请求处理 的 TokenEndpoint 处理的过程关联起来 

向 tomcat 的 applicationFilterChain 添加 filterDef 的地方来自于 SecurityFilterAutoConfiguration.securityFilterChainRegistration, 增加了一个 DelegatingFilterProxyRegistrationBean 

 

 

这里 FilterChainProxy 内部组合了三个 filterChain, 然后根据 request 获取实际处理的 filterChain, 构建 filter 责任链来处理 请求, 构建了一个 VirtualFilterChain, 在 tomcat 的 filter 责任链的基础上, 又嵌套了一层 filter责任链 

这里 我们的 /oauth/token, 匹配到了 第二个 filterChain, oauth/token 对应的策略为 fullyAuthenticated 

第一个 filterChain 对应的是 WebSecurityConfigurer 中 构建的一个 ignoring 的策略 

第二个 filterChain 对应的是 AuthorizationServerSecurityConfiguration 构建的一个 filterChain , 其中 /oauth/token 对应的策略为 fullyAuthenticated 

第三个 filterChain 对应的是 业务系统中自定义的 WebSecurityConfigurer 构建的一个 filterChain, 其中 /oauth/token 对应的策略为 permitAll 

构建这个 FilterChainProxy 的过程是在 WebSecurity. performBuild 的过程中, 先添加的 ignoring, 然后再添加的 各个 WebSecurityConfigurer 构建的 securityFilterChainBuilder 

55a57b15ef0044649d9feefb3b532e9b.png

 

 

梳理一下构建 FilterChainProxy 的整个流程 

  1. WebSecurityConfiguration.springSecurityFilterChain 中创建了 WebSecurity, WebSecurity.build 创建了 tomcat 这边接入的 FilterChainProxy 
  2. 这个 WebSecurity 组合了 applicationContext 中的 SecurityConfigurer, SecurityConfigurer 生成一个 HttpSecurity, HttpSecurity.build 会创建一个 DefaultFilterChain, 对应于 FilterChainProxy 组合的多个 DefaultFilterChain

 

  1. 在 WebWecurity init 的过程中, 各个 SecurityConfigurer 构建了相应的 HttpSecurity 然后注册到 WebWecurity 中, 这个过程会回调 SecurityConfigurer.configure(HttpSecurity http) 
  2. 在 WebWecurity configure 的过程中, 会回调各个 SecurityConfigurer 的 configure(WebSecurity web) 
  3. 在 WebWecurity performBuild 的过程中, 会构建 FilterChainProxy, 它组合了一系列的 DefaultFilterChain, 这个过程参见 WebWecurity.performBuild, 具体的方式是 组合 WebWecurity 下面的 HttpSecurity 来构建 DefaultFilterChain

            3.1 HttpSecurity performBuild 的过程中, 是直接根据已经采集的 filter 列表, 构建 DefaultFilterChain

            3.2 HttpSecurity  的已经采集的 filter 是来自于 HttpSecurity 下面的 configurers 在 init, configure 的过程中处理进去的 

            3.3 HttpSecurity 下面的各个 configurers 来自于 SecurityConfigurer 的 configure(HttpSecurity http) 的过程中的相关业务处理, 诸如 '.authorizeRequests().antMatchers("/token/**", "/actuator/**", "/sso/**", "/test/**", "/oauth/token").permitAll()', '.formLogin().loginPage("/token/login").loginProcessingUrl("/token/form")', ".authorizeRequests()" 的相关是配置的就是请求认证的相关配置 

 

 

以上一系列流程主要的目的是 为 FilterSecurityInterceptor 中的 this.obtainSecurityMetadataSource().getAttributes(object) 服务 

  1. 请求来了之后, 走 FilterChainProxy, FilterChainProxy  选择当前 request 需要使用的 DefaultFilterChain 
  2. DefaultFilterChain 中组合了一个责任链, 其中 FilterSecurityInterceptor 包含了如下认证步骤, 也是认证的相关问题核心需要关注的地方 

引用自 "20220321_01 配置了 security.oauth2.client.ignore-urls 但是访问配置的服务依然 "用户信息已过期或已更新,请重新登录" 问题"

3. 具体的 ignore-urls 的业务层面的使用

主要是在 FilterSecurityInterceptor, 这里面我们核心需要关注几个部分

    3.1 this.obtainSecurityMetadataSource().getAttributes(object) 根据当前 request 获取认证属性

    3.2 Authentication authenticated = authenticateIfRequired(); 根据请求头里面拿到的 token, 访问 auth 服务, 获取用户以及关联信息, 封装 Authentication

    3.3 accessDecisionManager.decide 结合 认证属性 和 Authentication 来判断是否有权限  

 

另外还有一个细节是 可以看到拿到的 filterChain, 相比于我们 SecurityConfigurer 的 configure(HttpSecurity http) 中配置的处理会多一些

这部分 filter 来自于 SecurityConfigurer.getHttp 的过程中初始化的一部分 Configurer, 诸如 AnonymousAuthenticationFilter, ExceptionTranslationFilter 等等 

 

 

getForObject 的时候 查询字符串 未拼接 到 uri 中

这个是 对于 getForObject 的 uriVariables 的理解存在问题 

这里的 uriVariables 对应于 uri 中的一部分模板, 而不是 我们常规理解的 get 请求中交互的参数 

e6c36ff20673464d8a4d0ed2d6fdff3f.png

 

 

完 

 

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/270783.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

excel中去除公式,仅保留值

1.单个单元格去除公式 双击单元格&#xff0c;按F9. 2.批量去除公式 选中列然后复制&#xff0c;选择性粘贴&#xff0c;选值粘贴

【每日一题】1976. 到达目的地的方案数-2024.3.5

题目: 1976. 到达目的地的方案数 你在一个城市里,城市由 n 个路口组成,路口编号为 0 到 n - 1 ,某些路口之间有 双向 道路。输入保证你可以从任意路口出发到达其他任意路口,且任意两个路口之间最多有一条路。 给你一个整数 n 和二维整数数组 roads ,其中 roads[i] = […

PCL官方demo的编译使用教程

写在前面 本文内容 PCL官方demo的编译使用教程&#xff1b; 后续对PCL demo中比较常用的算法、应用demo会出专门的博客讲解、拓展&#xff1b; 更多点云基础、算法相关内容请关注专栏&#xff1a; 点云处理基础 点云配准(PointCloud Registration) Open3D点云处理 PCL点云处理 …

青少年如何从零开始学习Python编程?有它就够了!

文章目录 写在前面青少年为什么要学习编程 推荐图书图书特色内容简介 推荐理由粉丝福利写在最后 写在前面 本期博主给大家带来一本非常适合青少年学习编程的图书&#xff0c;快来看看吧~ 青少年为什么要学习编程 青少年学习编程&#xff0c;就好比在他们年轻时就开始掌握一种…

Vulnhub靶机:Bellatrix

一、介绍 运行环境&#xff1a;Virtualbox 攻击机&#xff1a;kali&#xff08;10.0.2.4&#xff09; 靶机&#xff1a;Bellatrix&#xff08;10.0.2.9&#xff09; 目标&#xff1a;获取靶机root权限和flag 靶机下载地址&#xff1a;https://www.vulnhub.com/entry/hogwa…

Sy2 Linux系统登录及用户管理

实验环境&#xff1a; 宿主机为win11 Vmware workstaion 17 目标机的OS&#xff1a; Ubuntu 2004 网络&#xff1a;NAT 获取地址&#xff1a;192.168.248.131/24 DNS,DHCP&#xff1a;192.168.248.2 第一章ppt的命令操作&#xff08;部分&#xff09; S1、执行whoami、who…

极狐GitLab 如何设置 Markdown 中的图片大小

GitLab 是一个全球知名的一体化 DevOps 平台&#xff0c;很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab 是 GitLab 在中国的发行版&#xff0c;专门为中国程序员服务。可以一键式部署极狐GitLab。 使用极狐GitLab 进行代码托管或者 CI/CD&#xff0c;都避免不了…

Vue3.0里为什么要用 Proxy API 替代 defineProperty API ?

文章目录 Object.defineProperty小结 proxy总结有需要的请私信博主&#xff0c;还请麻烦给个关注&#xff0c;博主不定期更新&#xff0c;或许能够有所帮助&#xff01;&#xff01;请关注公众号 Object.defineProperty 定义&#xff1a;Object.defineProperty() 方法会直接在一…

docker部署aria2-pro

前言 我平时有一些下载视频和一些资源文件的需求&#xff0c;有时候需要离线下载&#xff0c;也要速度比较快的方式 之前我是用家里的玩客云绝育之后不再写盘当下载机用的&#xff0c;但是限制很多 我发现了aria2 这个下载器非常适合我&#xff0c;而有个大佬又在原来的基础…

php常见的45个漏洞及解决方案

[TOC]&#xff08;太多了&#xff0c;目录只列出最重要的几个&#xff0c;剩下的同学们自己翻&#xff09; PHP作为一种广泛应用的服务器端脚本语言&#xff0c;在历史上曾曝出过多种安全漏洞。以下是一些PHP漏洞的类别及其简要解释&#xff0c;以及如何解决这些问题&#xff1…

一次一对一服务引起的沉思和笑话(微信号Stefan)

前情提要 客户需求&#xff1a; 分析页面代码和接口请求协议和参数需求&#xff0c;将人工下载视频怎么获得最终的视频链接&#xff0c;这一逻辑清晰的展示并讲解清除。我询问了是否需要成品爬虫&#xff0c;他说代码他自己能搞定。 我给的价格选择&#xff1a; 第一种、首…

flowable的java class task,也叫服务任务

源码地址12级程序猿-新年正当红/flowable-ui和服务任务 启动flowable-ui-app 浏览器输入下面的地址 http://localhost:8080/flowable-ui/#/ 在服务任务这里设置java类的路径 com.dmg.flowabledemo.task.MyServiceTask 当请假任务完成之后&#xff0c;自动触发这个服务任务…

Java精品项目--第5期基于SpringBoot的高速收费系统的设计分析与实现

项目使用技术栈 SpringBootMavenShiroMySQLMybatis-PlusJavaJDK1.8HTML 系统介绍 项目截图

工商全程无纸化应用与CA认证结合方案

一、引言 随着互联网技术的飞速发展&#xff0c;政务服务正逐步向数字化、网络化、智能化转型。为响应国家关于推进“互联网政务服务”的号召&#xff0c;XX工商管理局致力于实现工商企业网上注册全程无纸化&#xff0c;提升政务服务的效率与质量。本方案旨在结合陕西CA认证中…

PowerBI怎么修改数据库密码

第一步&#xff1a;点击转换数据 第二步&#xff1a;点击数据源设置 第三步&#xff1a;点击编辑权限 第四步&#xff1a;点击编辑 第五步&#xff1a;输入正要修改的密码就可以了

半导体行业案例:Jira与龙智插件助力某半导体企业实现精益项目管理

近日&#xff0c;龙智Atlassian技术团队收到了国内一家大型半导体企业的感谢信。龙智团队提供的半导体行业项目管理解决方案和服务受到了客户的好评&#xff1a; 在龙智团队的支持下&#xff0c;我们的业务取得了喜人的成果和进步。龙智公司的专业服务和产品&#xff0c;是我们…

解密Lawnchair:打造个性化极致的Android桌面体验

解密Lawnchair&#xff1a;打造个性化极致的Android桌面体验 1. 简介 Lawnchair是一款知名的Android桌面定制工具&#xff0c;旨在为用户提供个性化极致的桌面体验。作为一个开源项目&#xff0c;Lawnchair融合了简洁、灵活和强大的特点&#xff0c;让用户能够自由定制其Andro…

1.5如何缓解图像分类任务中训练数据不足带来的问题?

1.5 图像数据不足时的处理方法 场景描述 在机器学习中&#xff0c;绝大部分模型都需要大量的数据进行训练和学习(包括有监督学习和无监督学习)&#xff0c;然而在实际应用中经常会遇到训练数据不足的问题。 比如图像分类&#xff0c;作为计算机视觉最基本的任务之一&#xff0…

必看——GlobalSign代码签名证书怎么申请?

一、GlobalSign代码签名证书申请流程 第一部分&#xff1a;选择适合的证书类型 1. 访问官方渠道&#xff1a; 首先访问JoySSL官方网站页面&#xff0c;浏览并了解不同类型的代码签名证书选项&#xff0c;包括但不限于标准代码签名证书、扩展验证&#xff08;EV&#xff09;代码…

AIOps常见问题

AIOps的自动化通常指什么&#xff1f; AIOps 平台的自动化一般包括以下几个方面&#xff1a; 数据收集和整合&#xff1a;AIOps 平台可以从多个 IT 基础架构组件、应用需求与性能监视工具以及服务工单系统等数据源中收集并整合运维数据&#xff0c;形成一个全面的数据平台。数…