Pardon de la longueur ici ... je espère que je ne suis pas allé trop loin ...endroit approprié pour les évaluations de sécurité - la logique métier ou d'accès aux données
Je suis en train de travailler sur ma première production MVC application et j'essaie de s'en tenir aux principes DDD dans le processus. J'ai rencontré des questions sur la façon de traiter les exigences de sécurité de l'application et je pensais que la communauté SO pourrait offrir des suggestions de meilleures pratiques.
Informations sur le domaine
Pour utiliser une explication simplifiée, cette application aura AffiliateCompanies
, Users
et Customers
.
AffiliateCompanies
sont hierarchal, de sorte qu'un affilié peut s'inscrire et être lié aux activités d'un autre affilié. La racine est la principale entreprise fournissant les produits/services.Users
appartiennent tous à une entité affiliée.Customers
sont des organisations auxquelles les produits/services sont vendus. Les affiliés sont assignés aux clients de telle sorte qu'il est possible que deux affiliés hiérarchiquement indépendants divisent un client.
Informations sur la sécurité
Droits d'effectuer certaines actions dans l'application seront déterminées à partir d'une ACL type d'arrangement. Chaque objet User
possède une propriété qui est une collection de SystemAccessRules
qui détermine les actions qu'ils peuvent effectuer et la portée de leurs autorisations (leurs propres objets, les objets de leurs affiliés ou les objets de leur hiérarchie entière). Les utilisateurs peuvent également appartenir à des rôles qui possèdent eux-mêmes la même collection de SystemAccessRules
. Par conséquent, si un utilisateur se connecte et souhaite voir une liste de «leurs» clients, la liste peut être composée de clients auxquels ils sont affectés individuellement, de clients auxquels leur organisation affiliée est affectée ou de clients. n'importe qui dans leur organisation ou l'une de leurs organisations d'enfants affiliées sont assignés à.
Considérations sur la base de données
DDD côté, à un moment donné la stratégie de stockage doit entrer en jeu. Dans ce scénario simple, les tables sont alignées avec les objets ci-dessus (y compris une table de rôles), avec quelques tables de soutien pour soutenir les relations entre les objets:
AffiliateCustomers
- ce tableau permet un grand nombre à plusieurs relation entre les affiliés et les clients en stockant le PK de chaque entité comme une paire de FK qui sont eux-mêmes un PK composite pour cette table. - cette table stocke les informations de sécurité, en particulier l'objet de l'entrée (un utilisateur ou un rôle), l'action en question (par exemple "CreateCustomer"), la permission (autoriser ou refuser) et une portée (leurs propres affaires, celles de leur organisation ou de leur réseau).
La question ...Enfin
J'utilise une combinaison de référentiels et de services. J'essaie de garder la logique métier dans les services et hors des référentiels ou de la base de données, mais en raison de la conception de sécurité ici, une simple demande pour la liste de "leurs" clients pourrait être extrêmement lourde, surtout à mesure que l'ensemble de données augmente. J'essayais d'utiliser Linq quand c'était possible, mais cette architecture ne semble pas très adaptée. Comme je le vois, voici mes choix:
Acceptez l'utilisateur qui demande comme argument pour les méthodes de service (ou le déterminer par le contexte), et ont la méthode de service remplir une liste par plusieurs requêtes au référentiel Linq. Cela nécessite d'extraire la liste des clients, puis de parcourir chaque client pour émettre une autre requête afin d'extraire les données ACL, puis d'utiliser ces données pour filtrer la première liste en fonction des autorisations. La question de la hiérarchie nécessiterait un jeu de jambes sophistiqué Linq (comme this), si c'est possible du tout.
Même si la question de hiérarchie pourrait être au travail, il semble que cette solution ne sera pas très bien ... effectuerAccepter l'utilisateur demandeur comme un argument, mais le transmettre et l'autorisation nécessaire (par exemple "Voir les clients") pour récupérer les données appropriées de la base de données via une procédure stockée qui utiliserait plusieurs clauses EXISTS dans une requête CTE qui pourrait expliquer la nature hiérarchique des données et la nécessité de vérifier le rôle et la sécurité de l'utilisateur.
Ceci pousse une bonne quantité de logique à la base de données, ce qui semble très anti-DDD et généralement mauvais.
Je suis plus vers la penchent deuxième option, mais peut-être parce que dans mes projets passés qui est comme ça que je l'ai fait. Je ne suis même pas sûr que mon design soit globalement sur la bonne voie (dans le passé, les déclarations d'autorisation étaient faites en utilisant des drapeaux bit, donc c'était encore plus facile de faire la requête DB en utilisant l'opérateur bitwise).
Est-ce que quelqu'un a été dans des situations similaires, et si oui pouvez-vous commenter sur la performance et la maintenabilité de la solution que vous avez suivie? Je veux m'en tenir à des principes de programmation ambitieux, mais pas au détriment de la simplicité et du bon sens.
Juste un commentaire, pas une réponse, mais n'oubliez pas les principes KISS et YAGNI. Concevez votre code d'application autour des interfaces de référentiel/service afin que vous puissiez toujours changer ce qui est à l'intérieur de 1 à 2. Ensuite, faites l'implémentation la plus simple et la plus simple possible. Par exemple. 2 si c'est ce que vous avez l'habitude de faire. Ne mettez pas trop dans la conception, car quelque chose que vous avez manqué peut le casser plus tard. Essayez juste de le garder assez abstrait et de le refactoriser progressivement. – queen3
Oui, je travaille à résister à l'envie de sur-ingénierie pour les exigences anticipées qui ne sont pas la réalité en ce moment. En même temps je ne veux pas me peindre dans un coin.Je pense que je vais devoir faire quelques tests pour voir à quel point il est difficile d'évaluer la sécurité en examinant le contenu d'une propriété 'IEnumerable' sur chaque objet 'AffiliateCompany' de la liste. À la fin de la journée, c'est ce qui me motive à mettre cette évaluation dans la base de données ... Je sais que la base de données sera plus rapide, mais je ne sais pas à quelle vitesse. –