【问题标题】:Validate date from other bounded context从其他有界上下文验证日期
【发布时间】:2018-09-14 21:37:49
【问题描述】:

我有两个限界上下文(学生注册、课程)。 Studentenrollment 包含所有学生的课程 ID 和作业。 课程的管理部分包含与课程相关的所有信息。 当学生想要获取课程信息时,它会点击发送 jwt 令牌的端点 (/courses/ID)。在课程上下文中,我获取学生 ID、课程 ID 并创建它在公共汽车中调度的查询。在从课程 ID 获取课程信息之前的查询处理程序中,我想验证学生 ID 是否存在并且该学生是否拥有该课程。为此,我必须调用另一个上下文有界的学生注册。所以,我一直在寻找如何在互联网上处理它,我发现了这个: https://medium.com/@martinezdelariva/authentication-and-authorization-in-ddd-671f7a5596ac

class findByCourseIdAndStudentIdQueryHandler()
    {
        public function handle($findByCourseIdAndStudentIdQuery)
        {
            $courseId = $findByCourseIdAndStudentIdQuery->courseId();
            $studentId = $findByCourseIdAndStudentIdQuery->studentId();

            $student = $this->collaboratorService->studentFrom(
                $courseId,
                $studentId
            );


            $this->courseRepository->findByCourseId($courseId);
        }
    }

    class collaboratorService()
    {
        public function studentFrom($courseId, $studentId)
        {
            $student = $this->studentEnrollmentClient->getStudentFrom($courseId, $studentId);

            if (!$student) {
                throw new InvalidStudentException();
            }

            return $student;
        }
    }

你怎么看?

更新

namespace App\Context\Course\Module\Course\UI\Controller;

class GetCourseController extends Controller
{
    public function getAction($request) {
        $this->ask(new FindByCourseIdQueryHandler($request->get('course_id'));
    }
}

namespace App\Context\Course\Module\Course\Infrastracture\Query;

class AuthorizedQueryDispatcher extends QueryDispatcher
{
    //In this case $query would be FindByCourseIdQueryHandler
    public function handle($query)
    {
        $authUser = $this->oauthService->getAuthUser();

        //it can be student or teacher
        $role = $authUser->getRole();
        $userId = $authUser->getUserId();

        //it will return FindByCourseIdAndStudentIdAuthorizedQueryHandler
        $authorizedQuery = $this->inflector->getAuthorizedQueryName->from($userId, $role, $query);

        $this->dispatch($authorizedQuery);

        $this->queryDispatch->dispatch($query);
    }
}

namespace App\Context\Course\Module\Course\Application\Query;

class FindByCourseIdAndStudentIdAuthorizedQueryHandler
{
    public function handle($findByCourseIdAndStudentIdQuery)
    {
        $student = $this->studentEnrollmentClient->getStudentFrom($findByCourseIdAndStudentIdQuery->courseId, $findByCourseIdAndStudentIdQuery->studentId);

        if (!$student) {
            throw new InvalidStudentException();
        }
    }
}

namespace App\Context\Course\Module\Course\Application\Query;

class findByCourseIdAndStudentIdQueryHandler()
{
    public function handle($findByCourseIdQueryHandler)
    {
        $courseId = $findByCourseIdQueryHandler->courseId();

        $this->courseRepository->findByCourseId($courseId);
    }
}

【问题讨论】:

  • 那么,您有一个授权建模问题,对吗?
  • 不是,我正在使用 LexikJWTAuthenticationBundle 处理授权。在执行控制器之前,它有一些侦听器从标头中恢复令牌并从令牌创建 userAuth。然后在控制器中,我从 userAuth 获取学生 ID 并将其设置在查询中。我的问题是:如果使用 collaboratorService 来检索属于另一个有界上下文的学生是否很好。因为我理解的是 collaboratorService 是为了授权。但就我而言,我用它来检索学生。
  • 授权不是认证,它们不一样。
  • 我想看看你有什么样的问题,所以我可以给你一个正确的答案
  • 我的问题是我需要知道那个学生是否有课程才能让他获得课程的信息。但是学生和课程之间的关系是在另一个有限的上下文中(学生注册)。所以我把逻辑放在 collaboratorService 里面。

标签: domain-driven-design cqrs


【解决方案1】:

TLDR;授权应该与域层明确分开,例如在不同的包/命名空间/模块中。此外,从域到授权的依赖关系应该倒置,域不应该依赖/知道授权/

实现它的一种方法是创建一个授权服务,例如FindByCourseIdAndStudentIdQueryAuthorizer(我们将其命名为授权者)。该服务可能跨越有界上下文 (BC) 边界,即它可能依赖于来自远程 BC 的远程域服务。理想情况下,当授权方进行检查时,远程数据应该已经可用。通过这种方式,系统在远程限界上下文服务不可用的情况下更具弹性。您可以通过监听远程事件或后台任务来做到这一点。

理想情况下,域层(来自任何 BC)不应该知道授权者。

执行此操作的一种方法是使用 AuthorizedQueryDispatcher 装饰应用程序的组合根中的 QueryDispatcher(或您拥有的)。这个 AuthorizedQueryDispatcher,当它接收到一个查询时,它首先搜索一个 Authorizer,然后调用它。如果授权失败,则拒绝查询。如果授权成功或没有授权者,则将查询发送到真实/装饰的 QueryDispatcher。

如果不能这样做(即您没有 QueryDispatcher),那么您可以尝试装饰每个查询处理程序(手动?)。例如,您可以拥有一个与FindByCourseIdAndStudentIdQueryHandler 具有相同接口的FindByCourseIdAndStudentIdAuthorizedQueryHandler。您可以在应用程序 (DIC) 的组合根目录中替换它们。

【讨论】:

  • 我按照你说的更新了我的问题,可以吗?看看命名空间
  • @AgustinCastro 是的,但我会以某种方式使用更多抽象,比如装饰器模式
  • 应该在哪一部分使用更多抽象?
  • @AgustinCastro 例如我会装饰 QueueHandler
猜你喜欢
  • 2021-11-07
  • 1970-01-01
  • 2016-11-09
  • 1970-01-01
  • 1970-01-01
  • 2012-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多