JBoss Seam – encja uprawnień
Po długiej przerwie powrócę wreszcie do tematu uprawnień. Do tej pory omówiłem jedynie autoryzację użytkownika na podstawie roli – zarówno dla strony, jak i komponentu. Teraz nadeszła pora na dynamiczne przypisywanie rolom uprawnień do poszczególnych metod komponentów czy elementów strony.
Zanim przejdę do samej autoryzacji, muszę przygotować odpowiednią encję, która posłuży mi do pobierania uprawnień z bazy danych. Taka encja, poza adnotacjami JPA i Hibernate, będzie zawierała szereg dodatkowych adnotacji z pakietu org.jboss.seam.annotations.security.permission opisujących pola związane z uprawnieniami.
Na początek zdefiniuję odpowiednią encję wraz z unikalnym indeksem:
package pl.info.czerwinski.blog;
import java.io.Serializable;
import javax.persistence.*;
import org.hibernate.validator.*;
import org.jboss.seam.annotations.security.permission.*;
@Entity
@Table(
name = "permissions",
uniqueConstraints = {
@UniqueConstraint(
columnNames = {
"target",
"action",
"recipient"})
})
public class Permission implements Serializable {
private final static long serialVersionUID = 1L;
}
Dla encji muszę określić kilka podstawowych pól. Pierwszym z nich będzie klucz główny – to pole raczej nie wymaga dodatkowych wyjaśnień:
@Id @GeneratedValue @Column(name = "id") @NotNull Long id;
Uprawnienie wymaga określenia trzech podstawowych informacji (Seam wymaga, aby wszystkie były typu java.lang.String):
- obiektu, którego dotyczy (przedmiot uprawnienia – target),
- czynności, jaką można wykonać (akcja – action),
- uprawnionego użytkownika albo roli (adresat uprawnienia – recipient).
Przedmiot uprawnienia oznaczany jest adnotacją @PermissionTarget:
@Column(name = "target") @Length(max = 64) @NotNull @PermissionTarget String target;
Akcja posiada adnotację @PermissionAction:
@Column(name = "action") @Length(max = 64) @NotNull @PermissionAction String action;
W przypadku adresata sprawa nieco się komplikuje. JBoss Seam pozwala przypisywać uprawnienia zarówno do ról, jak i do użytkowników, więc mogę zastosować jedno z dwóch rozwiązań:
- Utworzyć dwa pola – jedno dla użytkownika, drugie dla roli.
- Utworzyć jedno pole, w będzie przechowywany login użytkownika albo nazwa roli.
Ja zdecyduję się na to drugie rozwiązanie i utworzę pole jedno z dwiema adnotacjami – @PermissionUser i @PermissionRole:
@Column(name = "recipient") @Length(min = 3, max = 32) @NotNull @PermissionUser @PermissionRole String recipient;
Jednak Seam (właściwie to magazyn tożsamości – JPA Permission Store) musi mieć możliwość rozróżnienia użytkownika i roli. W tym celu należy dodać kolejne pole albo właściwość z adnotacją @PermissionDiscriminator – wartość "user" albo "role" będzie oznaczać odpowiednio użytkownika albo rolę.
Tutaj pojawia się kolejna komplikacja – chciałbym, aby w moim systemie uprawnienia były nadawane tylko rolom. Dlatego też utworzę właściwość, która nie będzie mapowana na kolumnę w relacji (@Transient), i która zawsze będzie miała wartość "role":
@Transient
@PermissionDiscriminator
public String getDiscriminator() {
return "role";
}
@Deprecated
public void setDiscriminator(String dump) {
}
Zastosowana przy metodzie setDiscriminator adnotacja @Deprecated sprawi, że będę zawsze ostrzegany o próbie użycia tej metody (normalnie używa się jej do oznaczenia metod wychodzących z użycia w którejś z kolejnych wersji). Takie ostrzeżenie przyda się w sytuacji, gdy zapomnę, że ta metoda nic nie robi, a uprawnienie dotyczy zawsze roli.
Aby encja uprawnień zadziałała, potrzebuję jeszcze dodać odpowiedni wpis konfiguracyjny w pliku components.xml:
<security:jpa-permission-store
user-permission-class=
"pl.info.czerwinski.blog.Permission"/>
Następnym razem omówię dokładniej, w jaki sposób zabezpieczać komponenty i strony z wykorzystaniem uprawnień.




Extra, świetny content