授权(备份)
#
概述授权指认证成功后系统对用户
是否能对指定资源
执行指定操作
的权限控制。
用户能否对指定的资源执行指定的操作取决于:
用户是否拥有执行该操作的权限(
privileges
),该检查结果取决于用户在系统中的角色后面我们会把角色定义为一个组织的成员中拥有一组特定权限的群组,所以这里所说角色是全局的,应称之为用户的类型。
例如,免费用户、付费用户、管理员可能会用有不同的权限。
论坛:Level1 用户没有发帖的权限、Level2 以后用户有发帖权限
用户是否拥有对指定资源执行该操作的权限,该检查结果取决于业务逻辑
例如,用户不能直接更改自己所下订单的应付金额。
例如,用户不能直接更改自己所下订单的应付金额。
指定的资源是否向该用户开放了执行该操作的权限,该检查结果取决于资源本身许可(
permissions
)的设置论坛:帖子的楼主关闭了帖子,除了楼主的论坛管理员所有其它人都无法查看
对于用户权限的检查,可以通过四个要素来分析:
- 操作的执行人(即用户),主要关注其所拥有的权限
- 操作的类型
- 操作的资源
- 操作的执行人与资源之间的关系
#
相关概念概念 | 说明 |
---|---|
用户(user ) | 执行操作的主体(principal ) |
租户(tenant ) | 使用系统服务的企业或组织,在电商/支付平台具化为商户(merchant ) |
用户角色(role ) | 通常一个系统中的用户会被分成若干个角色,或称之为用户群组(user group),同一角色的用户将用有一组相同的权限 |
用户权限、特权(privilege ) | 用户自身的或通过所属角色所获得的规定了其可以执行哪些操作的信息 |
资源访问权限许可(permission ) | 是资源的许可信息,说明了允许哪些用户执行哪些操作 |
一个大型的互联网应用可能会被设计为支持多租户,甚至多服务。
例如,淘宝作为电商平台是由众多第三方店铺构成的,而不论消费者还是商户用户,其账号都可以在阿里巴巴的众多服务中(如天猫、阿里云)使用。
此时,角色的作用域可能是商户的所有或部分(当商户存在子组织时)资源。
#
借鉴文件系统中的访问控制和权限参考资料:Wikipedia: File System Permissions
以下是几种常见操作系统中文件访问控制权限的设置示例,体现了为用户、用户群组授予可以对文件执行指定操作的权限的方式。
在类 Unix 系统中,文件访问控制权限针对文件所有者、所有者同组用户、其他用户三类用户对文件的读、写、执行操作进行控制。
#
Windows 7#
Mac OS X#
Linux#
互联网应用的权限控制然而,一个互联网应用的权限控制的场景要更复杂,主要体现在:
- 存在更多的业务角色
- 角色的作用域可能是有限的(而不是全局的)
- 操作的类型更多
此时,合理的业务设计和逻辑实现将尤为重要。
如上述文件系统的访问控制的实现,以及 RESTful 定义的以资源为中心的设计风格,有助于合理的设计互联网应用的权限控制。
下面以具体用例进行说明。
#
用例:电商订单系统#
业务场景用户C
是消费者,用户S
是店铺S
的店员,用户A
是系统管理员用户C
准备购买店铺S
的商品I
,并创建了订单O1
,然而,由于信息填写错误,用户C
又取消了订单O1
用户C
重新下单,创建了订单O2
- 由于符合商品信息中所描述的优惠条件,经过沟通,
用户S
同意将订单O2
的订单总额下调 用户C
支付订单,完成交易- 如果由于意外原因导致交易失败而产生脏数据,
用户A
可以对脏数据进行处理、修复。
#
实体-关系实体 | 实体类型 | 说明 | 实体间的关系 |
---|---|---|---|
用户A | 用户 | 管理员,超级用户 | |
用户C | 用户 | 消费者 | |
用户S | 用户 | 店员 | 是店铺S 的成员 |
店铺S | 商户 | ||
商品I | 商品 | ||
订单O1 、订单O2 | 订单 | 所有者为用户C ,商品所属店铺为店铺S |
#
资源定义本例的操作资源为消费者所创建的订单。
消费者通过以下请求创建订单:
消费者通过以下请求取消订单:
店员通过以下请求对订单改价:
经买卖双方沟通,需要取消已支付订单时,管理原可以通过以下请求执行该操作:
虽然 /users/用户C/orders/订单O2
、/stores/店铺S/customer-orders/订单O2
及 /orders/订单O2
在业务上是同一个实体,但是在表现层应被定义为多个资源,这样我们便可以清晰地描述用户对订单执行操作时应执行的权限检查的逻辑。
操作 | 接口 | 权限检查逻辑 |
---|---|---|
消费者取消订单 | DELETE /users/:user_id/orders/:order_id | 操作者必须为 ID 为 user_id 的用户(即订单的所有者) |
店员更新消费者所下订单的总额 | PATCH /stores/:store_id/customer-orders/:order_id | 操作者必须为 ID 为 store_id 的店铺的店员(即订单商品所属商户的成员) |
管理员取消已支付订单 | DELETE /orders/:order_id | 操作者必须为系统管理员 |
#
需求扩展在实际应用中可能还会存在以下需求:
同一店铺的店员被划分为不同的角色,拥有不同的权限
例如,一组店员只能维护商品,而另一组店员只能维护客户订单,而店铺管理员拥有所有权限。
特定商品的操作只对部分店员开放
#
权限检查过滤器设计示例现在我们可以开始设计一个权限检查过滤器。
权限检查在服务器接收到客户端请求,完成用户令牌校验后执行,即此时以下信息已被确定:
- 请求发送者的身份(用户的 ID、用户的类型、加入的组织及在各组织中的角色等信息)
- 请求操作的资源
配置路由时,我们可以为每一个路由设置一个权限检查的参数,路由器根据客户端请求的路径以及这个权限检查配置参数解构出上述权限检查过滤器的 permission
参数,并将其与访问令牌携带的用户信息一起传递给权限检查过滤器函数。
例如,消费者取消未支付订单接口的路由定义及其权限检查配置参数为:
店员修改订单应付金额接口的路由定义及其权限检查配置参数为:
这里我们增加一个需求:店员在店铺的角色必须为销售员(
salesman
)
管理员取消已支付订单的路由定义及其权限检查配置参数为:
下面是店员管理商品的接口的权限设计。
创建商品的路由定义及其权限检查配置参数:
更新商品的路由定义及其权限检查配置参数:
#
总结至此,我们实现了以下三个层面的访问控制:
- 将用户划分为不同的人群,并规定个人群可以使用哪些接口;
- 根据业务逻辑,判断用户能否对指定的资源执行指定的操作;
- 根据目标资源自身的访问许可,判断用户能否对该资源执行指定的操作。
访问控制权限检查的业务流程为:
- 校验用户令牌,取得用户信息;
- 根据路由定义从 HTTP 请求路径中解构路径参数;
- 根据权限检查配置,使用路径参数构造权限检查过滤器的参数;
- 执行访问权限检查。
- 用户类型检查;
- 所有者检查;
- 用户所属群组检查;
- 用户所属群组角色检查;
- 资源访问许可检查。