【深入浅出Spring原理及实战】「开发实战系列」OAuth2的技术体系架构和开发概览

news2024/11/18 1:51:58

背景介绍

主要实现 OAuth2的三种授权模式:密码模式、客户端模式和授权码模式,包括展示授权服务器、资源服务器、客户端等几种角色的交互,以及JWT的整合。并且每个实例都提供两个代码版本:一个是基于旧的 Spring Security OAuth2 组件;一个是基于新的 Spring Authorization Server 组件。

注意的是 password 模式由于 OAuth2.1 不推荐使用所以只能提供旧的组件代码版本,具体请参见 https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-02

OAuth 授权体系设计之初主要是为了解决第三方应用登录和授权的问题,但由于其严格规范的流程定义,广泛的授权通用性,且与具体技术平台无关等诸多优点,逐渐发展成为认证和授权领域的主流技术规范。但其实 OAuth2 规范归纳起来并不复杂,就四种主要的授权模式和五种角色。

OAuth2 体系结构

OAuth授权体系设计之初主要是为了解决第三方应用登录和授权的问题,但由于其严格规范的流程定义,广泛的授权通用性,且与具体技术平台无关等诸多优点,逐渐发展成为认证和授权领域的主流技术规范。但其实 OAuth2 规范归纳起来并不复杂,就四种主要的授权模式和五种角色。

OAuth2.0 的四种授权模式

  • 授权码模式(authorization code)

  • 简化模式(implicit)

  • 密码模式(resource owner password credentials)

  • 客户端模式(client credentials)

  • 密码模式常用于外部服务的认证、授权和鉴权,客户端模式常用于内部服务的认证、授权和鉴权和开放平台应用的授权,授权码模式常用于社会化登录和SSO,因此OAuth2.0 可作为完整的统一身份认证和授权方案。

  • 四种模式都有其特定的使用场景,但是在落地过程中,也可以根据实际情况自行取舍。为了方便接下来的介绍,基于图像的物品分类系统(IBCS,Image-Based Classification System)、相册预览系统(PAPS,Photo Album Preview System)。

授权码模式 vs 密码模式 vs 客户端模式

授权码模式

先来看授权码模式和密码模式之间的比较,

授权码模式是OAuth2体系安全性最高的模式,密码模式与其相比,主要差别是少了一层用户确认授权的动作,缺乏这一动作就导致在授权阶段,用户需要把用户名密码告知客户端,造成潜在的密码泄露风险。

比较项授权码模式密码模式备注
适用场景不可信/第三方认证和授权、可信/内部服务认证和授权可信/内部服务认证和授权
开发难度较为复杂相对简单
安全性最高只要不运用于不可信/第三方场景则同样安全
使用场景分析
可信/内部服务场景

同一套OAuth2体系的应用和服务,且这些应用和服务是由相同的或者相互信任的团队开发,也可以称作第一方应用。

微服务架构下的 B2C 商城系统,基本组成有前端 H5、无线端 APP、API 网关、认证授权服务、订单服务、商品服务等,由于上述所有组成部分都同属于一套OAuth2 体系,且都由相同团队开发,那么他们全都归属于可信/内部服务场景。

第三方/不可信应用
  • 网关属于安全边界,网关以内的认证授权服务、订单服务、商品服务属于内部服务,而前端H5、无线端APP则属于外部应用,如果这些外部应用是其他团队开发,我们也可以定义它们为第三方应用。这样就以网关为边界,划分出了内部服务和外部服务。

  • 电商系统的前端H5、无线端APP在认证和授权阶段,采用授权码模式和采用密码模式,授权码模式有一层用户确认授权的动作,从而避免泄露用户名和密码给第三方应用,除此之外,两者之间几乎提供了相同的安全流程。

以此来看,在上述条件的限定下,两种模式的安全性打平了。遵循“简化原则”,采用密码模式即可。

授权码模式

授权码模式主要的应用场景,是在第三方/不可信应用的登录和授权,主要解决在不泄露用户密码的情况下如何安全授权某个应用向另一个应用提供用户资源的问题,举例来说,某第三方应用(客户端)需要获得用户(资源所有者)在另一个不可信应用(资源服务器)上的该用户的用户数据(资源)的场景就特别适合采用授权码模式。

综上,选择授权码模式还是密码模式,具体要根据业务场景来确定,其中的关键决策点是应用或服务之间是否互相信任。

客户端模式

采用何种授权模式?

首先要明确资源是什么,其次该资源是受保护的,最后资源归谁所有,谁就是资源所有者。明确资源所有者的含义后,再根据前文的分析,毫无疑问:如果PAPS的demo应用是第三方的不可信应用,则应该采用授权码模式;如果是第一方可信应用,则可以采用密码模式,当然不怕麻烦也可以用授权码模式。

