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

基于Spring Security 6的OAuth2 系列之八 - 授权服务器--Spring Authrization Server的基本原理

之所以想写这一系列,是因为之前工作过程中使用Spring Security OAuth2搭建了网关和授权服务器,但当时基于spring-boot 2.3.x,其默认的Spring Security是5.3.x。之后新项目升级到了spring-boot 3.3.0,结果一看Spring Security也升级为6.3.0。无论是Spring Security的风格和以及OAuth2都做了较大改动,里面甚至将授权服务器模块都移除了,导致在配置同样功能时,花费了些时间研究新版本的底层原理,这里将一些学习经验分享给大家。

注意由于框架不同版本改造会有些使用的不同,因此本次系列中使用基本框架是 spring-boo-3.3.0(默认引入的Spring Security是6.3.0),JDK版本使用的是19,本系列OAuth2的代码采用Spring Security6.3.0框架,所有代码都在oauth2-study项目上:https://github.com/forever1986/oauth2-study.git

目录

  • 1 关键的类
    • 1.1 Authentication
    • 1.2 AuthenticationConverter
    • 1.3 AuthenticationProvider
  • 2 授权码模式的底层原理
  • 3 授权码模式整体流程图
  • 4 关键的Filter过滤器
    • 4.1 OAuth2AuthorizationEndpointFilter(授权码code请求处理)
    • 4.2 OAuth2TokenEndpointFilter(返回token)
    • 4.3 OAuth2ClientAuthenticationFilter(客户端认证)

前面我们了解授权服务器的实现以及自定义客户端、自定义授权页面,也窥探了其中部分原理。这一章,我们通过授权码模式下,分析一下Spring Authrization Server的基本原理,同时对其中一些关键的Filter过滤器列出来,对后续实现功能会有帮助。我们知道Spring Authrization Server也是基于Spring Security 6基础上实现的,因此其关键功能都在其过滤器上面。下图红色框框的是Spring Authrization Server新增的过滤器,我们挑一些关键的解释一下

在这里插入图片描述

1 关键的类

在介绍关键的过滤器之前,有几个类需要先说明一下其作用,对后面阅读源码有很好的理解。

1.1 Authentication

Authentication其实是Spring Security的接口,主要就是封装认证信息,用于上下文传输,而在Spring Authrization Server中,有几个实现类比较重要:

  • OAuth2AuthorizationCodeRequestAuthenticationToken:在授权码模式下,获取授权码时候封装的信息
  • OAuth2AuthorizationConsentAuthenticationToken:在授权码模式下,跳转授权界面时,封装所需的信息
  • OAuth2AuthorizationCodeAuthenticationToken:在请求token时,封装所需的信息
  • OAuth2TokenExchangeAuthenticationToken:在交换token请求下,封装所需的信息
  • OAuth2RefreshTokenAuthenticationToken:在刷新token请求下,封装所需的信息

在这里插入图片描述

1.2 AuthenticationConverter

AuthenticationConverter是一个request参数转换为Authentication的一个转换器,其中有几个实现类比较重要

  • OAuth2AuthorizationCodeRequestAuthenticationConverter:在请求授权码时,将request的参数都封装为Authentication
  • OAuth2AuthorizationConsentAuthenticationConverter:在请求授权码时,点击授权页面的确认后,将request的参数都封装为Authentication
  • OAuth2AuthorizationCodeAuthenticationConverter:在请求token时,将request的参数都封装为Authentication
  • OAuth2TokenExchangeAuthenticationConverter:在交换token时,将request的参数都封装为Authentication
  • OAuth2RefreshTokenAuthenticationConverter:在刷新token时,将request的参数都封装为Authentication

在这里插入图片描述

1.3 AuthenticationProvider

