具有客户端分隔的多租户数据库的Rest API

时间:2012-12-07 10:33:47

标签: rest asp.net-web-api

我有一个带有复合键的多租户数据库

clientId - docId

路由看起来像这样

/api/controller/clientId/docId

对于身份验证,我使用" global"通过https在每个请求的http-header中发送的用户名,例如电子邮件+密码。用户名明确映射到客户端,并在后端提供。

如何正确地进行休息并获得最佳安全性?

  1. 如上所述路由,只需验证根据用户名的clientId与路由
  2. 中的相同

    1. 如下所示更改路由并在保存记录之前从数据库获取clientId?

      /api/controller/docId

    2. 这可能是一个显而易见的问题,但我担心潜在的安全问题。或者使用较短的路由只是一个明智的选择?

      谢谢!

2 个答案:

答案 0 :(得分:8)

我认为/api/controller/docId可能是最好的主意,或者使用单个代理键来表示ClientId和docId(我的偏好)。

除非您需要允许客户端查看其他客户端资源,否则我会将其隐藏在URI方案中,最坏的情况是,最好将信息泄漏视为冗余,因为您已经对客户端进行了身份验证并知道他们是谁。这也是一个开销,即您仍然必须检查URL中的客户端ID是否映射到请求的用户名和密码,因此您需要在每个请求上检索客户端ID。

如果你看看其他多租户环境如何运作,例如销售人员可以看到他们必须通过安全机制推断客户端,或者幸运的是,每个对象/资源都有唯一的ID。

我看到的一种方法是在URL的根目录下放置客户端标识符(通常是somekind的代理键,避免暴露其他用户db id!)。 / API / {的clientId} /控制器/的docId。在多租户环境中,每个资源可能/根据定义对该客户端是唯一的。

有时为此方法提供的一个原因是,每个客户都有一个唯一的URL可以帮助缓存... / api / {clientId} / controller / docId或/ api / controller / {clientId} / docId

有关基本身份验证的简要说明

您的方法没有错,但考虑......您可以在验证密码和用户名的同时检索客户端ID,并将其作为IPrinciple上的声明添加。然后至少可以在代码中找到它,而不需要任何进一步的数据库查找(在该请求的生命周期内)。

更进一步......考虑一种两步认证机制,其中发布令牌(遵循正确的用户名和密码),其中客户端Id实际上在令牌中作为声明。这样,使用令牌的后续请求意味着您不需要为每个验证和检索信息的请求回调数据库。看看OAuth持票人代币http://self-issued.info/docs/draft-ietf-oauth-v2-bearer.html(一定要签名)或其他一些方法......

答案 1 :(得分:6)

Mark的方法完全有效,但是,我碰巧使用/tenant/docid,因为每个租户都有不同的数据库。如果您没有在URI中包含租户,那么尝试确定要连接到哪个数据库并搜索文档将是一个真正的痛苦。