如何表示RESTful属性级别访问控制?
我绞尽脑汁、谷歌搜索了好多年,却没有想出一个令人满意的方法来处理这个问题。我想编写一个很好的完全 RESTful 服务来返回资源,但是您有权读取(或写入)的数据根据您的角色而根据资源而变化。例如,用户可能能够在其个人资料上看到他们的私人电话号码,网站管理员也可以,但其他用户则看不到。匿名访问者可能无法看到其他用户的真实姓名,但其他用户(和网站管理员)可以。大约有 4 或 5 个访问级别以及关于哪些属性可以读取或写入的规则。我对写作感到满意,因为客户端可以 PUT 更改,并且服务器不一定接受全部(或根本)它们,但阅读是我的问题。
<user>
<id>jimbob</id>
<real-name>Jim Roberts</real-name> <!-- only logged-in users should see this -->
<phone-number>+1 42424151</phone-number> <!-- only the user and admin users should see this -->
</user>
我希望拥有一个可正确缓存的用户配置文件资源,其中包含所有公共数据,但如何对只有某些用户才能看到的所有内容进行建模?我最多可以有 4 个指向额外信息的链接,其中大多数会为大多数用户返回未经授权的错误,每个链接都保存与角色相关的额外信息。但这似乎非常低效,并且还将客户与角色概念联系在一起,而以前他们需要了解的只是用户。还有更好的想法吗?
<user>
<id>...</id>
<link rel="more" href="extra-user-profile-data-for-logged-in-users"/>
<link rel="more" href="extra-user-profile-data-for-senior-users"/>
<link rel="more" href="extra-user-profile-data-for-admin-users"/>
<link rel="more" href="extra-user-profile-data-for-superadmin-users"/>
</user>
请注意 - 我没有遇到任何身份
- 验证
- 资源级访问控制
- 在服务器端实现访问控制或授权
我正在努力
- 解决如何表示在“正常”HTML 网站中对不同人来说不同的资源,在真正宁静的方式。
这似乎是每个人都应该遇到的一个非常常见的问题,但我找不到任何相关内容!请帮忙!
I've been wracking my brain and googling away for ages without coming up with a satisfactory way of handling this. I want to write a nice fully RESTful service to return resources, but the data you have permission to read (or write) variest per-resource depending on your role. So, for example, a user may be able to see their private phone number on their profile, and so may a site administrator, but another user wouldn't. An anonymous visitor might not be able to see another user's real name, but other users (and the site admin) could do. There are around 4 or 5 access levels and rules about which attributes can be read or written. The writing I'm happy with as the client can PUT changes and the server is not bound to accept them all (or at all), but the reading is my problem.
<user>
<id>jimbob</id>
<real-name>Jim Roberts</real-name> <!-- only logged-in users should see this -->
<phone-number>+1 42424151</phone-number> <!-- only the user and admin users should see this -->
</user>
I want to have a properly cacheable user-profile resource which contains all the public data, but how do I model all the stuff that only certain users can see? I could up to 4 links to extra information, most of which would return Unauthorized errors for most users, with each link holding the extra information related to a role. But that seems very inefficient and also ties the clients into the role concept, when previously all they needed to know about was users. Are there any better ideas?
<user>
<id>...</id>
<link rel="more" href="extra-user-profile-data-for-logged-in-users"/>
<link rel="more" href="extra-user-profile-data-for-senior-users"/>
<link rel="more" href="extra-user-profile-data-for-admin-users"/>
<link rel="more" href="extra-user-profile-data-for-superadmin-users"/>
</user>
Please note - I am not struggling with any of
- Authentication
- Resource-level access control
- Implementing access control or authorisation on the server side
I am struggling with
- How to represent resources which in a 'normal' HTML website would appear different to different people, in a truly RESTful way.
This seems like a really common problem that everyone should be having, but I can't find anything on it! Please help!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果您考虑一下,管理客户端看到的
User
资源(所有字段都可见)与匿名或权限较低的客户端看到的完全相同的资源 。 URI 是相同的,但他们看到的表示不同。这类似于让客户端通过
Accept
标头请求将表示形式编码为 JSON 而不是 XML:服务器可以同意接受该请求,但不一定必须这样做。在您的情况下,服务器应该返回适合客户端提供的凭据的表示形式。因此,管理员可能会收到
application/vnd.yourcompany.user.full+xml
媒体类型中的内容,作为User
资源上的 GET 返回的正文,并且它将包含所有可能的字段。但是,匿名用户可能会收到编码为
application/vnd.yourcompany.user.limited+xml
的有效负载,您的文档会清楚地将其描述为可能包含也可能不包含来自完整
版本。客户端必须使用灵活的解码器或模式来容忍某些元素根本不存在。或者,您可以返回所有资源的信息,但使用特殊字段值来指示特定值已被编辑:
您可以为每个角色创建一个媒体类型,但这会在您的安全方案和表示之间引入强耦合,并且这可能是不可取的。从长远来看,使用字段省略或值编辑的灵活表示方案将更易于维护。
最终做出的决定是是否返回指向其他资源的链接,这些资源根据客户端提供的凭据无法导航。在我看来,即使这些凭据不起作用,这些链接也应该始终返回。为什么?因为理论上客户端在调用这些 URI 时可以提供其他凭据。即使他们不这样做,由此产生的
401
挑战也可能会导致客户最终提供它们。但如果他们甚至从未获得 URI,他们将无法做出该决定。If you think about it, the
User
resource that an admin client sees (with all of the fields visible) is exactly the same resource that an anonymous or less-privileged client sees. The URI is identical, but the representation they see is different.It's similar to having the client request the representation be encoded in JSON instead of XML via the
Accept
header: the server can agree to honor that request but it doesn't necessarily have to. In your case the server should return a representation appropriate to the client's supplied credentials.Therefore, an admin might receive the content within a media type of
application/vnd.yourcompany.user.full+xml
as the body returned by a GET on yourUser
resource, and it will contain all the fields possible.However an anonymous user might receive the payload encoded as say,
application/vnd.yourcompany.user.limited+xml
which your documentation would describe clearly as a representation that may or may not contain all the elements from thefull
version. The client would have to use a flexible decoder or schema that would tolerate certain elements not being present at all.Alternatively, you could return all the resource's information but use a special field value to indicate that a particular value was redacted:
You could create a media type for each role, but that would introduce a strong coupling between your security scheme and your representations, and that's probably not desirable. Flexible representation schemes that use either field omission or value redaction would be more maintainable in the long term.
The final decision to make is whether or not to return links to other resources which would not be navigable based on the credentials the client supplied. In my opinion those links should always be returned, even if those credentials would not work. Why? Because the client could theoretically supply other credentials when calling those URIs. Even if they don't, the resulting
401
challenge might lead the client to eventually provide them. But if they never even get the URI, they'd be prevented from ever making that decision.