【Spring专题】「开发指南」OAuth2的技术体系架构和开发概览

简介: 【Spring专题】「开发指南」OAuth2的技术体系架构和开发概览

背景介绍


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


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


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应用是第三方的不可信应用,则应该采用授权码模式;如果是第一方可信应用,则可以采用密码模式,当然不怕麻烦也可以用授权码模式。

image.png

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



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


  • 用户代理/浏览器 User Agent


  • 客户端 Client:一般指第三方应用程序,例如用QQ登录豆瓣网站,这里的豆瓣网就是 Client;但在微服务体系里,Client通常是服务本身,如 APP 端的注册登录服务;


  • 资源所有者 Resource Owner:一般指用户,例如用 QQ 登录豆瓣网站,这里的所有者便是用户;但在微服务体系里,资源所有者的指向不是一成不变的,要具体分析;


  • 资源服务器 Resource Server (受保护资源):一般指资源所有者授权存放用户资源的服务器,例如用 QQ 登录豆瓣网站,这里的 QQ 就是资源服务器;但在微服务体系里,服务提供者本身便是资源服务器;


  • 授权服务器 Authorization Server:一般是指服务提供商的授权服务,例如用 QQ 登录豆瓣网站,这里的 QQ 便是授权服务器;类似地,在微服务体系里,IDP 服务便是授权服务器。




整个流程分为两个阶段:


第一阶段:认证授权阶段


  1. 前端页面将用户输入的用户名和密码,发送给客户端(process-service);


  1. 客户端(process-service)将用户输入的用户名和密码,连同 client_id + client_secret (由idp分配)一起发送到idp以请求令牌,如果 idp 约定了 scope 则还需要带上 scope 参数;


  1. idp 首先验证 client_id + client_secret 的合法性,再检查 scope 是否无误,最后验证用户名和密码是否正确,正确则生成 token。这一步也叫“认证”;


  1. idp 返回认证结果给客户端,认证通过返回 token,认证失败返回 401。如果认证成功则此步骤也叫“授权”;


  1. 客户端收到 token 后进行暂存,并创建对应的 session;


  1. 客户端颁发 cookie 给用户代理/浏览器。


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




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


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


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


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


  1. 资源服务器(resource-service)向 idp 请求验证 token 有效性;


  1. idp 校验 token 有效性,再根据 scope 判断客户端(process-service)是否有权限调用此 API,最后返回校验结果给资源服务器。这一步也叫“鉴权”;


  1. 资源服务器根据 idp 检验结果(true/false 或其他等效手段)决定是否返回用户相册数据给客户端。如果 token 校验失败则返回 401 给客户端,如果 scope 检查不通过则返回 403。这一步也叫“权限控制”。


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


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




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


image.png

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


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


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


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


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


  • 如果校验全部通过,idp 生成 JWT 并返回给网关;如果 token 校验失败返回 401;如果 scope 检查不通过则返回 403;


  • 如果校验通过,网关将得到 JWT,携带此 JWT 转发请求到资源服务器;


  1. 资源服务器解析 JWT 得到用户信息,查询用户相册数据后返回给网关;


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


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


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


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


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




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


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

image.png

整个流程分为两个阶段:


第一阶段:认证授权阶段


  1. 用户在用户代理处点击登录按钮,或请求授权登录按钮,此操作将访问客户端的某个 URI;
  2. 客户端(process-service)将用户导向 idp 提供的认证授权页面,并在页面 ULR 参数中携带 client_id,response_type=code,redirect_uri(可选),scope(可选),state(可选);


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


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


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


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



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


  1. 用户在用户代理处点击登录按钮或请求授权登录按钮后,通知客户端(process-service),客户端收到通知后返回重定向的指示,以及 scope(可选),state(可选)等;


  1. 收到响应后,直接将用户导向 idp 提供的认证授权页面,并在页面 URL 参数中携带客户端返回的参数(除了 state 参数外,其他参数可以在页面中写死)client_id,response_type=code,redirect_uri(必选),scope(可选),state(可选),其中 redirect_uri 建议是必选的,而且必须是客户端提供的 URI(回调地址)。


  1. 用户在用户代理处点击登录按钮或请求授权登录按钮后,直接将用户导向 idp 提供的认证授权页面,并在页面 URL 参数中携带 client_id,response_type=code,redirect_uri(必选),scope(可选),但是不需要携带 state 参数,因为客户端不知道此参数的存在,其中 redirect_uri 建议是必选的,而且必须是客户端提供的 URI(回调地址)。



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