是密码模式的最精简架构层次,在实际开发中可以此作为基础进行扩展。密码模式涉及到五种主要角色,另外还有一个用户代理/浏览器角色。

OAuth2.0 的五种主要的角色:

  • 用户代理/浏览器 User Agent
  • 客户端 Client:一般指第三方应用程序,例如用QQ登录豆瓣网站,这里的豆瓣网就是 Client;但在微服务体系里,Client通常是服务本身,如 APP 端的注册登录服务;
  • 资源所有者 Resource Owner:一般指用户,例如用 QQ 登录豆瓣网站,这里的所有者便是用户;但在微服务体系里,资源所有者的指向不是一成不变的,要具体分析;
  • 资源服务器 Resource Server (受保护资源):一般指资源所有者授权存放用户资源的服务器,例如用 QQ 登录豆瓣网站,这里的 QQ 就是资源服务器;但在微服务体系里,服务提供者本身便是资源服务器;
  • 授权服务器 Authorization Server:一般是指服务提供商的授权服务,例如用 QQ 登录豆瓣网站,这里的 QQ 便是授权服务器;类似地,在微服务体系里,IDP 服务便是授权服务器。

整个流程分为两个阶段:

第一阶段:认证授权阶段

  1. 前端页面将用户输入的用户名和密码,发送给客户端(process-service);
  2. 客户端(process-service)将用户输入的用户名和密码,连同 client_id + client_secret (由idp分配)一起发送到idp以请求令牌,如果 idp 约定了 scope 则还需要带上 scope 参数;
  3. idp 首先验证 client_id + client_secret 的合法性,再检查 scope 是否无误,最后验证用户名和密码是否正确,正确则生成 token。这一步也叫“认证”;
  4. idp 返回认证结果给客户端,认证通过返回 token,认证失败返回 401。如果认证成功则此步骤也叫“授权”;
  5. 客户端收到 token 后进行暂存,并创建对应的 session;
  6. 客户端颁发 cookie 给用户代理/浏览器。

至此,认证授权阶段完成。其中步骤 5-6 也有其他会话方案,比如REST型应用可能会将 token 存储在浏览器端,但 session/cookie 方案无疑是最稳妥的选择。

在Web 应用中\用户登录过程。

第二阶段:授权后请求资源阶段

  1. 用户通过用户代理,访问“我的资源”页面,用户代理携带 cookie 向客户端(process—service)发起请求;
  2. 客户端通过session找到对应的 token,携带此 token 向资源服务器(resource-service)发起请求;
  3. 资源服务器(resource-service)向 idp 请求验证 token 有效性;
  4. idp 校验 token 有效性,再根据 scope 判断客户端(process-service)是否有权限调用此 API,最后返回校验结果给资源服务器。这一步也叫“鉴权”;
  5. 资源服务器根据 idp 检验结果(true/false 或其他等效手段)决定是否返回用户相册数据给客户端。如果 token 校验失败则返回 401 给客户端,如果 scope 检查不通过则返回 403。这一步也叫“权限控制”。

至此,授权后请求资源阶段完成。

scope 参数是用来约束客户端的权限的,跟用户权限(authorities)是不同的。比如可以在 idp 中利用scope参数约束某客户端只能发起读(GET)型请求,或只能调用指定的几个 API 等,具体业务逻辑自行编写。

密码模式的微服务架构层次和主要流程

  1. 微服务场景下,增加了一个网关,网关实际上是一个反向代理,将用户的请求转发到内部服务器。类似地,微服务场景下也分为两个阶段,而且第一阶段没什么变化,主要不同在于第二阶段:

  2. 用户通过用户代理访问“我的资源”页面,用户代理携带cookie向客户端(process—service)发起请求;

  3. 客户端通过session找到对应的token,携带此token向网关发起对资源服务器(resource-service)的请求;

  4. 网关截取token连同本次请求的细节,一并向idp请求校验;

  5. idp 校验 token 有效性,再根据 scope 和请求细节判断客户端(process-service)是否有权限调用此 API,最后返回校验结果给网关。

    • 如果校验全部通过,idp 生成 JWT 并返回给网关;如果 token 校验失败返回 401;如果 scope 检查不通过则返回 403;
    • 如果校验通过,网关将得到 JWT,携带此 JWT 转发请求到资源服务器;
  6. 资源服务器解析 JWT 得到用户信息,查询用户相册数据后返回给网关;

  7. 网关将用户数据返回给客户端。

  8. 网关截取 token 后向 idp 请求校验;

  9. idp 校验 token 有效性,通过校验则根据 token 查询用户信息和 scope,生成 JWT 返回给网关;如果不通过则返回 401;

  10. 网关得到 JWT,解析后根据 scope 判断客户端是否有权限调用此 API,如有则携带 JWT 转发请求到资源服务器,否则返回 403 给客户端。