AuthenticationProvider本身是Spring Security的接口,主要是用于验证结果,比如用户名密码登录等,这里Spring Authrization Server通过实现不同的AuthenticationProvider做不同验证,以下几个实现类比较重要:

  • OAuth2AuthorizationCodeRequestAuthenticationProvider:主要用于授权码模式下,客户端的验证
  • OAuth2AuthorizationConsentAuthenticationProvider:授权页面点击确认之后,客户端验证
  • OAuth2AuthorizationCodeAuthenticationProvider:获取token接口时,客户端验证
  • OAuth2TokenExchangeAuthenticationProvider:交换token接口时,客户端验证
  • OAuth2RefreshTokenAuthenticationProvider:请求刷新token接口时,客户端验证

在这里插入图片描述

2 授权码模式的底层原理

1)我们从《系列之四-客户端–oauth2-client底层原理》中可知,客户端会访问/oauth2/authorize接口,这时候会有先到达OAuth2AuthorizationEndpointFilter过滤器,但是由于未登录,因此会被认定没有权限,不做处理,继续走过滤器链。

在这里插入图片描述

在这里插入图片描述

2)接着,请求会接着跳转到AuthorizationFilter过滤器(这是Spring Security的过滤器,做认证判断的),这时候会报AccessDeniedException异常,并由LoginUrlAuthenticationEntryPoint处理,跳转到Spring Security的登录界面

在这里插入图片描述

3)出现登录界面,进行登录之后,会继续请求/oauth2/authorize接口,这时候会被OAuth2AuthorizationEndpointFilter拦截,我们再看看OAuth2AuthorizationEndpointFilter的doFilterInternal方法

在这里插入图片描述

  • 第一步:判断URI是否符合/oauth2/authorize
  • 第二步:判断客户端信息是否符合要求
  • 第三步:判断是否已经登录,没有登录,则由其它过滤器跳转到登录界面
  • 第四步:判断是否已经授权,没有授权则跳转到登录界面
  • 第五步:前面4步都没问题,则返回授权的code

下面我们将详细的源码调用过程列出来:

在这里插入图片描述

4)返回授权码给客户的之后,客户端会继续请求http://oauth-server:9000/oauth2/token获取token,而授权服务器的token由OAuth2TokenEndpointFilter过滤器处理

OAuth2TokenEndpointFilter是拦截"/oauth2/token"获取token请求,通过将request的参数封装为OAuth2AuthorizationCodeAuthenticationToken,然后调用OAuth2AuthorizationCodeAuthenticationProvider验证并生成token,通过后调用OAuth2AccessTokenResponseAuthenticationSuccessHandler返回token

在这里插入图片描述

3 授权码模式整体流程图

在这里插入图片描述

4 关键的Filter过滤器

从上面的整体流程,我们知道一些关键的Filter过滤器,这里罗列出来,后续讲解授权码其它功能时,会经常提到。

4.1 OAuth2AuthorizationEndpointFilter(授权码code请求处理)

在《系列之五 - 授权服务器–开篇》和本系列中分析过该过滤器。该过滤器专门处理/oauth2/authorize接口,在授权码模式下,该接口就是用于跳转到授权界面以及返回授权码的作用

在这里插入图片描述

4.2 OAuth2TokenEndpointFilter(返回token)

OAuth2TokenEndpointFilter是拦截"/oauth2/token"获取token请求,通过将request的参数封装为OAuth2AuthorizationCodeAuthenticationToken,然后调用OAuth2AuthorizationCodeAuthenticationProvider验证并生成token,通过后调用OAuth2AccessTokenResponseAuthenticationSuccessHandler返回token

在这里插入图片描述

4.3 OAuth2ClientAuthenticationFilter(客户端认证)

OAuth2ClientAuthenticationFilter主要是用于客户端认证,包括通过client_secret_basic、client_secret_post、client_secret_jwt、private_key_jwt、none、tls_client_auth和self_signed_tls_client_auth等不同认证方式。因此增加改拦截器用于客户端认证,其逻辑流程和OAuth2AuthorizationEndpointFilter前半部分有很大的相似,都是使用AuthenticationConverter转换参数,然后AuthenticationProvider进行验证。这块具体会在《系列之十五 - 高级特性–客户端认证方式》中详细说明。

