首页 > 解决方案 > 具有自己身份表的多个数据库应与单个 Web api 连接并验证 jwt 令牌

问题描述

我正在为几家公司开发一个相同的项目,因此我们为具有相同数据库结构的不同公司创建了不同的数据库,每个数据库都有自己的身份表、基于角色的菜单、基于角色的访问权限。

我已经编写了一个 api 来根据提供的用户名连接不同的数据库。因为所有公司都使用相同的登录屏幕登录。

我们决定通过登录屏幕上传递的用户名连接哪个数据库。

示例: 3 家公司 - abc.com,pqr.com,xyz.com 单一登录屏幕 - 登录屏幕上的 www.example.com/login 用户将使用其公司电子邮件 user@abc.com,user@pqr.com,user 登录@xyz.com

登录后一切正常

问题是: jwt 令牌路径总是连接到 abc.com 数据库,尽管这些记录在它们的数据库中,但它总是显示 user@pqr.com 和 user@xyz.com 的错误消息。

1) 未来公司将增加,因为这些是我们门户网站的客户,未来的数据库将是 - abc.com、bcd.com、def.com.......等。

2)公司所有者可能有多个公司也有不同的数据库,所以他们需要查看两个数据库的报告。就像 X 先生拥有 2 家公司(abc.com 和 pqr.com)一样,尽管公司所有者在不同的 db 中有不同的帐户,但他可能需要查看需要两个 db 数据的少量报告。

执行此操作后,除以下问题外,所有问题均已解决: 我已替换 //var userManager =context.OwinContext.GetUserManager();

var appDbContext = new ApplicationDbContext(context.UserName); HttpContext.Current.GetOwinContext().Set(appDbContext); HttpContext.Current.GetOwinContext().Set(new ApplicationUserManager(new Microsoft.AspNet.Identity.EntityFramework.UserStore(appDbContext))); var userManager= HttpContext.Current.GetOwinContext().GetUserManager();

在课堂上 - ApplicationOAuthProvider

注意没有 2 没有完成。## - 任何帮助表示赞赏

我正在寻找永久的解决方案,我很困惑。非常感谢任何帮助。

标签: asp.net-web-api2asp.net-identityjwtmulti-tenantasp.net-authorization

解决方案


是的你可以

1) 您应该准备好跨多个虚拟/物理服务器配置信任。这是 JWT 的主要优势,它可以被联合起来。这与 Web 应用程序之外的数据库无关。如果您要为此应用程序拥有多个 Web 服务器,则它们需要相互信任。

我相信您可以尝试以下方法之一:

i) 将您的身份验证服务器编码/配置为受解决方案中的域/机器信任

https://blogs.msdn.microsoft.com/webdev/2017/04/06/jwt-validation-and-authorization-in-asp-net-core/

特别注意受众和权限字符串,并围绕这些概念进行研究。

ii) 将外部 JWT 视为适当的“外部”凭证(如 Google OAuth),然后在引用外部令牌后初始化本地 JWT 或其他安全机制。我将不得不为此找到参考。

2)您应该为每个客户有一个单独的子域(在水平规则之后进一步参见下文)

3)您必须修复初始化数据库上下文的策略。GetOwinContext 方法是 IoC 模式的糟糕实现。默认的 JWT UserManager 代码期望从 OwinContext 单例引用派生 db 上下文。如果您要访问多个数据库,这是一个问题。一种方法是现在简单地按需构建上下文,然后想办法优化重用和性能。这可能很重要,因为您需要确保它为任何给定查询检查正确的数据库。

这是一个解决方案链接:如何在运行时更改 dbcontext 连接字符串中的数据库名称

4) 您的客户需要访问多个数据库。有几种方法可以做到这一点。理想情况下,您应该尽可能地维护联合模式。但是您可能还需要/需要服务器端编排:CRUD 之外的特殊 API,专门用于多数据库任务。每个固定报告都有一个服务器端操作。这样的服务器端操作将查看要查询的数据库的请求(根据 CustomerID),它将通过自定义 JWT 声明(一组 CustomerID)验证访问,如果有任何指定的 customerid,它将引发异常不允许。然后,该函数将根据需要执行这些经过验证的客户 ID 作为参考。有关它如何运行的信息,请参见 [5]。

以下是一些用于创建自定义 JWT 声明的链接(它们存储在 JWT 中,通过 Bearer 标头 [通常] 与客户端传输):

以下是获取自定义 JWT 声明的一些链接:

5) 对联合数据集进行排序是很常见的。这可能是你的情况。如果数据库在同一个 RDBMS 实例上,通常可以在一个 SQL 语句中运行多数据库查询(对于 SQL Server)。(但是,如果您使用的是 Azure 数据库池,它们通常会在不同的实例上运行(透明地)。我相信最近有一个更改允许您指定它们在同一个实例上,或者它们现在允许多数据库查询)。否则,服务器端编排意味着您将分别从每个数据库中获得前 10 个,然后执行最终排序并将前 10 个发送回客户端。最坏的情况是,您需要客户端多次查询,每个客户 ID/数据库一次,然后在客户端聚合数据。

(我已经介绍了很多点,请让我知道您想了解更多详细信息)


我喜欢每个客户的数据库

您似乎在描述一个系统,其中每个客户都有一个单独的数据库。当您将与不需要在应用程序内共享数据的客户打交道时:这是我非常提倡的设计。它隔离数据访问(安全/隐私),减少表锁定争用(性能),并使您能够将数据库移动到不同的服务器以实现邻近性和负载平衡(性能)。

all company logins with same login screen.

这个要求是你最大的障碍。如果您曾经使用过 Slack,您会注意到他们为每个团队设置了一个新的子域。每个团队无需共享凭据。

这种具有单独子域的设计意味着:

  • Web 服务器也是一个可移植的组件;除了数据库。
  • 客户可以将自己的 DNS 记录设置为虚 URL(即 yourapp.acmeco.com);以及您自己的默认子域(即 acmeco.yourapp.com)

无论您的具体问题的答案如何,我强烈建议您与项目的利益相关者交谈,看看是否可以实现多子域设计。

为了便于配置(遵从 Web 应用程序),我强烈建议:

  • 设置通配符 DNS 记录(我知道至少 CloudFlare 支持)
  • 您应该获得通配符 SSL 证书,以便轻松加密每个子域。这应该花费你大约 100 美元,为期 1-2 年。不要为更多功能付费,IMO 是浪费钱。
  • 在没有特定主机的情况下配置您的网络服务器。(如果您将其他 Web 应用程序与相同的 IP 一起配置,它们仍然可以有一个主机名并共享端口 80/443)。对于 IIS,这仅仅意味着将主机 URL 区域留空。
  • 您需要您的应用程序处理 JWT/Session 以检查要连接的数据库。登录时,您需要检查 Host 标头以确定要连接到哪个数据库。

推荐阅读