网络授权中的不同角色如何各司其职

前文书我们已经说到 OAuth 网络授权目的是为 API 的访问授权提供一个统一开放的标准,这篇图文咱们就看一看参与到网络授权的参与者都有哪些?核心的授权流程是如何进行的?这一次咱们从最复杂的场景出发,也就是上一篇图文当中小美的场景。在这个场景中小美的照片存放在 A 网站 “图片仓库” 中,而 B站 “美图羞羞” 需要 A 站中照片资源,所以希望 A 站能够提供小美账号下的照片以便美图羞羞可以向小美提供相册制作的服务。在这个场景下,参与者如下:

 

1. 资源的拥有者(Resource Owner) - 用户小美

2. 被授权的客户端 (Client Application) - B 站美图羞羞

3. 服务提供商(HTTP Service)- A 站图片仓库

 

毕竟咱们都是技术人员,所以必要的技术名词咱们还是要慢慢引入的,如果从 UML 的方法论来说,我们正在完成从 现实世界到业务模型的转化 过程,我们也正好借着这个机会简单学习一下建模的推导过程,不求严谨,但求把里面最重要的思想传递给大家。目前我们只是简单的提取出了当前授权场景下的参与者,其授权的交互流程尚未得出。现在咱们就来看一看,被授权的客户端美图羞羞都需要获得谁的授权,它需要获得用户小美和 A 站图片仓库的联合授权,而且这个授权的过程是分两步走:

 

1.  获得用户小美的授权

2.  获取 A 站图片仓库的授权,发给 B 站一个 access_token 令牌

 

经过这两步授权之后,美图羞羞无需用户在A站的用户名和密码,直接拿着令牌(access token)再次到服务提供商 A 站图片仓库那里调用指定的API获取到小美的照片资源。请记住,这是一个权限有限的令牌,使用这个访问令牌只能调用服务提供商图片仓库允许第三方客户端调用的 API 以获取相应的资源,在这里引出第 4 个核心概念,权限范围( scope ),在本例中,权限范围就是部分小美允许开放给第三方的照片资源。至此,最基本的几个核心概念咱们都凑齐了。再接下来,就到了系统分拆的阶段,我们知道参与OAuth 规则制订的多是大公司,大公司尤其讲究系统的职责划分。不光编程的时候有单一职责这个指导原则,系统进行设计的时候同样如此。于是乎,它们对服务提供商下手了,为的是更好的管理和更高的安全性,将其划分为以下两个子系统:

 

1. 授权/认证服务器 ( Authorization server )

2. 资源服务器 ( Resource server )

 

在大公司,这是两套系统,部署在不同的服务器中,而在大部分小型公司则把他们部署在一个服务器甚至一个服务器的同一项目中。OK,接下来就该进入核心部分了,授权和认证的流程,咱们还是先贴一张图吧,这张图很多博客或教程里都出现过:

 

Oauth2 授权抽象表达

这是一张抽象的流程图,它用最抽象的方式表达了授权和认证的过程,很多人看不懂这张图就是因为把它当作了某个场景下的具体实现流程,然而这张图只有抽象的过程,并没有具体授权和认证过程的逻辑,原来不光编程的时候玩抽象,流程图也可以玩抽象,抽象的思维无处不在,因为用好了抽象,可以帮助我们解决各类问题,不管是生活的还是工作的,利器在手,用不用在我们自己~

 

OAuth在"客户端"与"服务提供商"之间,设置了一个授权层(authorization layer)。"客户端" 不能直接登录 "服务提供商",只能通过授权层的授权之后才能访问用户的资源。"客户端" 所用的令牌(token),与用户的账号和密码不同。用户可以在登录的时候,指定授权层令牌的权限范围和有效期。  "服务提供商"根据“客户端令牌”的权限范围和有效期,向"客户端"开放用户储存的资源,我们先来简单把图中核心流程梳理一下:

 

[A] 用户打开客户端以后,客户端要求用户给予授权。 

[B] 用户同意给予客户端授权。 

[C] 客户端使用上一步获得的授权,向认证服务器申请令牌。 

[D] 认证服务器对客户端进行认证以后,确认无误,同意

[E] 客户端使用令牌,向资源服务器申请获取资源。 

[F] 资源服务器确认令牌无误,同意向客户端开放资源。

 

不难看出来,上面六个步骤之中,B是关键,即用户怎样才能给于客户端授权。有了这个授权以后,客户端就可以获取令牌,进而凭令牌获取资源。

 

上面的这一小段呢,是我从阮一峰的博客中剽窃过来的,做了剽客就得认,这是我一惯的风格,因为我也是个懒人,码字不容易的。但是最后一句话我要进行修改,为什么呢,因为之前咱们说了这是一张抽象流程图,之所以是抽象,那就是因为到了具体场景下具体流程也会表现出“多态”的特性,授权给客户端时,授权方可能是用户和授权服务器联合授权,也可能只有授权服务器在进行授权,压根没有用户什么事。所以这里需要修改为“B是关键,即如何向客户端进行授权”。理解了这一点,我们才能够真正理解 OAuth2 提出的四种不同使用场景下的授权模式,在某些场景下,A、B 这两个步骤都是不存在的。上帝啊,又出现“模式”这俩字了,江湖就是如此,小帮派有小讲究,大江湖有大套路,在编程语言层面有设计模式,到了业务层面,也有更高级别的模式。有一套系列技术书籍,现在甚至都很难买齐全套了《面向模式的软件架构》,极为经典,如果你有全套的话,送我可好,我想收藏一套,以娱晚年 ~

 

客户端必须得到授权(authorization grant),才能获得令牌(access token),OAuth 2 提出了四种授权模式供我们在不同场景下使用:

 

[1] 授权码模式 Authorization Code

[2] 简化模式 Implicit

[3] 密码模式 Resource Owner Password Credentials

[4] 客户端模式 Client Credentials

 

OK,本片图片就到这里吧,但是最后咱们再次强调两个重点,这两个点切不可理解偏差,会直接影响到后面对各个授权模式的学习和理解的:

 

1. OAuth 授权是围绕 API 进行的,是对需要授权的 API 设计的机制,不是针对资源进行的,也不要把那些不需要授权的 开放式 API 跟 OAuth2 授权的 API 混为一谈

 

2. 文中所说的 客户端 一定要正确理解,这个客户端与平时理解的前端或者 app 客户端不是一个概念,这里的客户端某些场景下是包含自己的后端服务器的只是因为在授权的场景下,授权方是服务的提供方,所以授权方是服务提供者,请求人家服务的第三方统一被认定为“客户端”,这是从大的调用关系上对他们的角色进行的划分。不要用日常使用的“客户端”来理解这里的客户端。

 

我真的很久不写图文了,感觉手生了,也感觉自己储备仍有不足,自己仍需努力,好好提升自己,在技术这条路上,咱们最不能丢的就是思考的能力和推理的能力,去伪存真,莫作乌合 ~