结语:本章我们对Spring Authrization Server如何实现授权码模式以及自定义客户端信息进行源码解析,并了解了几个关键的Filter过滤器。有了这个基础,对接下来我们实现更为高级的授权服务器功能,并了解实现原理就变得更为容易。

相关文章:

基于Spring Security 6的OAuth2 系列之八 - 授权服务器--Spring Authrization Server的基本原理

之所以想写这一系列,是因为之前工作过程中使用Spring Security OAuth2搭建了网关和授权服务器,但当时基于spring-boot 2.3.x,其默认的Spring Security是5.3.x。之后新项目升级到了spring-boot 3.3.0,结果一看Spring Security也升级…...

蓝桥与力扣刷题(234 回文链表)

题目:给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false 。 示例 1: 输入:head [1,2,2,1] 输出:true示例 2: 输入&…...

Google C++ Style / 谷歌C++开源风格

文章目录 前言1. 头文件1.1 自给自足的头文件1.2 #define 防护符1.3 导入你的依赖1.4 前向声明1.5 内联函数1.6 #include 的路径及顺序 2. 作用域2.1 命名空间2.2 内部链接2.3 非成员函数、静态成员函数和全局函数2.4 局部变量2.5 静态和全局变量2.6 thread_local 变量 3. 类3.…...

Windows图形界面(GUI)-QT-C/C++ - QT Tab Widget

公开视频 -> 链接点击跳转公开课程博客首页 -> ​​​链接点击跳转博客主页 目录 一、概述 1.1 什么是 QTabWidget? 1.2 使用场景 二、常见样式 2.1 选项卡式界面 2.2 动态添加和删除选项卡 2.3 自定义选项卡标题和图标 三、属性设置 3.1 添加页面&…...

【大数据技术】教程05:本机DataGrip远程连接虚拟机MySQL/Hive

本机DataGrip远程连接虚拟机MySQL/Hive datagrip-2024.3.4VMware Workstation Pro 16CentOS-Stream-10-latest-x86_64-dvd1.iso写在前面 本文主要介绍如何使用本机的DataGrip连接虚拟机的MySQL数据库和Hive数据库,提高编程效率。 安装DataGrip 请按照以下步骤安装DataGrip软…...

C++:结构体和类

在之前的博客中已经讲过了C语言中的结构体概念了,重复的内容在这儿就不赘述了。C中的结构体在C语言的基础上还有些补充,在这里说明一下,顺便简单地讲一下类的概念。 一、成员函数 结构体类型声明的关键字是 struct ,在C中结构体…...

MATLAB的数据类型和各类数据类型转化示例

一、MATLAB的数据类型 在MATLAB中 ,数据类型是非常重要的概念,因为它们决定了如何存储和操作数据。MATLAB支持数值型、字符型、字符串型、逻辑型、结构体、单元数组、数组和矩阵等多种数据类型。MATLAB 是一种动态类型语言,这意味着变量的数…...

UE求职Demo开发日志#19 给物品找图标,实现装备增加属性,背包栏UI显示装备

1 将用到的图标找好,放一起 DataTable里对应好图标 测试一下能正确获取: 2 装备增强属性思路 给FMyItemInfo添加一个枚举变量记录类型(物品,道具,装备,饰品,武器)--> 扩展DataT…...

C++泛型编程指南09 类模板实现和使用友元

文章目录 第2章 类模板 Stack 的实现2.1 类模板 Stack 的实现 (Implementation of Class Template Stack)2.1.1 声明类模板 (Declaration of Class Templates)2.1.2 成员函数实现 (Implementation of Member Functions) 2.2 使用类模板 Stack脚注改进后的叙述总结脚注2.3 类模板…...

使用MATLAB进行雷达数据采集可视化

本文使用轮趣科技N10雷达,需要源码可在后台私信或者资源自取 1. 项目概述 本项目旨在通过 MATLAB 读取 N10 激光雷达 的数据,并进行 实时 3D 点云可视化。数据通过 串口 传输,并经过解析后转换为 三维坐标点,最终使用 pcplayer 进…...

【Elasticsearch】allow_no_indices

