OAuth2授权码模式---详解

OAuth2简介

是一个业界标准的授权协议(authorization protocol),这里的授权是以委派代理(delegation)的方式。可以这样理解,OAuth 2.0提供一种协议交互框架,让某个应用能够以安全地方式获取到用户的委派书,这个委派书在OAuth 2.0中就是访问令牌(access token),随后应用便可以使用该委派书,代表用户来访问用户的相关资源。

在OAuth 2.0的协议交互中,有四个角色的定义,

  • 资源所有者(Resource Owner):顾名思义,资源的所有者,很多时候其就是我们普通的自然人(但不限于自然人,如某些应用程序也会创建资源),拥有资源的所有权。
  • 资源服务器(Resource Server):保存着受保护的用户资源。
  • 应用程序(Client):准备访问用户资源的应用程序,其可能是一个web应用,或是一个后端web服务应用,或是一个移动端应用,也或是一个桌面可执行程序。
  • 授权服务器(Authorization Server):授权服务器,在获取用户的同意授权后,颁发访问令牌给应用程序,以便其获取用户资源。

从一个简单的应用场景谈起

为了方便讨论,我们假设有一个用户Michael,他在一个资源服务器上保存着他自己的账号信息,例如微信账号的姓名、头像等。某个应用程序在用户登录时,需要获取Michael的这些账号信息。

Michael在资源服务器上保存的账号信息是受保护的,为了让应用程序能够获取Michael的账号信息,需要提供用户的访问密码。有一个简单的方法是,在应用服务器和资源服务器之间共享同一访问密码,当Michael登录输入密码后,应用程序复制Michael的登录密码并向资源服务器请求访问,获取Michael的账号信息。这是早些时候比较常见的跨应用授权访问方法。

这样子做有很大的安全隐患,主要有如下三个方面的问题,

  1. 用户在应用程序和资源服务器需要保持一致的密码
  2. 无法控制应用程序的权限,应用程序需要的是读权限,但是拿到用户密码后,获取到的却是用户的所有访问权限
  3. 用户的密码会被应用程序获取到,有用户密码泄露的风险,一旦应用程序多了,安全风险不可控

在简单的应用场景里,在应用程序和资源服务器之间保持一致的密码是可行的,这也确实能够带来一定的便利,至少用户不用记多套用户名和密码,但账号和密码的独立性无法得到保证,应用程序可以直接接触到用户密码等敏感信息,账号的安全性也无法控制。

为了解决第1个问题,用户Michael在应用程序和资源服务器可以使用不同的密码登录,有一个可行的方法是,让用户输入两次密码,第一次输入密码为了登录应用程序,第二次让Michael输入其在资源服务器的登录密码,以便应用程序获取资源服务器的账号信息。

这样就需要用户输入两次密码,给用户的使用带来很大的不便,而且这个方案依然存在第2和第3的问题。

为了解决第2个问题,限制应用程序访问资源服务器的权限,我们可以让用户在资源服务器申请一个只读的受限密码,该受限密码只用来读取用户信息,无法用来进行编辑和删除操作,用户输入这个只读密码给应用程序,让应用程序读取用户在资源服务器上的信息。

这个方法解决了上述提到的第3个问题,但是这个key是一个通用的读权限,权限范围很大,其和用户没有任何关联。在很多时候,我们还是需要用户级别上的受限权限控制。

能否有一个方案,在不影响用户的使用便利性,并且颁发一个在用户级别上的可控权限key?可以考虑的是,用户动态按需地向资源服务器申请读权限key,然后颁发给应用程序,用于应用程序去申请访问用户的信息,该受限密码在颁发后有一定的时效性,甚至可以指定其只能被使用一次。这样子的话,解决问题1、2和3的条件都得到满足。

这个方案已经很接近于OAuth 2.0在设计之初所提供的授权方案,不一样之处的是,受限密码的颁发交给了独立的安全组件:授权服务器。

