我正在为拥有不同权限的消费者设计REST API。我知道资源的表示不应该根据用户而改变。因此,我试图确定哪种方法最好:
GET - 列出所有文档的集合 - 仅限管理员。:
/ API /文件
GET - 列出所有文档的集合 - 任何有权访问文档123的用户
/ API /文档/ 123
对于普通用户,端点应为
列出用户12的所有文档
/ API /用户/ 12 /文件
文档123假设用户12具有访问权限
/ API /文档/ 123
OR ...端点应如下所示,并使用查询字符串过滤器:
/ API /文件?用户= 12
/ API /文档/ 123
答案 0 :(得分:5)
在这种情况下,您可以只使用两个端点(和一个标头!)。确保/documents
的API返回Vary: Authorization
标头。然后你可以使用
GET /api/documents // return all docs the logged-in user can see
GET /api/documents?userId=bob // return all of bob's docs that the logged-in user can see
GET /api/documents/123 // return doc 123 if the logged-in user can see it
将用户嵌套为la GET /api/users/bob/documents
并非完全不合理。我发现最终用户更难学习具有大量端点的API,我觉得嵌套方法往往会创建许多端点。从概念上讲,它更容易转到/documents
并查看可以过滤的内容,而不是查看每个端点并查看它具有的过滤器。
答案 1 :(得分:2)
我会将业务逻辑和授权逻辑完全分开。如果要检索文档XYZ,则不会将用户ID作为HTTP参数传递。
您建议/api/documents?user=12
,但实际上它应该是/api/documents
。用户信息应来自身份验证层。
同样,授权应完全分开。原因是:
API应仅反映您关注的业务对象,例如在这种情况下的文档(可能还希望用户显示用户配置文件......)。
要处理身份验证,请使用容器的标准技术(例如HTTP基本身份验证)或通过专用框架使用高级身份验证技术(OAuth ..)。
要处理授权,请使用过滤器,拦截器。在Java世界中(JAX-RS实现REST),请查看Jersey interceptors and filters。然后,您希望拦截器(或策略执行点 - PEP)查询外部授权服务(或策略决策点)。
进一步了解基于属性的访问控制模型ABAC和可扩展访问控制标记语言XACML,它解释了如何在不混合业务逻辑的情况下控制对REST API的访问授权逻辑。