当用户存储在外部身份提供程序服务中时与用户的关系

时间:2016-04-28 02:39:30

标签: azure oauth oauth-2.0 asp.net-web-api2 asp.net-identity

我正在尝试为其创建API和网站客户端。最近我已经阅读了很多关于OAuth2作为安全机制的公司以及提供身份验证作为服务的公司,例如auth0.com甚至Azure活动目录,我可以看到使用它们的优势

因为我以前总是让用户在同一个数据库中,并且以一对多的形式与Users表有关系,如下面的

public class User
    {
        public string subjectId { get; set; }

        public virtual List<Invoice> Invoices { get; set; }
        /*
        More properties in here
        */
    }

public class Invoice
    {
        public int InvoiceId { get; set; }
        public string PaymentNumber { get; set; }
        public DateTime Date { get; set; }
        public double Amount { get; set; }
        public string Description { get; set; }

        public virtual User User { get; set; }
    }

我的问题是。

如果用户存储在Auth0.com等外部身份验证服务中,

  • Invoice类如何处理与用户的关系?
  • 是否只是在Invoice表中添加一个新的属性subjectId,这将获取身份验证服务分配的任何id的值?

在后一种情况下,类Invoice会不会像下面那样?

public class Invoice
        {
            public int InvoiceId { get; set; }
            public string PaymentNumber { get; set; }
            public DateTime Date { get; set; }
            public double Amount { get; set; }
            public string Description { get; set; }

            public string SubjectId{get;set;}
        }

此外,如果用户存储在其他地方,您如何进行查询,

Select * from Users u inner join Invoices i where Users.Name='John Doe' and i.Date>Somedate.

2 个答案:

答案 0 :(得分:4)

我们的网站也有类似的设置。我们对用户数据库使用Passport,而我们的网站根本没有用户表。这使得生活比在Passport和我们的网站之间拥有大量重复数据简单得多。我将使用我们的代码作为你正在做的事情的一个例子,并希望它是有道理的。

我们的网站有一个看起来像这样的许可证对象(Java不是C#,但它们是相似的):

public class License {
  public String companyName;
  public List<User> users;
}

许可证表格如下(裁剪):

CREATE TABLE licenses (
  id           UUID         NOT NULL,
  company_name VARCHAR(255) NOT NULL,
  PRIMARY KEY (id)
);

许可证通过这样的连接表识别与之关联的用户(Passport使用UUIDs使用户ID再次使生活变得简单):

CREATE TABLE users_licenses (
  users_id    UUID NOT NULL,
  licenses_id UUID NOT NULL,
  PRIMARY KEY (users_id, licenses_id),
  CONSTRAINT users_licenses_fk_1 FOREIGN KEY (licenses_id) REFERENCES licenses (id)
);

然后我们可以选择任何一个方向。如果我们知道用户ID,我们可以要求他们所有的许可证:

select * from licenses where users_id = ?

或者,如果我们知道许可证ID,我们可以要求所有有权访问许可证的用户:

select * from users_licenses where licenses_id = ?

一旦我们有一个或多个用户ID,我们就可以调用Passport /api/user端点或/api/user/search端点来检索一个或多个用户对象。我们实际上正在使用Passport Java客户端(https://github.com/inversoft/passport-java-client)来为我们调用API,然后返回List<User>。这是从上面存储在License类中的内容。该代码如下所示:

License license = licenseMapper.retrieveById(licenseId);
List<UUID> userIds = licenseMapper.retrieveUserIdsFor(licenseId);
ClientResponse<SearchResponse, Errors> clientResponse = passportClient.searchUsers(userIds);
license.users = clientResponse.successResponse.users;

LicenseMapper是一个MyBatis接口,它执行SQL并返回许可证对象。 C#ORM使用LINQ,但它会类似。

这个设置的好处是我们的网站数据库中没有user数据库表,我们必须保持同步。一切都是通过API从Passport加载的。我们也不关心性能。 Passport是内部部署,每秒可以进行数千次用户查找,因此我们总是加载数据而不是缓存数据。

您需要额外代码的唯一问题是在搜索name='John Doe'等任意用户时处理联接。处理此问题的唯一方法是首先查询用户数据库,检索所有ID,然后加载其发票。如果你有一个庞大的用户数据库,但这仍然可行,这似乎很危险。

在我们的情况下,这可能会是这样的:

UserSearchCriteria criteria = new UserSearchCriteria().withName("John Doe");
ClientResponse<SearchResponse, Errors> clientResponse = passportClient.searchUsersByQueryString(criteria);
List<User> users = clientResponse.successResponse.users;
Set<License> licenses = new HashSet<>();
for (User user : users) {
  licenses.addAll(licenseMapper.retrieveByUserId(user.id));
}

答案 1 :(得分:3)

由于您已将Auth0称为身份提供者,因此有多种方法可以在数据库中实现用户表。 1.使用Auth0验证/注册用户将使用配置文件对象发送响应,该响应将包含您需要的所有基本配置文件信息。将此配置文件对象发布回您自己的API以将其保存到数据库。应使用您收到的访问令牌以及Auth0中的配置文件对象来保护此API端点。 2.您可以在Auth0中创建一个自定义规则,将用户信息发布回您的API。此规则在Auth0服务器上执行,因此这是一个安全的调用。 3.身份提供者(在我们的例子中为Auth0)需要公开API端点,该端点为我们提供用户配置文件数据(例如:https://yourdoamin.auth0.com/userinfo)。您可以从API调用此端点以接收用户信息。

当用户注册到您的应用程序时,请使用这些技术之一在数据库中建立用户配置文件信息表。将身份提供程序视为负责验证资源所有者(应用程序的用户)并提供访问令牌以安全访问API /应用程序的服务始终是一个好主意。如果您拥有数据库中用户的配置文件,则在用户通过身份验证后,您不必依赖身份提供程序。

如果您有任何其他问题,请与我们联系。

谢谢你, 索马。