【问题标题】:How to decouple user Identity from the application data如何将用户身份与应用程序数据分离
【发布时间】:2017-06-30 13:47:04
【问题描述】:

我和一些学校的朋友加入了一家新创业公司,我正在开发一个 REST API 作为 Web 应用程序/网站的后端。我最近刚毕业,对大型项目没有太多经验。

如果不详细介绍具体的商业理念,它将是一种“共享经济”服务,例如 uber 或 airbnb,用户注册为特定服务的客户或提供商。因此,用户需要注册一个帐户并拥有与该帐户相关的数据。

API 是使用 ASP.NET Web API 开发的。对于身份验证/授权,我使用 ASP.NET 身份和 JWT 作为带有 OWIN OAuth 中间件的 Oauth 不记名令牌。

我在部分设置中使用了指南,并进行了一些更改以适应我们的 项目。 (感兴趣的可以搜索“b​​itoftech Implement OAuth JSON Web Tokens Authentication in ASP.NET Web API and Identity 2.1”找到)。

对于那些不知道的人,ASP.NET 身份数据库如下所示: ASP.NET Identity database diagram.

所以我们有一个代表用户的 AppUser 表,在 Identity 数据库的不同表中附加了角色、声明和登录信息。

现在,用户在我们的应用程序中拥有许多与他的帐户相关的其他数据,例如消息(用户可以相互发送消息)、事件(如果这是 uber 的话,就像乘车)、类别、评论、文件和其他数据。全部在单独的表格中。

因此,由于所有这些其他表都与用户身份相关,我所做的是将所有这些其他表放在同一个数据库中,并使用 AppUser 表中的 Id 的外键。

每个用户在 IdentityRole 表中都有一个客户或提供商角色(如 Uber 示例中的客户或司机)。 这样我可以根据角色授权用户,也可以根据角色查询数据。

现在要注意了:意外的需求变化。该公司决定他们(我们)想要创建一个类似的服务(与客户和提供商),但在不同的业务领域,并具有相同的用户身份。因此,不应要求已经在一个站点注册的用户再次使用另一个站点的新帐户注册,而只需使用他们现有的帐户(并且可以通过单击其个人资料中的按钮或其他内容来注册新站点) .

所以如果第一个网站是 uber,现在我们要创建 airbnb(不是真的,但作为示例)。

新站点中的数据将与第一个站点非常相似。用户将拥有消息、事件、类别、文件等。但事件表可能会有所不同,并且可能会为新站点提供一些新的或不同的表。一开始我们会尽量保持数据非常相似,这样我们就可以使用大部分现有代码,但我们预计——如果网站变得流行——它们会在时间。

所以首先我想:“我怎样才能更改现有的数据库架构,以使其适合两种服务?”。但当我仔细考虑时,我认为这可能只会在未来产生问题。

Oauth flow diagram 中,你有一个单独的资源服务器和授权服务器。尽管我现在使用 Oauth,但我猜我的 API 既是资源服务器又是授权服务器,如果它们没有按照我描述的方式耦合,那可能没问题?

所以我的问题是:

1: 我是否应该为用户身份 (IdentityDbContext) 使用一个(单独的)数据库, 以及所有其他数据(事件、消息等)的另一个数据库?

如果需要,Identity 可以在完全不同的服务器上运行,并且不会与任何特定的域/站点/服务耦合。这是个好主意吗?

2: 如果是这样,我将如何在数据库之间建立关系?

我唯一能想到的就是在“Uber”数据库中创建一个只有 UserId(来自 Identity 数据库)的单独用户表,这将在用户第一次注册站点时创建,并且所有其他数据都与此键相关。然后我需要从两个数据库中查询数据并将它们放在一起进行一些操作,例如,当用户查询他的传入消息时,消息本身将在一个数据库中,而发件人的姓名在另一个数据库中。有没有更好的办法?

3: 我是否应该为第一个和第二个网站/服务使用单独的数据库(一个用于 Uber,一个用于 Airbnb,如示例所示)?还是有更好的办法?

4: 有没有我没想到的更好的解决方案?

很多人可能以前都遇到过这些问题,所以如果有经验丰富的开发人员能告诉我什么是最佳做法,我将不胜感激。

最后,如果我们当前的努力成功,未来更多的服务将“附加”到用户身份上并非不可能,所以我真的需要一个面向未来的解决方案来解决这个问题。

感谢您的任何回复。

【问题讨论】:

    标签: asp.net database-design architecture oauth-2.0 authorization


    【解决方案1】:

    这种方法似乎有些普遍:

    1. 维护一个完全独立的身份数据库。应该与任何业务线 (LOB) 数据库完全没有连接。

    2. 每个 LOB 数据库都应该有自己的用户表,并具有与其他 LOB 表的适当引用完整性约束,例如您的案例中的事件或消息。

    3. 当用户第一次访问您的 LOB 网站时,他应该在 LOB 数据库中“注册”。插入 LOB 用户记录。使用访问令牌调用身份服务器以获取您的 LOB 站点需要的任何人口统计信息。

    4. 当用户第 N 次访问您的 LOB 网站之一时,您可以使用访问令牌调用身份服务器并获取最新的人口统计信息,以防万一自从他上次访问以来,情况发生了变化。然后,您可以将此信息存储在 LOB 用户表中,以便您可以离线使用,例如如果您需要推送营销电子邮件,您将拥有电子邮件地址的副本。

    这种方法的优点是关注点分离以及支持多个身份验证提供程序的能力(例如,将来您也可以支持 Facebook 或 Google+ 登录)。

    您还避免了身份服务器和 LOB 服务器之间的任何依赖关系,因此您可以根据需要添加或删除业务线,并让身份服务器保持良好和轻量级。

    【讨论】:

    • 感谢您的回复。只是几个问题:API(LOB 服务器)是完全无状态的,那么服务器如何知道用户是否第 N 次点击它?每次更改用户记录时让身份服务器通知 LOB 服务器不是更容易吗?也许某种观察者模式?还是会打破关注点的分离?我是否应该为每个业务线使用完全独立的数据库(如我的第三个问题)?
    • 由于 LOB 用户表中缺少任何记录,LOB 应用程序会知道用户是新用户。如果您单独销售这些解决方案,您将希望避免它们之间的任何依赖关系(除了对登录协议的依赖,这是不可避免的)。
    • 我的问题是指用户第N次访问服务器,而不是第一次(你说我可以定期调用身份服务器-即第N次-检查用户信息是否已经更新)。那么我将如何实现呢?谢谢。
    • 使用逆逻辑。如果用户表中已存在记录,请执行更新。基本上,if not exists then insert else update.
    猜你喜欢
    • 2016-11-10
    • 1970-01-01
    • 2011-12-14
    • 1970-01-01
    • 2011-06-30
    • 2021-03-06
    • 1970-01-01
    • 1970-01-01
    • 2014-06-16
    相关资源
    最近更新 更多