- **allow_no_indices 参数的作用**: 该参数用于控制当请求的目标索引(通过通配符、别名或 _all 指定)不存在或已关闭时,Elasticsearch 的行为。 - **默认行为**: 如果未显式设置该参数,默认值为 …...

54【ip+端口+根目录通信】

上节课讲到,根目录起到定位作用,比如我们搭建一个php网站后,注册系统是由根目录的register.php文件执行,那么我们给这个根目录绑定域名https://127.0.0.1,当我们浏览器访问https://127.0.0.1/register.php时&#xff0…...

python算法和数据结构刷题[3]:哈希表、滑动窗口、双指针、回溯算法、贪心算法

回溯算法 「所有可能的结果」,而不是「结果的个数」,一般情况下,我们就知道需要暴力搜索所有的可行解了,可以用「回溯法」。 回溯算法关键在于:不合适就退回上一步。在回溯算法中,递归用于深入到所有可能的分支&…...

DeepSeek横空出世,AI格局或将改写?

引言 这几天,国产AI大模型DeepSeek R1,一飞冲天,在全球AI圈持续引爆热度,DeepSeek R1 已经是世界上最先进的 AI 模型之一,可与 OpenAI 的新 o1 和 Meta 的 Llama AI 模型相媲美。 DeepSeek-V3模型发布后,在…...

聚簇索引、哈希索引、覆盖索引、索引分类、最左前缀原则、判断索引使用情况、索引失效条件、优化查询性能

聚簇索引 聚簇索引像一本按目录排版的书,用空间换时间,适合读多写少的场景。设计数据库时,主键的选择(如自增ID vs 随机UUID)会直接影响聚簇索引的性能。 什么是聚簇索引? 数据即索引:聚簇索引…...

OpenAI 实战进阶教程 - 第四节: 结合 Web 服务:构建 Flask API 网关

目标 学习将 OpenAI 接入 Web 应用,构建交互式 API 网关理解 Flask 框架的基本用法实现 GPT 模型的 API 集成并返回结果 内容与实操 一、环境准备 安装必要依赖: 打开终端或命令行,执行以下命令安装 Flask 和 OpenAI SDK: pip i…...

python的pre-commit库的使用

在软件开发过程中,保持代码的一致性和高质量是非常重要的。pre-commit 是一个强大的工具,它可以帮助我们在提交代码到版本控制系统(如 Git)之前自动运行一系列的代码检查和格式化操作。通过这种方式,我们可以确保每次提…...

架构技能(四):需求分析

需求分析,即分析需求,分析软件用户需要解决的问题。 需求分析的下一环节是软件的整体架构设计,需求是输入,架构是输出,需求决定了架构。 决定架构的是软件的所有需求吗?肯定不是,真正决定架构…...

Linux环境下的Java项目部署技巧:安装 Nginx

Nginx 的简介: Nginx 是一个高性能的 HTTP 和反向代理服务器,也是一个 IMAP / POP3 / SMTP 代理服务器。它可以作为网站静态资源的 web 服务器,也可以作为其他应用服务器的反向代理服务器。同时, Nginx 还具有负载均衡的功能。 N…...

前端 Vue 性能提升策略

一、引言 前端性能优化是确保 Web 应用快速响应和流畅用户体验的关键。对于使用 Vue.js 构建的应用,性能优化不仅涉及通用的前端技术,还包括针对 Vue 特性的特定优化措施。本文将从多个方面探讨如何全面提升前端和 Vue 应用的性能。 二、前端性能优化基础 1. 减少初始加载…...

在软件开发中正确使用MySQL日期时间类型的深度解析

在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...

day52 ResNet18 CBAM

在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...

Oracle查询表空间大小

1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...

练习(含atoi的模拟实现,自定义类型等练习)

一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...

java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别

UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》

在注意力分散、内容高度同质化的时代,情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现,消费者对内容的“有感”程度,正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中&#xff0…...

MVC 数据库

MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...

Spring Boot面试题精选汇总

🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...

JDK 17 新特性

#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持,不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的&#xff…...

用docker来安装部署freeswitch记录

今天刚才测试一个callcenter的项目,所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...