相关文章
|
10天前
|
运维 Kubernetes Cloud Native
云原生技术:容器化与微服务架构的完美结合
【10月更文挑战第37天】在数字化转型的浪潮中,云原生技术以其灵活性和高效性成为企业的新宠。本文将深入探讨云原生的核心概念,包括容器化技术和微服务架构,以及它们如何共同推动现代应用的发展。我们将通过实际代码示例,展示如何在Kubernetes集群上部署一个简单的微服务,揭示云原生技术的强大能力和未来潜力。
|
18天前
|
运维 持续交付 API
从零构建微服务架构:一次深度技术探索之旅####
【10月更文挑战第28天】 本文记录了作者在从零开始构建微服务架构过程中的深刻技术感悟,通过实战案例详细剖析了微服务设计、开发、部署及运维中的关键要点与挑战。文章首先概述了微服务架构的核心理念及其对企业IT架构转型的重要性,随后深入探讨了服务拆分策略、API网关选型、服务间通信协议选择、容器化部署(Docker+Kubernetes)、以及持续集成/持续部署(CI/CD)流程的设计与优化。最后,分享了在高并发场景下的性能调优经验与故障排查心得,旨在为读者提供一套可借鉴的微服务架构实施路径。 ####
55 3
|
24天前
|
数据采集 监控 前端开发
二级公立医院绩效考核系统源码,B/S架构,前后端分别基于Spring Boot和Avue框架
医院绩效管理系统通过与HIS系统的无缝对接,实现数据网络化采集、评价结果透明化管理及奖金分配自动化生成。系统涵盖科室和个人绩效考核、医疗质量考核、数据采集、绩效工资核算、收支核算、工作量统计、单项奖惩等功能,提升绩效评估的全面性、准确性和公正性。技术栈采用B/S架构,前后端分别基于Spring Boot和Avue框架。
|
8天前
|
存储 分布式计算 关系型数据库
架构/技术框架调研
本文介绍了微服务间事务处理、调用、大数据处理、分库分表、大文本存储及数据缓存的最优解决方案。重点讨论了Seata、Dubbo、Hadoop生态系统、MyCat、ShardingSphere、对象存储服务和Redis等技术,提供了详细的原理、应用场景和优缺点分析。
|
10天前
|
监控 API 微服务
后端技术演进:从单体架构到微服务的转变
随着互联网应用的快速增长和用户需求的不断演化,传统单体架构已难以满足现代软件开发的需求。本文深入探讨了后端技术在面对复杂系统挑战时的演进路径,重点分析了从单体架构向微服务架构转变的过程、原因及优势。通过对比分析,揭示了微服务架构如何提高系统的可扩展性、灵活性和维护效率,同时指出了实施微服务时面临的挑战和最佳实践。
30 7
|
8天前
|
传感器 算法 物联网
智能停车解决方案之停车场室内导航系统(二):核心技术与系统架构构建
随着城市化进程的加速,停车难问题日益凸显。本文深入剖析智能停车系统的关键技术,包括停车场电子地图编辑绘制、物联网与传感器技术、大数据与云计算的应用、定位技术及车辆导航路径规划,为读者提供全面的技术解决方案。系统架构分为应用层、业务层、数据层和运行环境,涵盖停车场室内导航、车位占用检测、动态更新、精准导航和路径规划等方面。
43 4
|
27天前
|
Kubernetes Cloud Native 持续交付
云端新纪元:云原生技术重塑IT架构####
【10月更文挑战第20天】 本文深入探讨了云原生技术的兴起背景、核心理念、关键技术组件以及它如何引领现代IT架构迈向更高效、灵活与可扩展的新阶段。通过剖析Kubernetes、微服务、Docker等核心技术,本文揭示了云原生架构如何优化资源利用、加速应用开发与部署流程,并促进企业数字化转型的深度实践。 ####
|
9天前
|
Kubernetes Cloud Native 持续交付
云原生技术在现代应用架构中的实践与思考
【10月更文挑战第38天】随着云计算的不断成熟和演进,云原生(Cloud-Native)已成为推动企业数字化转型的重要力量。本文从云原生的基本概念出发,深入探讨了其在现代应用架构中的实际应用,并结合代码示例,展示了云原生技术如何优化资源管理、提升系统弹性和加速开发流程。通过分析云原生的优势与面临的挑战,本文旨在为读者提供一份云原生转型的指南和启示。
25 3
|
11天前
|
网络协议 数据挖掘 5G
适用于金融和交易应用的低延迟网络:技术、架构与应用
适用于金融和交易应用的低延迟网络:技术、架构与应用
39 5
|
9天前
|
运维 Kubernetes Cloud Native
云原生技术在现代应用架构中的实践与挑战####
本文深入探讨了云原生技术的核心概念、关键技术组件及其在实际项目中的应用案例,分析了企业在向云原生转型过程中面临的主要挑战及应对策略。不同于传统摘要的概述性质,本摘要强调通过具体实例揭示云原生技术如何促进应用的灵活性、可扩展性和高效运维,同时指出实践中需注意的技术债务、安全合规等问题,为读者提供一幅云原生技术实践的全景视图。 ####
下一篇
无影云桌面