干净的架构当前用户获取

Clean architecture current user acquisition

在 Clean Architecture 用例中是否应该注意 authentication/authorization 进程和 command/query 层应该使用一些框架在下面的层中实现身份验证服务的一些抽象,或者用户标识符应该作为传递command/query?

的部分

选项:

选项 1:

class ChangePasswordCommand {

    char[] newPassword;
}

class ChangePasswordCommandHandler {

    AuthService authService;

    void handle(ChangePasswordCommand command) {
        User currentUser = authService.currentUser();
        // logic
    }
}

选项 2:

class ChangePasswordCommand {

    UUID userId;
    char[] newPassword;
}

class ChangePasswordCommandHandler {

    UserRepository userRepository;

    void handle(ChangePasswordCommand command) {
         User currentUser = userRepository.findById(command.getUserId());
         // logic
    }
}

当您谈论用例时,这是您的应用程序的领域。 所以,要回答这个问题,我可以说:这取决于这个领域。

如果您的域是关于“用户管理”的(例如:LDAP 应用程序),是的!您需要在您的域中实施它。

否则,这只是一个技术问题,您可以在域外管理它(并直接调用存储库)。

示例:

假设您有一些第三方身份验证提供商提供具有以下字段的用户结构:id、电子邮件地址等。

如果没有业务规则只对用户进行身份验证,您可以从应用层调用放置在基础层的身份验证器。

    userApplication.authenticate(String login, String password) {
        userProvider.authenticate(login, password);
    }

另一方面,如果你想在认证用户时应用一些业务规则,你必须从应用层调用用户域API(接口放在域层)。

以下代码只是一个示例。你必须清理它。

应用层:

    userApplication.authenticate(String login, String password) {
        userAPI.authenticate(login, password);
    }

领域层:

    class Member {
        ...
    }

    interface UserAPI {
        Member authenticate(login, password);
    }

*您可以通过创建一些工厂或服务或任何您想要的方式来实现此接口。假设您有一个域用户服务。

    class UserService implements UserAPI {
        
        UserSPI userSPI;

        Member authenticate(login, password) {
            // apply some business rules
            userSPI.authenticate(login, password);
        }
    }

    interface UserSPI {
        Member authenticate(login, password);
    }

基础设施层:

    class MemberDTO {
        ...
    }

    class userProvider implements UserSPI {

        private final RemoteProvider remoteProvider;

        Member authenticate(login, password) {
            MemberDTO memberDTO = remoteProvider.authenticate(login, password);
            return memberMapper.dtoToDomain(memberDTO);
        }
    }