前两篇详细介绍了OAuth 2.0中的两个核心服务器,现在只剩下最后一个受保护资源服务器了,它可以说是OAuth 2.0的终极目的,前面做了那么多,最终就是为了去受保护资源服务器上获取用户想要的数据,与前两者一样,受保护资源服务器也有它要完成的使命:
如上图所示,它需要完成:
- 解析令牌
- 校验令牌
- 不同场景下提供不同的服务
一句话概括,资源服务器需要做的就是从传入的HTTP请求中解析出OAuth令牌,验证该令牌,并确定它能用于哪些请求!
一、解析令牌
前一篇文章【https://www.cnblogs.com/hellowhy/p/15521724.html】中提到发送令牌参数的方式有三种:
- 使用HTTP Authorization头部;
- 使用表单格式的请求体参数
- 使用URL编码的查询参数
但是一般情况下都是优先选择header方式,为了更好的兼容不同的客户端,资源服务器上最好提供三种不同传递方式的解析
OAuth bearer令牌使用规范规定,在使用HTTP Authorization头部传送令牌时,HTTP头部的值以关键字Bearer开头,后跟一个空格,再跟令牌值本身。而且,OAuth规范还规定 Bearer关键字不区分大小写。此外还规定了Authorization头部关键字本身不区分大小写,这意味着以下所欲HTTP头部都是等价的:
- Authorization: Bearer 8989jksihtbnpsoit7hsj
- Authorization: bearer 8989jksihtbnpsoit7hsj
- authorization: BEARER 8989jksihtbnpsoit7hsj
注意:令牌值本身是区分大小写的!!!
当资源服务器接收到请求后,需要兼容对三种请求方式的解析:
首先,从Authorization请求头中获取令牌,即bearer 之后的部分,如果获取到则不进行其他方式的获取
其次,当从header中获取不到时,尝试从表单请求参数中获取。(不推荐,因为这种方式限制了APi的输入只能是表单形式)
最后,如果前两者都没有获取到,则尝试从查询参数中获取
当通过三种方式都没有获取到时,证明客户端请求参数有问题,直接返回错误信息,否则进行下一步校验令牌。
二、校验令牌
令牌是由授权服务器的令牌端点颁发,可以存储在共享数据库中,资源服务器需要根据请求中的令牌值查询令牌是否存在,在存在的情况下校验令牌是否有效,如果校验失败则直接返回错误信息给客户端!
虽然使用共享数据库是一种非常常见的OAuth部署模式,但它绝对不是唯一选择。有一个叫做令牌内省(token introspection)的Web协议,它可以由授权服务器提供接口,让资源服务器能够在运行时检查令牌的状态。这使得资源服务器可以像客户端那样将令牌本身视为不透明的,代价是使用更多的网络流量。还要另一种方式:可以在令牌内包含受保护资源能够直接解析并理解的信息。JWT就是这样一种数据结构,它可以使用受加保护的JSON对象携带声明信息。
在实际的应用过程中,访问资源服务器的每一个接口都需要校验令牌,为了不在每个方法中都进行校验,一般都是将校验token的逻辑写在拦截器中进行。
三、提供服务
在很多的API设计中,不同的操作需要不同的访问权限,还有一些API会根据授权者不同而返回不同的结果,或者根据不同权限返回某一部分信息,一般有以下三种场景。
3.1 不同权限范围对应不同的操作
在这种风格的API设计中,不同类型的操作需要不同的权限范围,才能调用成功。这使得资源服务器可以根据客户端能执行的操作来划分功能,这也是在单个授权服务器对应的多个资源服务器之间使用单个访问令牌的常用方法。
举个例子 假设客户端A注册时的授权范围是通过对接口的操作方式区分的,有write、read、delete三种操作权限,当它请求授权时,资源拥有者只授予read权限给它,当它获取到访问令牌之后,向资源服务器发起请求,这时它所能请求的只有GET类型的方法,如果请求POST或DELETE,资源服务器直接拒绝!
在任何情况下,即使令牌有效,但只要权限范围不正确,同样返回错误!!!
3.2 不同权限范围对应不同的数据结果
在这种风格的API设计中,同一个处理函数可以根据传入的令牌中包含的权限范围不同,而返回不同类别的信息。如果数据结构复杂,且希望通过同一个API端点为客户端提供多种信息子集的访问,这样的设计就非常有用!
举个例子 假设客户端B注册时的授权范围是通过数据类型区分的,有企业、用户两种数据权限,当它请求授权时,资源拥有者只授予企业权限给它,那么当它获取到访问令牌之后,只能请求企业类型的资源,而不能请求用户类型的资源,因为资源服务器校验令牌时能查到该令牌对应的权限只有企业,如果用户请求了获取用户或者企业和用户的接口,就会报错!
3.3 不同的用户对应不同的数据结果
在这种风格的API设计中,同一个处理函数可以根据授权客户端的用户不同而返回不同的信息。这是一种常见的API设计模式,它使得客户端应用在不知道用户是谁的情况下,调用同一个URL也能获取个性化的结果。
举个例子 假设客户端C注册时的授权范围有管理员、普通用户两种用户,当它向一个管理员角色的资源拥有者请求授权时,该管理员只授予它普通用户的权限,那么当它获取到访问令牌之后,只能请求普通用户有权访问的资源,如果访问管理员能访问的资源,则资源服务器会根据资源能被访问的权限范围对它进行拒绝!
使用OAuth能对受保护资源实现的访问控制远不止本文所列的这些,但是不管这样,在任何情况下,资源服务器都对访问令牌的含义拥有最终决定权,不管资源服务器外包了多少决策过程,最终都由它来决定如何处理给定请求!
四、总结
使用OAuth保护Web API 非常简单:
- 从传入的请求中解析令牌
- 通过授权服务验证令牌
- 根据令牌的权限范围做出响应,令牌的权限范围多种多样
至此,OAuth 2.0中的三巨头梳理的已经差不多了,接下来会梳理一下OAuth 2.0中的其他许可类型,加油!!!