客户端权限检查放到网关,则网关要维护 scope 和客户端权限的逻辑。

授权码模式的微服务架构层次和主要流程

授权码模式在微服务场景下的架构层次和主要流程:

整个流程分为两个阶段:

第一阶段:认证授权阶段
  1. 用户在用户代理处点击登录按钮,或请求授权登录按钮,此操作将访问客户端的某个 URI;

  2. 客户端(process-service)将用户导向 idp 提供的认证授权页面,并在页面 ULR 参数中携带 client_id,response_type=code,redirect_uri(可选),scope(可选),state(可选);

  3. 用户通过用户代理,在 idp 的认证授权页面选择是否给予授权,如用户未登录,则需要先登录后再操作;

  4. 用户给予授权,idp 将用户导向 redirect_uri 指定的页面,并附加授权码(code);如果未指定 redirect_uri,则导向发起该请求时的 URI,同时附加授权码(code);

  5. 客户端收到授权码(code),向 idp 发起令牌申请,同时附上 client_id(必填) + client_secret(必填) + state(如有) + scope(如有)。注意这一步是客户端在后台发起的,用户层面无法感知;

  6. idp 收到请求后,先核对 client_id + client_secret + scope(如有)是否无误,然后校验授权码(code),全部正确后颁发 token 给客户端。

第二阶段:授权后请求资源阶段
  1. 用户在用户代理处点击登录按钮或请求授权登录按钮后,通知客户端(process-service),客户端收到通知后返回重定向的指示,以及 scope(可选),state(可选)等;
  2. 收到响应后,直接将用户导向 idp 提供的认证授权页面,并在页面 URL 参数中携带客户端返回的参数(除了 state 参数外,其他参数可以在页面中写死)client_id,response_type=code,redirect_uri(必选),scope(可选),state(可选),其中 redirect_uri 建议是必选的,而且必须是客户端提供的 URI(回调地址)。
  3. 用户在用户代理处点击登录按钮或请求授权登录按钮后,直接将用户导向 idp 提供的认证授权页面,并在页面 URL 参数中携带 client_id,response_type=code,redirect_uri(必选),scope(可选),但是不需要携带 state 参数,因为客户端不知道此参数的存在,其中 redirect_uri 建议是必选的,而且必须是客户端提供的 URI(回调地址)。

至此,授权码模式的认证授权全流程完毕。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于java学生成绩管理系统

开发工具eclipse,jdk1.8 技术:java swing 数据库:mysql5.7 学生选课系统功能:管理员、教师、学生三个角色 一、管理员功能: 1.登录、修改密码、退出系统 2.学生管理:添加、修改、删除、查询 3.班级管理&#x…

python文件夹拷贝思路

最近在做项目中,要使用python,对文件拷贝有了一些了解,这里将自己理解的文件拷贝整理出来。 如下所示,文件拷贝思路: 文件拷贝,从io上来说就是读文件,写文件到另一个指定的地方。 拷贝&#xff…

MXNet的Faster R-CNN(基于区域提议网络的实时目标检测)《1》

原论文:Faster R-CNN: Towards Real-Time Object Detection with Region Proposal Networks 开源代码:https://github.com/ijkguo/mx-rcnn Parallel Faster R-CNN implementation with MXNet,使用MXNet实现快速并行的区域提议的卷积神经网络…

[oeasy]python0032_杀死进程_进程后台运行不输出_nohup_ps_显示进程

查看进程 回忆上次内容 上次先ctrl z 挂起进程 然后运行 bg程序继续跑起来而且不断输出到标准输出流甚至连ctrl c 都无法结束进程了这可怎么办呢?只能新开一个终端想办法 查询进程 搜索 debian进程查询找到具体方法 进程 具体方法动手试试 新开一个终端 运行ps…

新冠阳性的第五篇博客,宝塔面板如何快速部署一个SpringBoot项目

宝塔面板如何快速部署一个SpringBoot项目1.删除旧版本的Java2.安装Java3.配置Java环境变量4.宝塔快速部署1.删除旧版本的Java 删除旧版本的Java,防止对我们的服务产生影响! 如果你的服务器上没有下载过Java,则跳过此步骤! 查找…

【K3s】第1篇 K3s入门级介绍及架构详解

目录 1、什么是 K3s? 2、为什么叫 K3s? 3、适用场景 4、架构详解 单节点架构 高可用架构 K3s高可用架构: 固定 agent 节点的注册地址 注册 Agent 节点 1、什么是 K3s? K3s 是一个轻量级的 Kubernetes 发行版,它针对边缘计算、物联网等场景进…

SpringBoot图文详解 | 系统性学习 | 无知的我费曼笔记

