我有两个有界上下文(studentenrollment,courses)。 Studentenrollment让所有学生都有他的课程ID和他的家庭作业。课程的管理部分包含与课程相关的所有信息。当学生想要获得课程的信息时,它会命中发送jwt令牌的端点(/ courses / ID)。在课程上下文中,我获得了学生ID,课程ID以及创建在公交车上发送的查询。在从课程ID获取课程信息之前的查询处理程序中,我想验证学生ID是否存在且该学生是否具有此课程。为此我必须调用另一个上下文有限的studentenrollment。所以,我一直在寻找如何在互联网上处理,我发现: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);
}
}
TLDR;授权应与Domain层明确分开,例如在不同的包/命名空间/模块中。此外,应该反转从域到授权的依赖关系,域不应该依赖/了解授权/
实现它的一种方法是创建一个授权服务,例如FindByCourseIdAndStudentIdQueryAuthorizer
(让我们将它命名为Authorizer)。该服务可以跨越有界上下文(BC)边界,即它可以依赖于来自远程BC的远程域服务。理想情况下,当授权人进行检查时,远程数据应该已经可用。通过这种方式,系统在远程有界上下文服务不可用的情况下更具弹性。您可以通过侦听远程事件或后台任务来完成此操作。
理想情况下,域层(来自任何BC)不应该知道授权者。
一种方法是使用AuthorizedQueryDispatcher装饰应用程序的Composition根中的QueryDispatcher(或您拥有的)。这个AuthorizedQueryDispatcher,当它收到一个查询时,它首先搜索一个Authorizer,然后调用它。如果授权失败,则拒绝查询。如果授权成功或没有授权者,则查询将被发送到真实/装饰的QueryDispatcher。
如果不能这样做(即你没有QueryDispatcher)那么你可以尝试装饰每个查询处理程序(手工?)。例如,您可以使用与FindByCourseIdAndStudentIdAuthorizedQueryHandler
具有相同界面的FindByCourseIdAndStudentIdQueryHandler
。您可以在应用程序的组合根(DIC)中替换它们。