简体   繁体   English

REST API设计中的授权和查询字符串

[英]Authorization and the query string in REST API design

We have a design where a user has access to products, but only in a certain category. 我们有一个设计,用户可以访问产品,但只能在某个类别中访问。

A superuser can list all products in all categories with a simple GET request, such as GET /products . 超级用户可以使用简单的GET请求列出所有类别中的所有产品,例如GET /products

Simple filtering already exists via the query string, so the superuser can already restrict his search to category N by requesting GET /products?category=N . 通过查询字符串已经存在简单过滤,因此超级用户已经可以通过请求GET /products?category=N将其搜索限制为类别N.

Say that user X is authenticated, and user X has access to products with category of 3 . 假设用户X已通过身份验证,用户X可以访问类别为3

Should an API server: 应该是API服务器:

  1. mandate that the user pass the filter for the appropriate category -- ie require GET /products?filter=3 , and GET /products would fail with 403 Forbidden ? 要求用户通过适当类别的过滤器 - 即需要GET /products?filter=3GET /products会因403 Forbidden而失败? -- or - 要么
  2. expect a simple GET /products and silently filter the results to those that the user is authorized to access? 期待一个简单的GET /products并默默地将结果过滤到用户有权访问的结果?

expect a simple GET /products and silently filter the results to those that the user is authorized to access? 期待一个简单的GET /产品,并默默地将结果过滤到用户有权访问的结果?

Changing the representation of a resource depending on which user is looking at it strikes me was a Bad Idea [tm]. 根据哪个用户正在查看它来改变资源的表示形式对我来说是一个坏主意[tm]。

Consider, for instance, the use case where a uri gets shared between two users. 例如,考虑两个用户之间共享uri的用例。 They each navigate to the "same" resource, but get back representations of two different entites. 它们各自导航到“相同”资源,但返回两个不同实体的表示。

Remember - here's what Fielding had to say about resources 请记住 - 这就是菲尔丁对资源所说的话

The key abstraction of information in REST is a resource. REST中信息的关键抽象是一种资源。 Any information that can be named can be a resource: a document or image, a temporal service (eg "today's weather in Los Angeles"), a collection of other resources, a non-virtual object (eg a person), and so on. 可以命名的任何信息都可以是资源:文档或图像,临时服务(例如“洛杉矶的今天天气”),其他资源的集合,非虚拟对象(例如人)等等。 In other words, any concept that might be the target of an author's hypertext reference must fit within the definition of a resource. 换句话说,任何可能是作者超文本引用目标的概念都必须符合资源的定义。 A resource is a conceptual mapping to a set of entities, not the entity that corresponds to the mapping at any particular point in time. 资源是到一组实体的概念映射,而不是与任何特定时间点的映射相对应的实体。

Now, there are conceptual mappings which depend on the perspective of the user (eg "today's weather in my city"). 现在,存在依赖于用户视角的概念映射(例如“ 我所在城市的今天的天气”)。 But I'm a lot more comfortable addressing those by delegating the work to another resource (Moved Temporarily to "today's weather in Camelot") than I am in treating the authorization credentials as a hidden part of the resource identifier. 但是通过将工作委托给另一个资源(临时移动到“Camelot中的今天的天气”)而不是将授权凭证视为资源标识符的隐藏部分,我更方便地解决这些问题。

If consumers of your api are arriving at this resource by following a link, then 403 Forbidden on the unfiltered spelling is fine. 如果您的api的消费者通过链接到达此资源,那么未经过滤的拼写403 Forbidden就可以了。 On the other hand, if consumers are supposed to be bookmarking this URI, then implementing it as a redirecting dispatcher may make more sense. 另一方面,如果消费者应该将此URI加入书签,那么将其实现为重定向调度程序可能更有意义。

The redirecting approach is consistent with remarks made by Fielding in a conversation about content negotiation on the rest-discuss list in 2006 重定向方法与Fielding 在2006年关于其余讨论列表的内容协商对话中所做的评论是一致的

In general, I avoid content negotiation without redirects like the plague because of its effect on caching. 一般来说,我避免内容协商而没有像瘟疫这样的重定向,因为它对缓存有影响。

Eg, if you follow a link to 例如,如果你点击链接

http://www.day.com/ http://www.day.com/

then the site will redirect according to the user's preference to one of 然后该网站将根据用户的偏好重定向到其中一个

Both of the solutions are perfectly valid. 这两种解决方案都非常有效。 You can always hide things when the user does not have the permission to see them. 当用户无权查看时,您始终可以隐藏内容。 This means, that you can display a filtered representation of /products by the actual user, or you can hide the /products resource and give link only to the /products?filter=3 resource. 这意味着,您可以显示实际用户对/products的过滤表示,或者您可以隐藏/products资源并仅链接到/products?filter=3资源。 I don't think there is a best practice here, since both solutions are easy to implement. 我不认为这里有最好的做法,因为这两种解决方案都很容易实现。

@VoiceOfUnreason: @VoiceOfUnreason:

Apparently you did not read Fielding's work carefully enough. 显然你没有仔细阅读菲尔丁的工作。

Changing the representation of a resource depending on which user is looking at it strikes me was a Bad Idea [tm]. 根据哪个用户正在查看它来改变资源的表示形式对我来说是一个坏主意[tm]。

The representation depends on the whole request, not just on the GET /resource part. 表示取决于整个请求,而不仅仅取决于GET /resource部分。 The Authorization header is part of the HTTP request as well. Authorization标头也是HTTP请求的一部分。 So changing the representation depending on the Authorization header is valid in REST. 因此,根据Authorization标头更改表示在REST中是有效的。 It is just the same as changing the representation depending on the Accept header. 它与根据Accept标头更改表示形式相同。 Or do you say that we should serve XML even if somebody requests for JSON? 或者你说我们应该提供XML,即使有人要求JSON? It is a huge mistake to think that a single resource can have only a single representation. 认为单个资源只能有一个表示是一个巨大的错误。 Another mistake to return a broken link to the client and let them waste resources by sending pointless HTTP messages... 将断开的链接返回给客户端并通过发送无意义的HTTP消息让他们浪费资源的另一个错误......

Consider, for instance, the use case where a uri gets shared between two users. 例如,考虑两个用户之间共享uri的用例。 They each navigate to the "same" resource, but get back representations of two different entites. 它们各自导航到“相同”资源,但返回两个不同实体的表示。

REST is for machine to machine communication and not for human to machine communication! REST用于机器到机器的通信,而不用于人机交流! The browser is not a REST client. 浏览器不是REST客户端。 Or did you mean that a facebook bot will share the link with a google crawler? 或者你的意思是Facebook机器人将与谷歌搜索器共享链接? Such a nonsense... 这样的废话......

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

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