JBoss Seam – zabezpieczanie elementów strony na podstawie ról
Ostatnio otrzymuję sygnały, że od zbyt dawna nie poruszałem tematów związanych z JBoss Seam. Dlatego dzisiaj napiszę coś o autoryzacji.
W projekcie zawierającym uwierzytelnianie utworzę dwie role – admin i user. Następnie będę ukrywał elementy menu strony na podstawie roli zalogowanego użytkownika.
W projekcie zawierającym interfejs WWW otwieram plik layout/template.xhtml, gdzie znajdują się elementy wspólne dla wszystkich stron w aplikacji. Zanim przejdę do sedna sprawy, muszę upewnić się, że przestrzenie nazw xmlns:h, xmlns:s i xmlns:rich zostały zdefiniowane dla znacznika f:view na początku dokumentu:
<f:view contentType="text/html" xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:a="http://richfaces.org/a4j" xmlns:s="http://jboss.com/products/seam/taglib" xmlns:rich="http://richfaces.org/rich">
Następnie wyszukuję fragment odpowiadający za wyświetlanie ciała strony:
<div class="body">
<h:messages id="messages" globalOnly="true"
styleClass="message" errorClass="errormsg"
infoClass="infomsg" warnClass="warnmsg"
rendered="#{showGlobalMessages != 'false'}" />
<ui:insert name="body" />
</div>
Pokrótce wyjaśnię poszczególne znaczniki:
div- określa fragment strony, w tym wypadku zawierający główną treść,
h:messages- służy do wyświetlania wiadomości (informacji, ostrzeżeń, błędów) przesyłanych przez aplikację,
ui:insert- wstawia obiekt
ui:defineo podanej nazwie, zdefiniowany w głównym pliku aktualnie wyświetlanej strony.
Nieco zmienię układ elementów – na lewo od zawartości strony dodam menu panelowe (linijki 02–24) z elementami podzielonymi na narzędzia administratora (04–10), użytkownika (11–17) i gościa (18–22):
<h:panelGrid columns="2">
<s:div styleClass="menu">
<rich:panelMenu style="width:200px" mode="ajax">
<rich:panelMenuGroup
label="Narzędzia administratora">
<rich:panelMenuItem
label="Użytkownicy" />
<rich:panelMenuItem
label="Ustawienia" />
</rich:panelMenuGroup>
<rich:panelMenuGroup
label="Narzędzia użytkownika">
<rich:panelMenuItem
label="Moje konto" />
<rich:panelMenuItem
label="Preferencje" />
</rich:panelMenuGroup>
<rich:panelMenuGroup
label="Narzędzia gościa">
<rich:panelMenuItem
label="Wyjdź ze strony" />
</rich:panelMenuGroup>
</rich:panelMenu>
</s:div>
<s:div styleClass="body">
<h:messages id="messages" globalOnly="true"
styleClass="message" errorClass="errormsg"
infoClass="infomsg" warnClass="warnmsg"
rendered="#{showGlobalMessages != 'false'}" />
<ui:insert name="body" />
</s:div>
</h:panelGrid>
Elementnacznik h:panelGrid układa zawarte w nim elementy w tablicę o podanej liczbie kolumn. Należy zauważyć, że element div został zamieniony na s:div, aby umożliwić przetworzenie odpowiednich fragmentów na komórki tablicy (atrybut class został zastąpiony przez styleClass!).
Po uruchomieniu aplikacji w przeglądarce, widoczne są wszystkie grupy elementów menu. Do wykonania pozostała jeszcze najważniejsza część pracy, czyli umieszczenie regół autoryzacji:
<rich:panelMenuGroup
label="Narzędzia administratora"
rendered=
"#{identity.loggedIn and identity.hasRole('admin')}">
<rich:panelMenuItem
label="Użytkownicy" />
<rich:panelMenuItem
label="Ustawienia" />
</rich:panelMenuGroup>
<rich:panelMenuGroup
label="Narzędzia użytkownika"
rendered=
"#{identity.loggedIn and identity.hasRole('user')}">
<rich:panelMenuItem
label="Moje konto" />
<rich:panelMenuItem
label="Preferencje" />
</rich:panelMenuGroup>
<rich:panelMenuGroup
label="Narzędzia gościa"
rendered="#{not identity.loggedIn}">
<rich:panelMenuItem
label="Wyjdź ze strony" />
</rich:panelMenuGroup>
Wykorzystany został atrybut rendered umieszczony w znaczniku rich:panelMenuGroup. Dany element wyświetlany jest wtedy i tylko wtedy gdy #{wyrażenie} jest prawdziwe. Wartość identity.loggedIn określa, czy użytkownik jest w tej chwili zalogowany, podczas gdy metoda identity.hasRole(role-name) sprawdza, czy zalogowany użytkownik posiada określoną rolę.
Tym razem po uruchomieniu przeglądarki widoczne są jedynie narzędzia gościa (niezalogowany – not identity.loggedIn). Po zalogowaniu na konto użytkownika z rolą admin pojawią się tylko narzędzia administratora. Natomiast uwierzytelnienie użytkownika jako posiadacza roli user spowoduje wyświetlenie tylko grupy narzędzi użytkownika.
W podobny sposób można zabezpieczyć też inne elementy strony przed nieautoryzowanym wyświetlaniem. Teoretycznie całą aplikację można by napisać używając jedynie ukrywania elementów strony, jednak w kolejnych wpisach omówię także inne poziomy autoryzacji, dające więcej możliwości.



