Czas posmęcić o informatyce...
Kontenery referencyjnego serwera aplikacji Java EE udostępniają trzy mechanizmy bezpieczeństwa dla komponentów aplikacji odpowiedzialnych za uwierzytelnianie użytkowników i autoryzację dostępu do zasobów i funkcjonalności.
- mechanizm deklaratywny - kluczowym elementem mechanizmu jest deskryptor wdrożenia, w którym w sposób deklaratywny zapisane są wymagania dotyczące prawidłowego wdrożenia i wykorzystania mechanizmu bezpieczeństwa. Deskryptor pełni tu rolę kontraktu. Wyróżniamy dwa poziomy, na których może być wykorzystany deklaratywny mechanizm bezpieczeństwa:
· Poziom aplikacji (ang.
Application Level Security) – na poziomie aplikacji, role wykorzystywane w aplikacji muszą być zdefiniowane za pomocą adnotacji DeclareRoles, RolesAllowed lub w elementach
w pliku deskryptora wdrożenia aplikacji. Mapowanie roli na zarządców definiuje się w elemencie , dla wszystkich ról wykorzystywanych w systemie. Zdefiniowane role dotyczą wszystkich komponentów aplikacji. Pozwala to na pewnego rodzaju generalizację ról w aplikacji. Jeśli w deskryptorze wdrożenia konkretnego komponentu aplikacji zdefiniowano role, to komponent ten poza tymi rolami, może również korzystać z ról zdefiniowanych na poziomie aplikacji.
· Poziom komponentu (ang.
Component Level Security) – Dotyczy konkretnego komponentu aplikacji. W przypadku komponentów webowych może to być na przykład serwelet. Wówczas nazwy ról powinny być zdefiniowanie w deskryptorze wdrożenia serwletu – w
eb.xml.
-
Mechanizm programowalny – programowalny mechanizm bezpieczeństwa, wykorzystywany jest, gdy deklaratywny mechanizm jest niewystarczający do spełnienia wymagania modelu aplikacji. Mechanizm ten dotyczy komponentów EJB oraz serwletów i opiera na wykorzystaniu metod interfejsu
EJBContext dla komponentów EJB oraz interfejsu
HttpServletRequest dla serwletu. Metody te zostały wymienione poniżej:
· isCallerInRole (EJBContext),· getCallerPrincipal (EJBContext),· isUserInRole (HttpServletRequest),· getUserPrincipal (HttpServletRequest),· getUserRemote (HttpServletRequest).Metoda getUserInRole pozwala na uzyskanie informacji o roli, jaką posiada użytkownik, metoda getUserPrincipal zwraca obiekty klasy Principal z pakietu java.security.Principal, natomiast metoda getUserRemote zwraca nazwę użytkownika, który ma zostać uwierzytelniony. Wymieniony zestaw metod pozwala na podejmowanie biznesowych decyzji w oparciu o logiczną rolę użytkownika.
Przykładem wykorzystania mechanizmu programowalnego może być sytuacja w której aplikacja dokonuje autoryzacji w oparciu o parametry środowiskowe lub parametry wywołania komponentu webowego. Na listingu przedstawiony został szkielet kodu serwletu wykorzystujący metody
getUserPrincipal i
getName.
public void doGet(HttpServletRequest request, HttpServletResponse response) {
String userName;
... //inny kod
//Uzyskanie obiektu obiektu nadzorcy z żądania HTTP
Principal principal = request.getUserPrincipal();
if (principal != null) {
//Uzuskanie nazwy nadzorcy
userName = principal.getName();
}
... //inny kod
}
Listing: Szkielet kodu wykorzystanie metody getUserPrincipal i getName w serwlecie.
Jeżeli serwlet jest tylko jednym z komponentów aplikacji i dla niego zostały zdefiniowanie role to mogą one posłużyć do określenia pozwoleń dla ról w innych komponentach aplikacji. Sytuacja taka może wystąpić, jeśli cześć funkcjonalności serwletu wykorzystuje kod innych komponentów aplikacji. Za pomocą deskryptora wdrożenia można obsłużyć taka ewentualność i przekazać pozwolenia roli określonej w serwlecie do roli zdefiniowanej w całej aplikacji. Rozwiązanie takie jest możliwe poprzez wykorzystanie elementu
, będącego podelementem
<>.
<security-role-ref>
<role-name>role_A</role-name>
<role-link>role_B</role-link>
</security-role-ref>
Listing: Konfiguracja w deskryptorze wdrożenia.
public void doGet(HttpServletRequest request, HttpServletResponse response) {
... //inny kod
//Uzyskanie obiektu obiektu nadzorcy z żądania
if (request.isUserInRole("role_A")) {
//przekierowanie do strony roli "role_B"
} else {
//przekierowanie do strony błędu autoryzacji
}
... //inny kod
}
Listing: Szkielet kodu serwletu ilustrujący sytuację, gdzie konieczne jest przekazanie pozwoleń przyznanej roli zdefiniowanej w jednym komponencie, do roli zdefiniowanej w innym komponencie.
-
Mechanizm oparty o adnotacje (ang.
annotations) – Adnotacje są metadanymi, pozwalającymi na podanie pewnych parametrów konfiguracyjnych dla kodu w języku Java. Wykorzystywane są do deklarowania zależności wykonania kodu od kontekstu i konfiguracji, w jakiej ma zostać wykonany. Zgodnie ze specyfikacją Java EE, adnotacje dla komponentów webowych zostały dołączone do specyfikacji serwletów. Dla komponentów webowych dostępne są adnotacje:
· @DeclareRole,· @RunAs.Adnotacja
@DeclareRole jest alternatywą dla elementu
w deskryptorze wdrożenia aplikacji webowej. Jej wartość specyfikuje rolę, jaką muszą posiadać użytkownicy, aby mieć dostęp do funkcjonalności oferowanej przez obiekt klasy. Przykładowo, zadeklarowanie, że klasa dostępna jest dla użytkowników posiadających rolę administratora byłaby następująca:
@DeclareRole("Admin")
public class nazwa_klasy {
...
}
Adnotacja @RunAs pozwala na definiowanie ról w komponencie aplikacji, które mają swoje odpowiedniki na poziomie serwera. Odpowiednikiem adnotacji @RunAs jest element <> w deskryptorze wdrożenia aplikacji.
To tyle tytułem wprowadzenia do pojęcia bezpieczeństwa w standardzie Java EE. Następny post w tym temacie będzie o uwierzytelnianiu klientów webowych.