实现HATEOAS的rest API的权限

时间:2014-07-09 23:55:07

标签: api rest hateoas hypermedia

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

举个例子:

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

基础rest API具有以下资源:

/作业/ {ID} 哪个接受GET和PUT。 GET返回作业模型,PUT接受作业模型作为请求体:

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

接受的工作状态可以是:休眠|跑步|暂停了|停止。

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

开始,暂停,停止

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

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

通知app / 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-service

3 个答案:

答案 0 :(得分:5)

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

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

或者,如果想要在每个响应中包含所有链接但是明确指定哪些是允许的,哪些不是,如果使用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"
}

答案 1 :(得分:1)

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

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

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

答案 2 :(得分:0)

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

为此目的,IANA create-formedit-formdelete-formlink relations

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