【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(回调地址)。



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




相关文章
|
7月前
|
SQL 前端开发 关系型数据库
如何开发一套研发项目管理系统?(附架构图+流程图+代码参考)
研发项目管理系统助力企业实现需求、缺陷与变更的全流程管理,支持看板可视化、数据化决策与成本优化。系统以MVP模式快速上线,核心功能包括需求看板、缺陷闭环、自动日报及关键指标分析,助力中小企业提升交付效率与协作质量。
|
6月前
|
人工智能 运维 Java
Spring AI Alibaba Admin 开源!以数据为中心的 Agent 开发平台
Spring AI Alibaba Admin 正式发布!一站式实现 Prompt 管理、动态热更新、评测集构建、自动化评估与全链路可观测,助力企业高效构建可信赖的 AI Agent 应用。开源共建,现已上线!
6895 89
|
6月前
|
前端开发 JavaScript BI
如何开发车辆管理系统中的车务管理板块(附架构图+流程图+代码参考)
本文介绍了中小企业如何通过车务管理模块提升车辆管理效率。许多企业在管理车辆时仍依赖人工流程,导致违章处理延误、年检过期、维修费用虚高等问题频发。将这些流程数字化,可显著降低合规风险、提升维修追溯性、优化调度与资产利用率。文章详细介绍了车务管理模块的功能清单、数据模型、系统架构、API与前端设计、开发技巧与落地建议,以及实现效果与验收标准。同时提供了数据库建表SQL、后端Node.js/TypeScript代码示例与前端React表单设计参考,帮助企业快速搭建并上线系统,实现合规与成本控制的双重优化。
|
6月前
|
安全 前端开发 Java
《深入理解Spring》:现代Java开发的核心框架
Spring自2003年诞生以来,已成为Java企业级开发的基石,凭借IoC、AOP、声明式编程等核心特性,极大简化了开发复杂度。本系列将深入解析Spring框架核心原理及Spring Boot、Cloud、Security等生态组件,助力开发者构建高效、可扩展的应用体系。(238字)
|
6月前
|
运维 监控 安全
公链开发中的高可用架构设计要点
本指南提供公链高可用架构的可复用流程与模板,涵盖目标拆解、先决条件、分步执行、故障排查及验收标准,结合跨链DApp与量化机器人案例,提升落地效率与系统稳定性。
|
6月前
|
消息中间件 运维 监控
交易所开发核心架构拆解与流程图
本文系统解析交易所架构核心要素,从接入层到清算结算,结合系统流程图拆解各模块职责与协作机制。深入剖析撮合引擎、账本设计与风控逻辑,建立性能、可用性、安全性等多维评估标准,并提供可落地的流程图绘制、压测优化与进阶学习路径,助力构建高效、安全、可扩展的交易系统。(238字)
|
7月前
|
供应链 监控 JavaScript
如何开发ERP(离散制造-MTO)系统中的库存管理板块(附架构图+流程图+代码参考)
本文详解MTO模式下ERP库存管理的关键作用,涵盖核心模块、业务流程、开发技巧与代码示例,助力制造企业提升库存周转率、降低缺货风险,实现高效精准的库存管控。
|
7月前
|
前端开发 API 定位技术
如何开发车辆管理系统中的用车申请板块(附架构图+流程图+代码参考)
本文详细解析了如何将传统纸质车辆管理流程数字化,涵盖业务规则、审批流、调度决策及数据留痕等核心环节。内容包括用车申请模块的价值定位、系统架构设计、数据模型构建、前端表单实现及后端开发技巧,助力企业打造可落地、易扩展的车辆管理系统。
|
7月前
|
设计模式 人工智能 API
AI智能体开发实战:17种核心架构模式详解与Python代码实现
本文系统解析17种智能体架构设计模式,涵盖多智能体协作、思维树、反思优化与工具调用等核心范式,结合LangChain与LangGraph实现代码工作流,并通过真实案例验证效果,助力构建高效AI系统。
838 7

热门文章

最新文章