Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
RESTAPI与多租户数据库(由客户端分隔)_Rest_Asp.net Web Api - Fatal编程技术网

RESTAPI与多租户数据库(由客户端分隔)

RESTAPI与多租户数据库(由客户端分隔),rest,asp.net-web-api,Rest,Asp.net Web Api,我有一个具有复合密钥的多租户数据库 clientId - docId 路由如下所示 /api/controller/clientId/docId 对于身份验证,我使用“全局”用户名,例如电子邮件+密码,通过https发送到每个请求的http头中。用户名显式映射到客户端,并且在后端可用 如何正确使用rest并获得最佳安全性 按照上面的方式进行路由,只需根据用户名验证clientId是否与路由中的相同 或 按如下所示更改路由,并在保存记录之前从数据库获取clientId /api/control

我有一个具有复合密钥的多租户数据库

clientId - docId
路由如下所示

/api/controller/clientId/docId
对于身份验证,我使用“全局”用户名,例如电子邮件+密码,通过https发送到每个请求的http头中。用户名显式映射到客户端,并且在后端可用

如何正确使用rest并获得最佳安全性

  • 按照上面的方式进行路由,只需根据用户名验证clientId是否与路由中的相同
  • 按如下所示更改路由,并在保存记录之前从数据库获取clientId

    /api/controller/docId

  • 这可能是一个显而易见的问题,但我担心潜在的安全问题。或者,选择较短的路线是一件很容易的事


    谢谢

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

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

    如果您查看其他多租户环境(例如销售人员)的工作方式,您会发现他们必须通过安全机制推断客户机,或者幸运地拥有每个对象/资源的唯一id

    我见过的一种方法是将客户机标识符(通常是某种代理键,避免暴露其他用户的db id!)放在URL的根目录下,例如/api/{clientId}/controller/docId。在多租户环境中,根据定义,每个资源可能都是该客户机独有的

    这种方法有时给出的一个原因是,每个客户有一个唯一的url有助于缓存/api/{clientId}/controller/docId或/api/controller/{clientId}/docId

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

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


    更进一步。。。考虑一个两步认证机制,其中令牌被发出(正确的用户名和密码)与客户端ID实际上在令牌中作为索赔。这样,使用令牌的后续请求意味着您不需要为每个请求回调数据库来验证和检索信息。看看OAuth承载令牌(请确保对其进行签名)或其他一些方法

    Mark的方法是完全有效的,但是,我碰巧使用了
    /tenant/docid
    ,因为每个租户都有一个不同的数据库。如果URI中没有包含租户,那么决定连接到哪个数据库并查找文档将是一件非常痛苦的事情。

    我也有类似的情况。您是否考虑将租户ID存储为用户声明(或类似于访问令牌/凭据)?我认为将租户作为URI的一部分是理想的,但应用到现有软件时需要做更多的工作。@bjornhol如果URL中不包含租户ID,则会使本地缓存变得困难,因为我使用整数而不是guid作为标识符,因此租户之间可能存在冲突。@Darreller传递租户ID(guid)时,您认为如何在http头中构建连接字符串和承载令牌(授予类型“密码”)以验证用户以访问控制器?我需要你的建议。谢谢。@IshworKhanal您可以这样做,但请记住,如果希望HTTP缓存工作,您需要引用vary头中的头。@Darreller感谢您的回复,我正在使用WebApi 2 OData v3表示层和EF Codefirst数据库层来构建水平缩放多租户SAAS(分片基础数据库,即每个租户的数据库)。我决定构建以api为中心的saas,因为我不需要每次登录会话时都存储任何用户凭据,但他们需要使用他们所属的租户令牌和自己的承载令牌进行授权才能访问服务。在构建atm体系结构时,这有意义吗?请给出进一步建议。谢谢。