简体   繁体   English

实现HATEOAS的rest API的权限

[英]Permissions on a rest API implementing HATEOAS

I'm trying to figure out the right way to handle permissions in a single page app that talks directly to several RESTful APIs, that implement HATEOAS. 我正在尝试找出在单页面应用程序中处理权限的正确方法,该应用程序直接与几个实现HATEOAS的RESTful API对话。

As an example: 举个例子:

"As a user of my application I can view, start and pause jobs but not stop them." “作为我的应用程序的用户,我可以查看,启动和暂停作业,但不能阻止它们。”

The underlying rest API has the following resource: 基础rest API具有以下资源:

/jobs/{id} Which accepts GET and PUT. / jobs / {id}接受GET和PUT。 The GET returns a job model and the PUT accepts a job model as a request body in the form: GET返回作业模型,PUT接受作业模型作为请求体:

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

Accepted job states can be: dormant | 接受的工作状态可以是:休眠| running | 跑步| paused | 暂停了| stopped. 停止。

The requirement says that on the UI I must have the buttons: 要求说在UI上我必须有按钮:

START, PAUSE, STOP 开始,暂停,停止

... and only display based on the logged in user's permissions. ...并且仅基于登录用户的权限进行显示。

From the API perspective everything works as the underlying logic on the server makes sure that the user cannot update the state to a STOPPED state when a request is made (a 401 is returned maybe). 从API的角度来看,一切都可以作为服务器上的底层逻辑,确保用户在发出请求时无法将状态更新为STOPPED状态(可能会返回401)。

What is the best way to inform the app / UI of the user's permissions, so it can hide any buttons that the user has no permission to action? 通知app / UI用户权限的最佳方法是什么,因此它可以隐藏用户无权操作的任何按钮?

Should the API provide a list of permissions, maybe something like : 如果API提供权限列表,可能类似于:

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

OR should the API change so that the permissions are reflected in the HATEOS links maybe something like : 或者应该更改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"
}

Or should it be done in a completely different way? 还是应该以完全不同的方式完成?

UPDATE UPDATE

I've found the following article which suggests an answer: https://softwareengineering.stackexchange.com/questions/215975/how-to-handle-fine-grained-field-based-acl-permissions-in-a-restful-service 我发现以下文章提出了一个答案: https//softwareengineering.stackexchange.com/questions/215975/how-to-handle-fine-grained-field-based-acl-permissions-in-a-restful-服务

I would go with the latter: Imply permissions based on which links are present. 我会选择后者:根据存在的链接暗示权限。

If the link isn't there, the user can't access the resource/perform the action. 如果链接不存在,则用户无法访问资源/执行操作。 If it is, they can. 如果是,他们可以。 That's what I'd do, because it's simple and clean and leaves little to the discretion of the front-end code. 这就是我要做的事情,因为它简单而干净,并且几乎没有前端代码的自由裁量权。 Decoupling, yo. 解耦,哟。

Alternatively, if you do want to include all the links in each response but explicitly specify which are allowed and which aren't, if you use a format such as HAL to write your links, you could extend it with a flag on each link like so: 或者,如果您确实希望在每个响应中包含所有链接但是明确指定允许哪些链接,哪些不允许,如果您使用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"
}

I would go with the latter. 我会选择后者。 The reason I don't like the former is because you are creating extra work for the client by requiring it to figure out the mapping between permissions and the resources they permit access to. 我不喜欢前者的原因是因为您要为客户创建额外的工作,要求它找出权限与它们允许访问的资源之间的映射。 If you use hateoas and check for the presence of relation types, this mapping is done for you by the server. 如果您使用hateoas并检查是否存在关系类型,则服务器会为您完成此映射。 It also means the uris can change without breaking the client. 这也意味着uris可以在不打破客户的情况下改变。

I recently wrote a blog post on this area: 我最近写了一篇关于这个领域的博客文章:

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

You should be using forms, not links, to provide state transition hypermedia. 您应该使用表单而不是链接来提供状态转换超媒体。 If you cannot provide forms in your media type, provide links to URIs which use another media type that supports forms, such as XHTML. 如果您无法在媒体类型中提供表单,请提供指向使用支持表单的其他媒体类型(如XHTML)的URI的链接。

IANA has link relations for create-form , edit-form and delete-form for this purpose. 为此,IANA为create-formedit-formdelete-form提供了链接关系

Also, please do not use start and pause as real link relations. 另外,请不要使用startpause作为真正的链接关系。 If you define them yourself, they must be URIs (preferably HTTP URLs, but any URI under your control will suffice). 如果您自己定义它们,它们必须是URI(最好是HTTP URL,但是您控制下的任何URI都可以)。 start has a completely different meaning to what you're using it for, and pause is not defined. start与你正在使用它的含义完全不同,并且没有定义pause

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM