Maj
18
2009

JBoss Seam – zabezpieczanie elementów strony na podstawie ról

Słowa kluczowe: , | Kategorie: Seam Framework
No Gravatar

Ostatnio otrzymuję sygnały, że od zbyt dawna nie poruszałem tematów związanych z JBoss Seam. Dlatego dzisiaj napiszę coś o autoryzacji.

projekcie zawierającym uwierzytelnianie utworzę dwie role – adminuser. 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:sxmlns: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:define o 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.

Napisz Komentarz

*