Atrybuty autoryzacji – wstęp
Sporo czasu spędzam ostatnio przy systematyzacji procesu autoryzacji w aplikacji mvc. Plan jest taki, aby każda metoda była zabezpieczona, a dostęp był zweryfikowany rolą, którą ma zalogowany użytkownik. Jak to zrobić?
Z pomocą przychodzą atrybuty, ja wykorzystałem dwa (te same, ale dwa)
Atrybuty jako AOP
Atrybuty służą do tego aby zdefiniować kod, który powinien się wykonać przed wykonaniem metody która została oznaczoną danym atrybutem. Umożliwia to wyniesienie części wspólnej gdzieś indziej i nie zaśmiecanie metod powtarzającą się funkcjonalnością. Przykładem tego co można wynieść do atrybutów może być logowanie do plików czy właśnie weryfikacje dostępów. Takie programowanie nazywa się programowaniem aspektowym AOP – i mocno polecam zapoznanie się z nim bo jest cool.
Dobra, pitu pitu – pitu pitu. Mięso:
Widać tu przykładowy kontroler, który zawiera kilka metod. Metody zostały wzbogacone o atrybut BlogAuthorization, AllowAnonymous oraz jedna pozostawiona sama sobie tak ma być.
Nudna część: Index, About, Contact.
Ciekawsze to Login: gdzie tworzymy jakiegoś użytkownika, nadajemy mu role Reader (same role zdefiniowane są w innym miejscu – jako prosty enum), potem logujemy przy pomocy domyślnej autentykacji, ustawionej przy starcie aplikacji.
Do pary jest także Logout, który użytkownika wylogowuje.
I na koniec metoda NotDefined, do której nie powinniśmy wejść, ponieważ nie posiada ona atrubutu AllowAnonymous ani także BlogAuthorization (o tym poniżej).
Co robi atrybut BlogAuthorization, że jest taki sprytny?
Zaczynamy od wrodzenia się do dobrej rodziny, w tym przypadku wybieramy AuthorizeAttribute. Następnie aby móc korzystać ze swoich enumów BlogRoles, a nie stringów jako ról definiuje kolekcje ról, które w locie są tłumaczone na string w-i-we-wte (właściwość BlogRoles). Szczerze mówiąc w wersji pierwszej miałem tutaj dużo więcej kodu, ale jak to sobie przemyślałem to w zasadzie to “nadpisanie” ról wystarczy. Reszta ma działać tak jak każdy inny atrybut Authorize. Wiadomo mniej kodu to czytelność++ bugowatość– a w ogólnym rozliczeniu profit!
Wszyscy mają mieć
Co zrobić aby każda metoda była oznaczona autoryzacją lub dostęp do niej był zabroniony? O to upewni się ten dodatkowy atrybut:
Jego jedyną (x2 – tak naprawdę) odpowiedzialnością, jest to aby upewnić się czy metoda nie posiada tokenu anonimowości (jeśli tak to nic nie rób) oraz czy posiada mój blogerski znak (znowu, jeśli tak to nic nie rób). Jeśli go nie posiada to ustaw Request jako nie autoryzowany. Ten zabieg spowoduje, że nie będzie następowało dalsze autoryzowanie i użytkownik zostanie obsłużony przez 401 (taka niespodzianka: https://stackoverflow.com/questions/18728631/httpstatuscoderesult401-returns-302-found)
Wprowadzenie reżimu w życie
Jak zmusić naszą aplikację aby przy każdym wywołaniu korzystała z atrybutu. Hocus-pokus:
Linijka @6, to miejsce gdzie do globalnie zarejestrowanych filtrów dodajemy kolejny – własny. W przypadku web api wszystko to powyżej zadziała w zasadzie tak samo. Należy tylko dziedziczyć po atrybucie z innego namespace (to w przypadku starszej wersji, od nowszych [nie pamiętam dokładnie których] webapi oraz mvc zostały połączone i jest mniej roboty), oraz dodać go w odrobinę innym miejscu:
Reszta pozostaje praktycznie bez zmian.
Oklaski
Voilà. Od tej pory każda metoda musi posiadać jeden z dwóch atrybutów określających kto może z niej korzystać, albo wszyscy (AllowAnonymous), albo określeni rolami (BlogAuthorizationAttribute)
Podziękowania
Tyle. Jeśli Ci się podobało i uznasz to za wartościową wiedzę, wyświadcz mi przysługę i udostępnij ten wpis na tweeterze/facebooku/linkedin czy udostępnij w inny sposób. Kilka godzin mojej pracy za kilka Twoich klików.
“Atrybuty służą do tego aby zdefiniować kod, który powinien się wykonać przed wykonaniem metody która została oznaczoną danym atrybutem.” – wcale atrybuty nie muszą być wykonywane przed wykonaniem metody, ani nawet po. Zaś samo użycie w jakimś miejscu atrybutów zamiast kodu nie oznacza, że coś jest już programowaniem aspektowym. W C# o programowanie AOP w ogóle bardzo trudno (rzadko kto je tak naprawdę stosuje), dużo popularniejsze jest w Javie. Polecam się trochę nim najpierw pobawić i dopiero wrócić do tematu.
Janek – dlaczego uważasz, że C# jest ciężko programować w AOP?
Nie ma autentykacji tylko uwierzytelnianie
Tak jest, poniósł mnie amerykański melanż.
Właśnie szukałem tego rozwiązania – wielkie dzięki:)