我应该在RESTful服务中拥有资源的多个视图/端点吗?

时间:2014-01-03 17:23:08

标签: rest authorization entity-relationship

假设我正在创建一个RESTful服务来处理我在网上的仓库订单。

  • 我想允许客户创建帐户
  • 我希望客户管理员能够为其办公室中的其他用户创建帐户
  • 我想允许客户用户创建订单
  • 我希望网站管理员能够创建和管理所有客户帐户
  • 我希望网站管理员能够创建和管理所有用户
  • 我希望网站管理员能够创建和管理所有订单

鉴于这些要求。我最初的想法是以这种方式设计端点。

# to request a new customer account
/customers/request {POST}
# create and view customers - limited to admins
/customers {GET, POST}
# view customer info, update a customer
/customers/{customer_id} {GET, PATCH}
# create and view orders for a customer
/customers/{customer_id}/orders {GET, POST}
# view and update order for a customer
/customers/{customer_id}/orders/{order_id} {GET, PATCH}

我非常有信心,这些道路是有道理的,并遵循一般的宁静想法。但是,我不确定如何处理用户端点。问题是,我希望客户管理员能够创建可以使用其客户帐户创建订单的用户。客户管理员在哪里发布POST以实现此目的?我有几个想法。 在answer之后,我想到了这一点。

# creation of users always done through this endpoint no matter what the
# authenticated user's role is
/users { GET, POST }
# associate user with customer
/customers/{customer_id}/user_memberships { GET, POST }

此方法的问题是客户帐户的管理员如何获得与客户帐户关联的用户的ID。通过仅检索属于其客户帐户的用户来过滤/用户上的任何GET请求。但是,由于用户将在成员资格之前创建,因此他们永远无法查看用户。 我还想知道只有两个端点来创建用户。

# create a user for a customer account
/customers/{customer_id}/users {GET, POST}
# root users endpoint only accessible to admins
/users {GET, POST}
# return same user
/users/1
/customers/{customer_id}/users/1

它基本上归结为使用客户URL前缀作为授权方式。让两个端点使另一个端点无效似乎有点奇怪。如果根端点只是子资源端点的视图怎么办?

# view all users in system - admin only
/users {GET}
# create & view admin users
/admin/users {GET, POST}
# create internal office users
/locations/{location_id}/users { GET, POST }
# create customer users
/customers/{customer_id}/users { GET, POST }

在这种情况下,我们仍然可以在子资源上缓存GET响应,因为它们不会更改,除非在子资源的特定ID上有POST或PATCH / DELETE。

这种风格似乎对订单也有意义。管理员可以查看所有订单,即使他们在技术上属于给客户。

# admin can view all orders
/orders?customer_id=1234
/orders

我有点像根资源是子资源视图的想法,允许基于URL更容易的授权。

所以,我想在所有这些之后,我真正的问题是:

是否有多个端点表示同一资源是一个问题,即使其中一个端点只是子资源的聚合视图,并且不允许通过该端点创建资源?

2 个答案:

答案 0 :(得分:4)

您不应混淆API的设计,REST原则和授权需求。您应该以这样的方式设计您的API:

  • 易于使用
  • 易于维护
  • 易于理解

RESTful API设计方法试图解决这些不同的问题。 RESTful方法是识别您拥有的对象,它们的状态以及它们可能的转换。

这就是它停止的地方。现在,你想知道授权。您希望能够控制用户可以对给定记录执行的操作,具体取决于用户是谁(管理员,客户......)以及目标资源是什么(客户记录......)。

您需要做的是以松散耦合的方式在REST API之上部署授权框架。换句话说,您希望外部授权。您绝对不希望直接在API中构建授权。想象一下,您突然有了新的授权规则/约束:您必须重新编码您的API。这样做可以打破所有客户。这将导致糟糕的用户体验。

因此,我们已经确定您需要外部授权。大。有什么不同的方法呢?这取决于您使用的语言和框架。

您可以使用:

  • Java中的Spring Security
  • Yii in PHP
  • Ruby中的CanCan
  • ......还有更多

您还可以实现自己的过滤器,例如在REST端点前面的Java中的Servlet过滤器。

最后,您可以转向基于XACML的基于属性的完整授权模型。有几种开源和供应商的替代品。如果您不熟悉基于属性的访问控制或XACML,请查看以下链接:

使用XACML,您可以集中定义策略,例如:

  • 管理员可以查看所有客户帐户
  • 管理员可以修改他/她分配到的客户帐户
  • 客户只能查看和编辑自己的帐户

然后在授权服务中评估策略(在XACML中称为策略决策点)。授权服务公开了一个二进制授权API,您的API可以调用它:可以用户Alice查看记录foo吗?

使用基于策略和使用XACML的外部授权,可以实现业务逻辑(业务API)与授权逻辑之间的松散耦合,您可以更轻松地维护和更新。

答案 1 :(得分:0)

根据我的理解,对于前。你想要特定的customerId你希望这个客户只查看其用户不能创建只由admin创建的用户,所以这也可以使用spring security来完成,这肯定会产生问题所以你有根据您的要求对客户进行分类。