6

我试图找出在单页应用程序中处理权限的正确方法,该应用程序直接与几个实现 HATEOAS 的 RESTful API 对话。

举个例子:

“作为我的应用程序的用户,我可以查看、启动和暂停作业,但不能停止它们。”

底层的 REST API 有以下资源:

/jobs/{id} 接受 GET 和 PUT。GET 返回一个作业模型,PUT 接受一个作业模型作为请求主体,格式如下:

{
 "_links" : {
     "self" : "/jobs/12345678"
 }
 "id" : 12345678,
 "description" : "foo job",
 "state" : "STOPPED"
}

接受的工作状态可以是:休眠 | 运行 | 暂停 | 停了下来。

要求说在 UI 上我必须有按钮:

开始、暂停、停止

...并且仅根据登录用户的权限显示。

从 API 的角度来看,一切都是服务器上的底层逻辑,确保用户在发出请求时无法将状态更新为 STOPPED 状态(可能返回 401)。

通知应用程序/ UI 用户权限的最佳方式是什么,以便它可以隐藏用户无权操作的任何按钮?

API 是否应该提供权限列表,可能类似于:

{
 "_links" : {
     "self" : "/permissions",
     "jobs" : "/jobs"
 }
 "permissions" : { 
     "job" : ["UPDATE", "DELETE"], 
     "job-updates" : ["START", "PAUSE"] 
  }
}

或者 API 是否应该更改,以便权限反映在 HATEOS 链接中,可能类似于:

{
 "_links" : {
     "self" : "/jobs/12345678",
     "start" : "/jobs/12345678/state?to=RUNNING", 
     "pause" : "/jobs/12345678/state?to=PAUSED", 
 }
 "id" : 12345678,
 "description" : "foo job",
 "state" : "DORMANT"
}

还是应该以完全不同的方式完成?

更新

我发现以下文章提出了答案: https ://softwareengineering.stackexchange.com/questions/215975/how-to-handle-fine-grained-field-based-acl-permissions-in-a-restful-服务

4

3 回答 3

6

我会选择后者:根据存在的链接来暗示权限。

如果链接不存在,则用户无法访问资源/执行操作。如果是,他们可以。这就是我要做的,因为它简单而干净,几乎没有前端代码的自由裁量权。脱钩,哟。

或者,如果您确实希望在每个响应中包含所有链接,但明确指定哪些是允许的,哪些是不允许的,如果您使用HAL等格式来编写链接,您可以在每个链接上使用一个标志来扩展它,例如所以:

{
    "_links" : {
        "self" : {
            "href":"/jobs/12345678",
            "allowed":false
        },
        "start" : {
            "href":"/jobs/12345678/state?to=RUNNING",
            "allowed":false
        },
        "pause" : {
            "href":"/jobs/12345678/state?to=PAUSED",
            "allowed":false
        }
    },
    "id" : 12345678,
    "description" : "foo job",
    "state" : "DORMANT"
}
于 2014-07-10T14:05:04.727 回答
2

我会选择后者。我不喜欢前者的原因是因为您通过要求客户端找出权限与他们允许访问的资源之间的映射来为客户端创建额外的工作。如果您使用 hateoas 并检查是否存在关系类型,则此映射由服务器为您完成。这也意味着 uri 可以在不破坏客户端的情况下更改。

我最近写了一篇关于这个领域的博客文章:

https://www.opencredo.com/2015/08/12/designing-rest-api-fine-grained-resources-hateoas-hal/

于 2015-08-13T19:14:10.667 回答
0

您应该使用表单而不是链接来提供状态转换超媒体。如果您无法在您的媒体类型中提供表单,请提供指向使用另一种支持表单的媒体类型(例如 XHTML)的 URI 的链接。

IANA为和为此目的建立了链接关系。create-formedit-formdelete-form

另外,请不要使用startpause作为真正的链接关系。如果您自己定义它们,它们必须是 URI(最好是 HTTP URL,但您控制的任何 URI 都可以)。start与您使用它的含义完全不同,并且pause没有定义。

于 2017-02-21T11:34:00.610 回答