Buduję interfejs API REST, dla którego kilku użytkowników z różnymi rolami będzie miało dostęp do zasobów w nim zawartych.
Aby uprościć zakres, weźmy domenę „uczeń / nauczyciel / klasa”:
GET /students
jest zasobem do uzyskania dostępu.
Użytkownicy mogą pełnić role takie jak Student i / lub Nauczyciel
Studenci będą mieli dostęp tylko do uczniów swoich klas. Nauczyciele będą mieli dostęp do uczniów klas, których nauczają. Niektóre zastosowania mogą być uczniem ORAZ uczyć także innych klas. Muszą mieć dostęp do uczniów swoich klas ORAZ do uczniów klas, których nauczają.
Idealnie chcę zaimplementować to jako dwie funkcje - po jednej na rolę, a następnie „unii”, jeśli użytkownik ma wiele ról.
Moje pytanie brzmi: jakiego wzoru należy użyć do wdrożenia tego?
Zewnętrznie
- Czy powinienem podzielić mój interfejs API na rolę?
GET /teacher/students
iGET /student/students
nie wydaje mi się to właściwe. - Zachowaj wszystko, jestem jednym zasobem (preferowane)
Wewnętrznie
Jak należy to wdrożyć wewnętrznie?
- Czy każda metoda powinna zaczynać się od BIG switch / if per role?
- Czy powinienem wdrożyć repozytorium według roli?
- Czy istnieje wzór, który pomoże mi to osiągnąć?
Na marginesie: używam ASP.NET Web API i Entity Framework 6 , ale tak naprawdę nie ma to znaczenia dla implementacji koncepcyjnej.
źródło
Odpowiedzi:
Interfejs API należy budować wokół zasobów, a nie ról, np .:
powinny być dostępne dla każdego, kto ma rolę, która pozwala im widzieć uczniów.
Wewnętrznie wdrażasz zabezpieczenia oparte na rolach. To, jak sobie z tym poradzisz, zależy od szczegółów aplikacji, ale załóżmy, że masz tabelę ról, każda osoba ma jedną lub więcej ról, a te role określają, do czego każda osoba może uzyskać dostęp. Już określiłeś zasady dostępu do studentów:
Kiedy więc osoba dzwoni:
nazywasz metodę dostępną dla uczniów, przekazując rolę osoby. Oto pseudo kod:
i w tej metodzie możesz zdobyć uczniów dla każdej roli z osobnymi wywołaniami, np .:
To bardzo trudny pomysł na to, co możesz zrobić i niekoniecznie będzie pasował do twoich konkretnych potrzeb, ale powinien dać ci poczucie zaangażowanych elementów. Jeśli chcesz zwrócić zajęcia z każdym uczniem na liście, jest to dobre podejście. Jeśli chcesz tylko uczniów, możesz wyodrębnić ich z każdej klasy i połączyć w zbiór uczniów.
Nie, nie powinieneś mieć osobnego repozytorium dla każdej roli. Jedyną rolą jest ustalenie, w jaki sposób otrzymujesz dane i być może to, co możesz zrobić z danymi (np. Nauczyciele mogą wprowadzać oceny uczniów). Same dane są takie same.
Jeśli chodzi o wzorce, w tym podejściu stosuje się wzorzec fabryczny, aby wyodrębnić usługę, która pobiera dane na podstawie roli. Wydzielenie usług według roli może być lub może nie być właściwe. Podoba mi się to podejście, ponieważ minimalizuje ilość kodu na każdym etapie programu i sprawia, że jest bardziej czytelny niż przełącznik lub blok.
źródło
Znajdź długopis i papier i zacznij modelować swój system.
Przekonasz się, że prawdopodobnie potrzebujesz podmiotu o nazwie PERSON. Ponieważ zarówno UCZNIOWIE, jak i NAUCZYCIEL „OSOBA”, można utworzyć abstrakcyjny byt o nazwie OSOBA o ogólnych atrybutach, takich jak imię, nazwisko itp. NAUCZYCIEL -> to-a -> Osoba. Teraz możesz spróbować znaleźć cechy NAUCZYCIELA, które nie dotyczą UCZNIÓW; np. NAUCZYCIEL prowadzi zajęcia (klasy) dotyczące jednego lub więcej TEMATÓW.
Wymuszanie bezpieczeństwa jest uważane za niefunkcjonalny aspekt twojej aplikacji. Jest to problem przekrojowy, którym należy się zająć poza „logiką biznesową”. Jak zauważa @Robert Munn, ROLĘ należy zachować w jednym miejscu. Korzystanie z ról w celu ograniczenia dostępu do niektórych funkcji jest raczej gruboziarniste, a koncepcja nazywa się kontrolą dostępu opartą na rolach (RBAC).
Aby sprawdzić, czy nauczyciel powinien mieć możliwość zobaczenia ocen uczniów, należy je wyrazić w modelu domeny. Powiedzmy, że nauczyciel ma zajęcia z programowania przedmiotów. Prawdopodobnie wyraziłbyś w swoim modelu, że uczniowie uczęszczają na zajęcia z różnych przedmiotów. Tutaj zaczyna się logika aplikacji / biznesu. Logikę tę można zweryfikować za pomocą programowania testowego.
Państwo powinno podzielić swoje zasoby, aby aplikacja sprawdzalne i modułowe.
W każdym razie najlepszym sposobem, aby naprawdę pokazać, co mam na myśli, jest pokazanie go za pomocą kodu :) Oto strona GitHub: https://github.com/thomasandersen77/role-based-rest-api
Powodzenia :)
źródło