无知的我复盘,顺便上传笔记。 对比Spring,SpringBoot 其实就是简化了固定的开发步骤。如坐标、Web3.0配置类、配置类 文章目录1 SpringBoot简介1.1 SpringBoot快速入门1.1.1 开发步骤1.1.1.1 创建新模块1.1.1.2 创建 Controller1.1.1.3 启动服务器1.1.1.…

【问题记录与解决】OSError: [WinError 127] 找不到指定的程序。

目录 一、报错记录二、尝试解决(已解决)2.1 先 卸载掉 几个与torch相关的模块2.2 重新下载几个模块,并分别安装一、报错记录 首先来看报错的截图: 报错的具体代码,可以看这里,和这里使用的一样的: 【Pytorch_Geometric】(GCN)基本使用:数据集与邻接矩阵格式,图形(…

河道水尺水位监测系统 基于opencv

河道水尺水位监测系统基于pythonopencv对现场画面中水位进行实时监测,当监测到画面中水位异常变化时,立即抓拍存档同步回传图片给后台。Python是一种由Guido van Rossum开发的通用编程语言,它很快就变得非常流行,主要是因为它的简…

用Python写个实用工具 - TheFuck(命令纠正工具)

前言 哈喽啊,我亲爱的铁铁们,I am back ! 别管,我也是阳过的人了,这么久都没有更新,今天就带来个小玩意吧 我们在学习python的时候,有个小工具,是可以纠正我们写错的命令 The Fu…

React封装一个纯CSS实现的水滴样式的盒子

背景 刷B站刷到一个纯css实现的水滴效果的视频 感觉真不错,决定封装一个具有水滴效果的盒子(DIV) 涉及知识点 CSS样式,核心是这个和box-shadow阴影,实现水滴boder和阴影效果。JS控制CSS样式16进制的颜色(…

SpringBoot项目+注册功能实现

注册功能实现分析 目录 一、AppConfig.java 二、register.html 三、UserDto.java 四、UserController.java 五、UserMapper.xml 六、运行结果 一、AppConfig.java Configuration public class AppConfig implements WebMvcConfigurer {//统一视图跳转Overridepublic void…

(1)Qt的基本数据类型以及基本输出

基础类型 因为Qt是一个C框架, 因此C中所有的语法和数据类型在Qt中都是被支持的, 但是Qt中也定义了一些属于自己的数据类型, 下边给大家介绍一下这些基础的数据类型。 类型名称注释备注qint8signed char有符号8位数据qint16signed short16位数据类型qint32signed short32位有符号…

数据结构与算法java篇--二叉树

内容有点多,建议先收藏 目录 一.树的介绍 二.java代码实现树 1.Node类 2.Tree类 3.查找节点 4.插入节点 5.遍历树 5.1 中序遍历 5.2 前序遍历和后序遍历 6.查找最大值和最小值 7.删除节点 7.1 删除没有子节点的节点 7.2 删除有一个子节点的结点 7.3 删除…

java美食论坛系统发帖子系统美食论坛网站美食分享论坛源码

ssm开发的美食论坛系统,用户注册之后可以发布关于美食的帖子,其他人可以回帖,评论,点赞回复和评论,分为楼主,第一楼,第二楼等。可以再个人中心查看我对别人的回复,以及别人对我的回复…

学习黑客十余年,如何成为一名安全工程师?

1. 前言 说实话,一直到现在,我都认为绝大多数看我这篇文章的读者最后终究会放弃,原因很简单,自学终究是一种适合于极少数人的学习方法,而且非常非常慢,在这个过程中的变数过大,稍有不慎&#x…

主成分分析(PCA)

主成分分析是一种降维(去除噪声和不重要信息)方法,它能将多个指标转换为少数几个主成分,这些主成分是原始变量的线性组合,且彼此之间互不相关。 适用性:当研究的问题涉及到多变量且变量之间存在很强的相关…

【LeetCode】2099. 找到和最大的长度为 K 的子序列

【LeetCode】2099. 找到和最大的长度为 K 的子序列 给你一个整数数组 nums 和一个整数 k 。你需要找到 nums 中长度为 k 的 子序列 ,且这个子序列的 和最大 。 请你返回 任意 一个长度为 k 的整数子序列。 子序列 定义为从一个数组里删除一些元素后,不…

BIT.1_常见指令以及权限理解

目录使用 XShell 远程登录 Linux下载安装 XShell查看 Linux 主机 ip使用 XShell 登陆主机XShell 下的复制粘贴文件 内容数据 属性数据Linux目录结构相对/绝对路径Linux下基本指令01. ls 指令02. pwd命令03. cd 指令04. touch指令05.mkdir指令(重要)&am…

基于Xlinx的时序分析与约束(4)----主时钟约束

主时钟约束语法 主时钟约束,就是我们对主时钟(Primary Clock)的时钟周期进行约束(告诉综合工具布局布线的标准),这个约束是我们用的最多的约束了,也是最重要的约束。 主时钟必须与一个网表对象相…