我应该将使用 DDD 和 CQRS 方式刷新访问令牌的代码放在哪里?

Posted

技术标签:

【中文标题】我应该将使用 DDD 和 CQRS 方式刷新访问令牌的代码放在哪里?【英文标题】:Where should I put the code for refreshing access token with a DDD & CQRS manner? 【发布时间】:2020-01-25 01:55:59 【问题描述】:

我正在使用 ASP.NET Core 并学习 DDD 和 CQRS(包括 MediatR)。我已阅读 eshopcontainers 文件。在我的应用程序中,我们需要将每个用户的访问令牌和谷歌刷新令牌存储在我们的 SQL 数据库中,因为我们必须定期检查 gmail 中的某些状态。 当我们实现这个功能时,或多或少我们想编写以下逻辑。

1. Get the access token and refresh token from our DB
2. If the access token is expired, we get the valid access token with refresh token
3. If the access token is updated in step 2, we save the new access token to DB
4. With the valid access token, we fetch information from gmail

此过程将用于 CQRS 模式中的几个命令处理程序。

我的问题是,

我应该把DDD,CQRS方式的逻辑放在哪里? 它应该放在存储库、应用程序服务还是域服务中...?

我们可以从查询处理程序中调用方法吗? 我想知道这是因为该逻辑偶尔会更新 DB 中的数据,所以我认为我们不应该从 Query Handler 调用此过程

我目前的想法是创建一个包含上述过程的UserService。我的解决方案结构的具体示例如下。 UserService 将在几个命令处理程序中使用,并且不会在 QueryHandler 中使用,因为它偶尔会更新数据库。但是,如果有更好的基于 DDD 方式的想法,我想知道它。

解决方案结构

Application layer (depends on Domain and Infrastructure)
 - UserController.cs
 - CommandHandlers folder (several command handlers use UserService)
 - QueryHandlers folder 

Domain Layer (No dependency)
  - UserAggregate folder
    - User.cs (Model for user)
  - IRepository.cs (Interface)

Infrastructure Layer (depends on Domain)
  - EF Core related folder
  - Repository.cs (Implemented IRepository.cs)
  - UserService.cs (has the token update process)

User.cs

public class User 
   
    public string AccessToken  get; set; 
    public string RefreshToken  get; set; 
    public long Id get; set;

UserService.cs(只是一个想法)

public class UserService 

    ....

    GetValidAccessToken(long userId) 
    
        var user = repository.Find(userId);
        if (user.AccessToken is expired) 
        
            var newAccessToken = GetNewAccesstokenWithRefreshToken(user.RefreshToken);
            user.AccessToken = newAccessToken;
            repository.Save(user);
        
        return user.AccessToken;
    

【问题讨论】:

这是横切关注点 - 尽量不要将它与域逻辑耦合。 ASP NET 中间件是管理它的好地方。此外,您的应用程序非常小,无法利用 DDD,通常具有小域的应用程序在执行 DDD 时由于分离而很难处理。 DDD 更适合复杂的领域。 【参考方案1】:

我同意@Ankit Vijay。请务必接受他的正确答案,因为我只会对此进行扩展。

您通常在需要授权访问的集成层中使用访问令牌。例如,Web API 和其他视图控制器。使用消息队列时,消息处理程序不应公开,因此这些通常不需要授权。

据我所知,您需要使用访问令牌访问外部存储以获取特定于用户的数据。这意味着访问令牌可能会在尝试该操作之前过期。

在我看来,您有 3 个选项:

1) 您在初始集成点(例如 Web api 控制器)获取相关信息,然后传递该数据。

2) 您传递用户名并使用各种服务帐户为用户获取访问令牌,其中服务帐户有权代表用户这样做,然后使用访问令牌以获取相关数据。

3) 服务帐户可能有能力为用户收集这些额外信息,在这种情况下,服务帐户将进行身份验证以获取令牌,然后为相关用户请求数据。

在我之前参与的一个项目中,我们不得不使用 webMethods 集成服务器,后端团队使用 ADFS 令牌。令牌的有效期为 8 小时,由于各种原因,一些操作仅在此时间之后才执行。由于服务帐户在 ADFS 上具有某种形式的委派权限,因此将为用户刷新过期的令牌。我没有参与该实施,但从广义上讲,这是规避问题的想法。

如果您无法让服务帐户刷新令牌或直接获取所需数据,我猜选项 (1) 将是您的最佳选择。

【讨论】:

【参考方案2】:

存储用户访问令牌和刷新令牌似乎不是业务/域问题。我认为你不应该试图通过 DDD 来处理它。如果您需要访问CommandHandlers 中的令牌,我会将与访问令牌有关的逻辑放在域之外的某种中间件中。

【讨论】:

以上是关于我应该将使用 DDD 和 CQRS 方式刷新访问令牌的代码放在哪里?的主要内容,如果未能解决你的问题,请参考以下文章

域驱动设计中的访问控制

DDD CQRS架构和传统架构的优缺点比较

CQRS框架(nodejs的DDD开发落地框架)初识感想

与 DDD + CQRS + ES 的并发

DDD CQRS和Event Sourcing的案例:足球比赛

DDD CQRS架构和传统架构的优缺点比较