Je construis une API REST pour laquelle plusieurs utilisateurs avec des rôles différents auront accès aux ressources qu'elle contient.
Pour garder la portée simple prenons le domaine "étudiant / enseignant / classe":
GET /students
est la ressource à laquelle accéder.
Les utilisateurs peuvent avoir des rôles comme étudiant et / ou enseignant
Les étudiants n'auront accès qu'aux étudiants de leurs classes. Les enseignants auront accès aux étudiants des classes qu'ils enseignent. Certaines utilisations peuvent être étudiantes ET enseigner d'autres classes aussi. Ils doivent avoir accès aux étudiants de leurs classes ET aux étudiants des classes qu'ils enseignent.
Idéalement, je veux implémenter cela comme deux fonctions - une par rôle et ensuite "union" si un utilisateur a plusieurs rôles.
Ma question est: quel modèle dois-je utiliser pour l'implémenter?
Extérieurement
- Dois-je diviser mon API par rôle?
GET /teacher/students
etGET /student/students
cela ne me semble pas juste. - Gardez tout ce que je suis une ressource (préféré)
Intérieurement
Comment doit-il être mis en œuvre en interne?
- Chaque méthode doit-elle commencer par un GRAND commutateur / si par rôle?
- Dois-je implémenter un référentiel par rôle?
- Existe-t-il un modèle de conception qui m'aidera à y parvenir?
En guise de commentaire secondaire: j'utilise l' API Web ASP.NET et Entity Framework 6 , mais cela n'a pas vraiment d'importance pour l'implémentation conceptuelle.
la source
Réponses:
Vous devez structurer l'API autour des ressources, pas autour des rôles, par exemple:
devrait être accessible à toute personne ayant un rôle qui lui permet de voir les élèves.
En interne, vous implémentez la sécurité basée sur les rôles. La façon dont vous procédez dépend des détails de votre application, mais supposons que vous ayez une table de rôles, chaque personne a un ou plusieurs rôles, et ces rôles déterminent à quoi chaque personne peut accéder. Vous avez déjà énoncé les règles d'accès aux étudiants:
Donc, quand une personne appelle:
vous appelez une méthode qui accède aux étudiants, en passant dans le rôle de la personne. Voici un pseudo code:
et dans cette méthode, vous pouvez obtenir les étudiants pour chaque rôle avec des appels séparés, par exemple:
C'est une idée très approximative de ce que vous pourriez faire et ne répondra pas nécessairement à vos besoins spécifiques, mais cela devrait vous donner une idée des éléments impliqués. Si vous souhaitez retourner les cours avec chaque élève répertorié, c'est une bonne approche. Si vous voulez juste les étudiants, vous pouvez les extraire de chaque classe et les fusionner dans une collection d'étudiants.
Non, vous ne devriez pas avoir de référentiel distinct par rôle. Tout ce rôle consiste à déterminer comment vous obtenez les données, et peut-être ce que vous pouvez faire avec les données (par exemple, les enseignants peuvent entrer les notes des élèves). Les données elles-mêmes sont les mêmes.
En ce qui concerne les modèles, cette approche utilise Factory Pattern pour abstraire le service qui obtient les données en fonction du rôle. Il peut être approprié ou non d'avoir des services distincts par rôle. J'aime cette approche car elle minimise la quantité de code à chaque étape du programme et la rend plus lisible qu'un commutateur ou un bloc if.
la source
Trouvez un stylo et un papier et commencez à modéliser votre système.
Vous constaterez que vous avez probablement besoin d'une entité de domaine appelée PERSON. Puisque les ÉTUDIANTS et le PROFESSEUR "est-une" PERSONNE, vous pouvez créer une entité abstraite appelée PERSONNE avec des attributs génériques comme prénom, nom de famille, etc. UN PROFESSEUR -> est-a -> Personne. Vous pouvez maintenant essayer de trouver des caractéristiques pour un ENSEIGNANT qui ne s'appliquent pas aux ÉTUDIANTS; Par exemple, UN ENSEIGNANT enseigne des classes concernant un ou plusieurs sujet (s).
L'application de la sécurité est considérée comme un aspect non fonctionnel de votre application. Il s'agit d'une préoccupation transversale qui doit être traitée en dehors de votre «logique métier». Comme le souligne @Robert Munn, le (s) RÔLE (s) doivent tous être conservés au même endroit. L'utilisation de rôles pour limiter l'accès à certaines fonctions est plutôt grossière et le concept est appelé contrôle d'accès basé sur les rôles (RBAC).
Pour vérifier si un enseignant doit être autorisé ou non à voir les notes des élèves, doit être exprimé dans votre modèle de domaine. Disons qu'un enseignant a un cours sur la programmation du sujet. Vous exprimeriez probablement dans votre modèle que les élèves suivent des cours dans différentes matières. C'est là que la logique d'application / métier entre en jeu. C'est une logique que vous pouvez vérifier à l'aide d'un développement piloté par les tests.
Vous devez partager vos ressources pour faire votre demande testable et modulaire.
Quoi qu'il en soit, la meilleure façon de vraiment montrer ce que je veux dire est de le montrer avec du code :) Voici une page GitHub: https://github.com/thomasandersen77/role-based-rest-api
Bonne chance :)
la source