这里马上就要介绍OAuth 2.0的基本授权方式:授权码模式。

OAuth 2.0基本授权流程:授权码模式

让我们看看在增加授权服务器之后,OAuth 2.0的一个基本授权流程,

如图所示,授权流程场景可以描述为如下几个步骤,

  1. 用户在应用程序中,应用程序尝试获取用户保存在资源服务器上的信息,比如用户的身份信息和头像,应用程序首先让重定向用户到授权服务器,告知申请资源的读权限,并提供自己的client id。
  2. 到授权服务器,用户输入用户名和密码,服务器对其认证成功后,提示用户即将要颁发一个读权限给应用程序,在用户确认后,授权服务器颁发一个授权码(authorization code)并重定向用户回到应用程序。
  3. 应用程序获取到授权码之后,使用这个授权码和自己的client id/secret向认证服务器申请访问令牌/刷新令牌(access token/refresh token)。授权服务器对这些信息进行校验,如果一切OK,则颁发给应用程序访问令牌/刷新令牌。
  4. 应用程序在拿到访问令牌之后,向资源服务器申请用户的资源信息
  5. 资源服务器在获取到访问令牌后,对令牌进行解析(如果令牌已加密,则需要进行使用相应算法进行解密)并校验,并向授权服务器校验其合法性,如果一起OK,则返回应用程序所需要的资源信息。

这个授权流程在OAuth 2中被称为授权码模式(authorization code grant),其命名的原因是,应用程序使用授权码来向授权服务器申请访问令牌/刷新令牌。

可以看到,在整个过程中应用程序没有接触到用户的密码。

授权码和令牌都是一个唯一标识的值,其各个意义为,

  • 授权码:即用户的委派书,代表着用户的受限权限,有时效性
  • 访问令牌:用于应用程序每次向资源服务器访问时提供,有时效性,如果安全性比较高的话,则每个访问令牌可以被设置为只用一次,或者对令牌设置一个有效期,在有效期可以反复使用。
  • 刷新令牌:用于应用程序向授权服务器申请新的访问令牌,在访问令牌失效或过期的时候,重新获取新的访问令牌。

注意的是,访问令牌对于应用程序来说是透明的,应用程序无需关注访问令牌所带的任何信息,只需在访问资源服务器时带上它。但是资源服务器需要知道访问令牌的组成和加密方式,资源服务器需要解析或解密这个访问令牌,查看并校验里面的信息。

授权服务器和访问令牌,前者为授权的颁发,后者为授权的载体,两者实现了动态按需地代理权限分发,这也是OAuth 2.0解决方案在授权上所带来的创新变化。

相关推荐
吾疾唯君医17 小时前
Java SpringBoot集成积木报表实操记录
java·spring boot·spring·导出excel·积木报表·数据文件下载
白鲸开源19 小时前
杀疯了!SeaTunnel AI CLI 解锁数据集成新玩法
大数据·人工智能·github
Skylwn19 小时前
保姆级教程之将 GitHub Models 接入 NewAPI
笔记·github
正儿八经的少年20 小时前
Spring Boot 两种激活配置方式的作用与区别
java·spring boot·后端
云烟成雨TD20 小时前
Spring AI Alibaba 1.x 系列【52】Interrupts 中断机制:节点执行前后静态中断
java·人工智能·spring
疯狂成瘾者20 小时前
Spring Boot 项目中的 SMTP 邮件验证码服务技术解析
java·spring boot·后端
Better Bench20 小时前
Claude Code 学习指南:优秀 GitHub 仓库推荐与进阶路线图
github·claude code·学习指南
逛逛GitHub21 小时前
强烈推荐看看这个演讲,还配套 7 万 Star 的开源 Skill。
github
Volunteer Technology21 小时前
SpringAI Tool Calling 工具调用(六)
人工智能·spring
笨拙的老猴子21 小时前
Spring AI 实战教程(七):Agent 智能体 —— 用电商购物助手学透自主规划与工具执行
java·人工智能·spring