根据访问级别忽略或不忽略API端点参数

时间:2017-03-14 20:39:17

标签: api

我正在开发一个返回产品列表的API端点:

"api/products"

端点接受以下参数:

page_size
page_number 

每个产品都有一个名为IsApproved的布尔属性。

在普通用户使用的Web应用程序中,我总是希望只返回已批准的产品...在管理员使用的网络管理员应用程序中,我想要返回所有产品,已批准或未批准...

我的想法是添加一个名为:

的新参数(枚举)
ApprovedStatus

值为ApprovedNotApprovedAll

在每个API调用中,我会检查用户权限...如果是admin,我会考虑此参数的值。如果没有,那么我将始终只返回批准的产品。

另一种解决方案是拥有不同的端点......

有关采取哪种方法或有其他选择的建议吗?

4 个答案:

答案 0 :(得分:1)

你对自己的想法是对的:

  1. 您可以为管理员创建一个新的终端,它将返回所有产品
  2. 您可以使用某种授权(例如授权标头)来检查是通过管理员还是普通用户调用API。然后,您可以在内部进行路由以获取所有产品或仅使用IsApproved产品。
  3. 您可以在API前添加代理以路由到正确的操作,但也可以直接在API中实现,但我认为第二种解决方案更容易。

答案 1 :(得分:1)

添加一个属性是一个坏主意。

在我看来,添加另一个终点是非常好的。因为它会增加管理端点的保护。

否则,由于它是一个Web应用程序,只需设置一个cookie和一个会话来识别和分离管理员和用户。

答案 2 :(得分:1)

批准状态是产品的一部分,因此,在完美的REST环境中,由于您访问的是相同的资源,因此您根本不需要不同的端点。

然后,为了根据属性值过滤资源,我认为惯例是,如果您将该属性指定为查询参数,它将只返回与该值匹配的属性,如果不是,则返回所有属性,所以我认为不需要使用一些特殊值来定义特殊的ApprovedStatus参数。只需按isApproved进行查询!

最后,关于如何处理授权。我认为,这应该在一个完全独立的层**处理。如果涉及授权,您应该有一个显式授权层,该层确定对于特定资源和用户,是否授予了访问权限。这意味着将触发查询,如果查询生成的某个资源未能被触发查询的用户授权,则会从结果中取出。这样就完成了您想要的行为,而没有任何代码根据特定查询参数检查特定用户,这很好,因为如果明天您有另一个公开此对象的端点,您将不必执行两次相同的授权策略。 Pundit是如何优雅地使用Ruby实现这一目标的完美示例。

**当然,这种方法会不必要地从数据库中检索数据,这对您来说很重要,并且还可以打开您的终端以进行计时攻击。即便如此,我会考虑解决这些过早优化的问题,除非你有充分的理由,否则应该忽略这些问题。

答案 3 :(得分:0)

遵循最不惊讶的原则,我赞成为管理员用户添加第二个端点。这样你就会:

GET /api/products       (for regular users)
GET /api/admin/products (for admins)

这样可以很好地分离您的代码和API文档,并且所有特定于管理员的身份验证详细信息都可以存在于“admin”命名空间下。

每个API调用背后的意图也更加清晰,这有助于开发人员;并且意味着您可以在您跟踪的任何使用统计数据中区分管理员与常规使用情况。

使用ApprovedStatus,我认为这里的具体细节并不重要,但是 - 考虑使用API​​的开发人员可能合理期望/假设 - 这样做会很好:

  • 确保ApprovalStatus参数名称与您为每个product对象返回的“审批”的属性名称匹配
  • 如果未指定,则默认为“已批准”
  • 在指定无效值时提醒用户,或者他们无权访问

底线:回答您的标题问题 - 我认为忽略用户输入是不好的做法......有时候。设计你的API,以便可以传入输入的区别是非常清楚的;如果您收到技术上可接受的的输入值,但不是用户请求的方式或其访问级别,则始终提醒用户。忽略明显错误的值(例如,不存在的参数)是另一个故事,可以用于将来的证明或向后兼容。