RESTful API 访问控制
RESTful API access control
关于 RESTful API 的访问控制设计的大部分信息都围绕着用户(即不同的用户有不同的访问级别等)。
想象一个没有用户概念的系统。有一堆服务器通过 RESTful API 相互通信。没有客户端 - 我的意思是,对于两个服务器之间的每次交互,其中一个可以被视为“客户端”,但我的观点是所有服务器或多或少是“平等的”,并且每个服务器都可以向许多其他服务器发送请求服务器(反之亦然)。
这与传统的 web/mobile 客户端-服务器架构非常不同。
现在,想象一下并非所有这些服务器实际上都是 100% 平等的。有些人应该可以访问一些 APIs,但不是全部。如何保证这样级别的访问控制?
让我们将您拥有的服务器视为网络中的节点,以避免混淆。当node1向node2发送请求时,那么在那个交互中,node2是服务器,node1是客户端(类似于“用户”)。
因此,从 node2 的角度来看,如果您必须区分 client1 和 client2(可以发送请求的两个可能的节点),根据它们各自可以访问或不可以访问的内容,那么强烈建议为 node2 定义角色映射。
这意味着您将有 key-value 对,其中键是方法,值是角色。
每当 client1 或 client2 请求一个方法时,您将以某种方式确定该方法需要哪些角色,以及 client1 和 client2 是否具有所有必要的角色。
这意味着对于节点2的API,每当接收到请求时,需要执行以下算法:
- 会调用一个中心方法(暂且称之为
APIWrapper
)
APIWrapper
找出客户端的角色是什么
APIWrapper
找出调用 function1
所需的角色,客户端请求的功能
- 如果客户端未履行
function1
所需的任何角色,则以未经授权的错误响应并停止进程
- 如果已成功到达此阶段且没有未经授权的错误,则执行
method1
并将其响应传输给客户端
你可能有一个角色林,也就是说,你会有角色树,这取决于访问级别(即你可能有一个单独的角色来上传 xlsx 文件,你可能有一个角色来上传任何文件,因此,在这种情况下,您可能需要上传 xlsx,而客户端将具有上传任何文件的角色,在这种情况下,仍应允许客户端执行给定的操作)。
如果您对角色子类有这样的需求,那么强烈推荐
- 在值部分的角色映射中,您将指定该角色属于哪个角色树(即文件上传)和该角色的级别(即 xlsx)
- 在每个角色树中,如果有一个父P和一个子C,那么就意味着P => C,也就是说,C比P更具体,所以如果角色P存在就意味着这个角色客户端也存在C
- 每个角色都需要有一个签名来唯一标识其在树中的路径,因此到达它的复杂度为 O(log(N)) 而不是 O(N)
不用说,分配或撤销角色的方式需要安全且一致。
所以,我们站在node2的角度是这样想的。然而,node2 本身也可能是其他节点的客户端。问题类似。
但是,如果 server1 gains/loses 在节点 1 上扮演角色,是否会触发 server1 gains/loses 其他服务器的角色?如果是这样,那么您还需要某种方式来同步角色,也许通过 cron 作业定期进行。
最后,如果可以将定义、分配和撤销角色的方式标准化,那就太好了。因为这样一来,每个服务器的配置,无论内容有多么不同,都可以使用相同的软件进行维护,这将大大简化管理负担。
关于 RESTful API 的访问控制设计的大部分信息都围绕着用户(即不同的用户有不同的访问级别等)。
想象一个没有用户概念的系统。有一堆服务器通过 RESTful API 相互通信。没有客户端 - 我的意思是,对于两个服务器之间的每次交互,其中一个可以被视为“客户端”,但我的观点是所有服务器或多或少是“平等的”,并且每个服务器都可以向许多其他服务器发送请求服务器(反之亦然)。
这与传统的 web/mobile 客户端-服务器架构非常不同。
现在,想象一下并非所有这些服务器实际上都是 100% 平等的。有些人应该可以访问一些 APIs,但不是全部。如何保证这样级别的访问控制?
让我们将您拥有的服务器视为网络中的节点,以避免混淆。当node1向node2发送请求时,那么在那个交互中,node2是服务器,node1是客户端(类似于“用户”)。
因此,从 node2 的角度来看,如果您必须区分 client1 和 client2(可以发送请求的两个可能的节点),根据它们各自可以访问或不可以访问的内容,那么强烈建议为 node2 定义角色映射。
这意味着您将有 key-value 对,其中键是方法,值是角色。
每当 client1 或 client2 请求一个方法时,您将以某种方式确定该方法需要哪些角色,以及 client1 和 client2 是否具有所有必要的角色。
这意味着对于节点2的API,每当接收到请求时,需要执行以下算法:
- 会调用一个中心方法(暂且称之为
APIWrapper
) APIWrapper
找出客户端的角色是什么APIWrapper
找出调用function1
所需的角色,客户端请求的功能- 如果客户端未履行
function1
所需的任何角色,则以未经授权的错误响应并停止进程 - 如果已成功到达此阶段且没有未经授权的错误,则执行
method1
并将其响应传输给客户端
你可能有一个角色林,也就是说,你会有角色树,这取决于访问级别(即你可能有一个单独的角色来上传 xlsx 文件,你可能有一个角色来上传任何文件,因此,在这种情况下,您可能需要上传 xlsx,而客户端将具有上传任何文件的角色,在这种情况下,仍应允许客户端执行给定的操作)。
如果您对角色子类有这样的需求,那么强烈推荐
- 在值部分的角色映射中,您将指定该角色属于哪个角色树(即文件上传)和该角色的级别(即 xlsx)
- 在每个角色树中,如果有一个父P和一个子C,那么就意味着P => C,也就是说,C比P更具体,所以如果角色P存在就意味着这个角色客户端也存在C
- 每个角色都需要有一个签名来唯一标识其在树中的路径,因此到达它的复杂度为 O(log(N)) 而不是 O(N)
不用说,分配或撤销角色的方式需要安全且一致。
所以,我们站在node2的角度是这样想的。然而,node2 本身也可能是其他节点的客户端。问题类似。
但是,如果 server1 gains/loses 在节点 1 上扮演角色,是否会触发 server1 gains/loses 其他服务器的角色?如果是这样,那么您还需要某种方式来同步角色,也许通过 cron 作业定期进行。
最后,如果可以将定义、分配和撤销角色的方式标准化,那就太好了。因为这样一来,每个服务器的配置,无论内容有多么不同,都可以使用相同的软件进行维护,这将大大简化管理负担。