授权和构建RESTful后端的正确方法是什么?
很多关于RESTful Web服务的例子都没有考虑到今天许多应用程序都是多用户的问题。
想象一下, 多用户后端暴露了一个RESTful API 。 后端数据体系结构使用共享数据库和共享模式。 每个表格将包含对tenant_id
的引用:
+-------------+----+-----------------+
| tenant_name| id | shared_secret |
+-------------+----+-----------------+
| bob | 1 | 2737sm45sx543 |
+-------------+----+-----------------+
| alice | 2 | 2190sl39sa8da |
+-------------+----+-----------------+
+-------------+----+-------+-----------+
| pet_name | id | type | tenant_id |
+-------------+----+-------+-----------+
| fuffy | 1 | dog | 1 |
+-------------+----+-------+-----------+
| kerry | 2 | cat | 2 |
+-------------+----+-------+-----------+
问题1 :有三个或更多客户端应用程序(即Android,iOS和Web App)与RESTful后端交互时 ,您将如何对后端执行身份验证?
RESTful backend, API, HTTP-Verbs, shared database and schema
|
|
+---- Web Application (Client 1)
| |
| + Alice
| |
| + Bob
|
+---- Android Application (Client 2)
| |
| + Alice
| |
| + Bob
|
+---- iOS Application (Client 3)
| |
| + Alice
| |
| + Bob
|
每个客户应允许Alice和Bob管理她/他的宠物。 每个客户端都是一个GUI,它将使用(内部发出HTTP请求)后端。 问题:每个客户如何才能对后端进行身份验证?
假设HMAC(它完全是RESTful,没有会话):这种方法涉及用共享密钥签署有效载荷(从未通过线路发送)。 每个客户都应该拥有自己的tenant
表副本(其中包含shared_secret
字段)?
Android App -> Client Sign -> Signed Request -> Backend -> Result
Web App -> Client Sign -> Signed Request -> Backend -> Result
问题2 :资源URI应该是什么样的?
以下是获取鲍勃宠物的两种可能性:
可能性#1: Authorization
标题为您提供租户的(唯一)名称:
GET /pets HTTP/1.1
Host: www.example.org
Authorization: bob:c29kYW9kYSBhb2lzYWRoIGYgZDUzNDUz
可能性#2。 tenant_id
作为查询参数发送:
GET /pets/tenant_id=1 HTTP/1.1
Host: www.example.org
Authorization: bob:c29kYW9kYSBhb2lzYWRoIGYgZDUzNDUz
第1部分
(大声思考:你是否已经决定使用HTTP和HMAC?如果是这样,你为什么问我们?)
我会建议使用基本身份验证的HTTPS。 简单。 毕竟这对Stripe来说已经足够了。
参考文献:
更新 :以下是关于如何处理auth的一些额外细节:
每个客户端应用程序都将使用API密钥联系服务。 使用HTTPS和基本身份验证,客户端将提供其API密钥作为基本身份验证用户名。 它不需要提供密码,因为它使用的是HTTPS。 您需要为每个应用程序(Web应用程序,Android,iOS)分配一个API密钥,我看到两种方式:
答:一种选择是为每个用户提供一个在客户端之间共享的API密钥。
B.另一种选择是给每个客户一个独特的应用程序。)
但是,你如何首先获得客户的钥匙? 构建“关键请求”API端点。 我建议给每个客户端一个“启动器”键,只用于联系这个端点。 (起始键不允许其他访问。)当用户第一次使用客户端时,他/她必须进行身份验证。 客户端将其传递给“密钥请求”端点,以便它可以生成与用户关联的密钥。 从那以后,每个客户端都有一个客户端绑定的API密钥。
第2部分
考虑给每个租户一个子域名。 如果您使用Rails(或者可能是任何现代Web栈),则可以使用该子域来查找租户ID。 然后你的API可以像这样使用:
GET http://tenant1.app.co/pets
GET http://tenant2.app.co/pets
GET http://tenant3.app.co/pets
参考文献(Rails特有的,但应该对整个Web栈有所帮助):
请注意:正如您的示例所示,为了简单起见,我不会为不同的租户重复使用相同的宠物ID。 例如,以下是一个简单的方法:
GET http://tenant1.app.co/pets/200
GET http://tenant2.app.co/pets/201
GET http://tenant3.app.co/pets/202
我所描述的方法比传递tenant_id
作为查询参数要干净得多。 此外,使用tenant_id
作为参数感觉不对。 正如我在Ruby和Richardson的“RESTful Web Services”中所读到的,我喜欢使用更多“算法”的参数。
参考文献:
通过“多租户”,你是否只是指应用程序/ Web服务用户? 多租户通常意味着更复杂的事情msdn.microsoft.com/en-us/library/aa479086.aspx。
您需要使用您的Web服务来验证每个用户。 这可以通过SSL的基本http身份验证完成。
从Web服务的角度来看,您将对所有三个客户端执行相同的身份验证。 该服务不关心客户的类型 - 这就是要点。 这可能是因为你需要为你的客户提供不同的表述,例如XHTML或JSON。 我喜欢将事情简单化并始终选择JSON。
对于资源,管理它们的最简单方法是将用户资源作为最高级别,然后将所有资源链接到每个用户,例如
GET users/fred/pets - returns all pets for user fred
GET users/fred/pets/sparky - returns details on freds pet sparky
这样做的好处在于您可以添加代码来授权每个请求,例如,您可能有两个用户,fred和jack。 两个用户都会通过身份验证,但你只应该允许fred请求他的资源和插口来请求他的。 你只需要在你的API中添加授权检查,例如从URI获取用户名,获取经过验证的用户的用户名,检查它们是否相同。 如果不返回类似http 403的内容,如果它们相同,则允许请求。
我想如果你还不清楚,你需要阅读REST的细节。 到目前为止,关于这个主题的最好的书是这一个RESTful Web服务。 它涵盖了来自第一原则的REST。 它在设计资源,以及如何管理用户和多个客户端方面也有非常好的一面。
我不确定要理解这个问题,因为在这种情况下多租户似乎有点矫枉过正。 不过,我可以尝试回答第二个问题。
REST是一种“基于资源”的体系结构,您必须认识到/pets
和/pets/?tenant=1
不会引用相同的资源:
/pets
是指当前用户的宠物, /pets/?tenant=1
是指Bob的宠物。 虽然这两种解决方案都没有错,但通常情况下最好是获得第二种解决方案 URI的确被设计为共享,并且你有更多的理由来分享“Bob的宠物”(即使它需要认证和授权来表示),而抽象的“我的宠物”对每个用户都不相同。
请参阅资源ID是否应存在于网址中? 进行类似的讨论...
链接地址: http://www.djcxy.com/p/21971.html上一篇: What is the correct way to authorize and structure a RESTful backend