EJB Security


Tym razem poruszę zagadnienia związane z zabezpieczeniem bean’ów działających w ramach kontenera JBoss AS EJB. W tym celu stworzymy arcyciekawą aplikację – komercyjny kalkulator. Osoby niezarejestrowane będą miały możliwość wykonywania jedynie operacji dodawania, podczas gdy każdy użytkownik należący do grupy ENTERPRISE także operację mnożenia. Serwer aplikacyjny JBoss posiada wbudowaną obsługę standardu LDAP, relacyjnych baz danych oraz plików płaskich, gdzie składować możemy nazwy użytkowników, ich hasła oraz informacje na temat przynależności do poszczególnych ról. Dla zachowania prostoty owego przykładu zdecydowałem się na przechowywanie owych informacji w plikach płaskich.

Pierwszy krok, jaki należy wykonać, to konfiguracja serwera aplikacyjnego, czyli stworzenie tzw. securoty domain, przykładowego zarejestrowanego użytkownika, przypisanie mu hasła oraz roli ENTERPRISE. Na początku (czyt. wewnątrz taga <policy>) pliku $JBOSS_HOME/server/default/conf/login-config.xml dopisujemy:

<application-policy name="CommercialCalculator">
  <authentication>
    <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule"
                  flag = "required">
      <module-option name="unauthenticatedIdentity">anonymous</module-option>
      <module-option name="usersProperties">props/cc-users.properties</module-option>
      <module-option name="rolesProperties">props/cc-roles.properties</module-option>
    </login-module>
  </authentication>
</application-policy>

Następnie tworzymy dwa pliki cc-users.properties oraz cc-roles.properties (w podkatalogu props/). Struktura plików powinna mieć formę properties, tzn. każdy wiersz posiada parę klucz-wartość rozdzieloną znakiem równości. Linia rozpoczęta symbolem # traktowana jest jako komentarz. Plik cc-users.properties zawiera nazwy użytkowników oraz przypisane im hasła (niezaszyfrowane niestety, aczkolwiek istnieje taka możliwość: http://community.jboss.org/wiki/UsersRolesLoginModule). Drugi plik zaś, definiuje role posiadane przez danego użytkownika. W przypadku większej niż jedna ilości ról, należy rozdzielić je przecinkiem. Zwróćmy uwagę na użytkownika anonimowego, gdyż musi on posiadać odpowiedni wpis w pliku login-config.xml, jak i cc-users.properties. Przykładowe pliki konfiguracyjne:

cc-users.properties:

foo=bar
anonymous=

cc-roles.properties:

foo=ENTERPRISE

Zastanawia mnie teraz, czy istnieje możliwość definiowania hierarchii ról… Wracając do przykładu – stwórzmy ziarno EJB (Stateless, Remote) kalkulatora wykorzystując adnotacje @RolesAllowed oraz @PermitAll. W tutorialu tym nie opisuję szczegółowo kolejnych kroków tworzenia projektu EJB w Eclipse IDE. Jeśli ktoś przypadkiem trafił na ten mini-artykuł z wyszukiwarki Google, odsyłam do mojego poprzedniego wpisu na temat EJB i JPA, gdzie wymagane kroki zostały szczegółowo przedstawione.

import javax.annotation.security.PermitAll;
import javax.annotation.security.RolesAllowed;
import javax.ejb.Stateless;

import org.jboss.ejb3.annotation.SecurityDomain;

@Stateless
@SecurityDomain("CommercialCalculator")
@RolesAllowed("ENTERPRISE")
public class CommercialCalculator implements CommercialCalculatorRemote {
    @PermitAll
    public int add(int a, int b) {
        return a + b;
    }

    public int multiply(int a, int b) {
        return a * b;
    }
}

Klasa CommercialCalculator opatrzona została adnotacją @SecurityDomain, która specyfikuje, z której domeny bezpieczeństwa korzysta ziarno EJB. Domena ta zdefiniowana została przez Nas uprzednio w pliku login-config.xml. Adnotację @RolesAllowed stosować można w odniesieniu do całej klasy (definiuje wtedy role wymagane domyślnie do użycia jakiejkolwiek z metod) lub dla pojedynczej metody. @PermitAll przesłania adnotację @RolesAllowed udostępniając wszystkim wywołanie owej metody.

Przedstawię teraz kod klienta. Niestety JBoss nie trzyma się tutaj standardów. Serwer aplikacyjny nie korzysta z atrybutów Context.SECURITY_PRINCIPAL oraz Context.SECURITY_CREDENTIALS. Mało tego – udostępnia on całkowicie odrębny mechanizm logowania! Szczegóły widać gołym okiem na poniższym listingu (por.: http://nurkiewicz.blogspot.com/2009/08/invoking-secured-remote-ejb-in-jboss-5.html i http://community.jboss.org/wiki/SecurityFAQ).

import java.util.Properties;
import javax.naming.Context;
import javax.naming.InitialContext;
import org.jboss.security.client.SecurityClient;
import org.jboss.security.client.SecurityClientFactory;
import edu.lantoniak.ejb.security.CommercialCalculatorRemote;

public class Main {
    public static void main(String[] args) throws Exception {
        SecurityClient securityClient = null;
        try {
            securityClient = SecurityClientFactory.getSecurityClient();
//          securityClient.setSimple("anonymous", "");
            securityClient.setSimple("foo", "bar");
            securityClient.login();

            Properties props = new Properties();
            props.put(Context.INITIAL_CONTEXT_FACTORY,
                      "org.jnp.interfaces.NamingContextFactory");
            /* Not supported by JBoss AS. */
//          props.put(Context.INITIAL_CONTEXT_FACTORY,
//                    "org.jboss.security.jndi.JndiLoginInitialContextFactory");
//          props.put(Context.SECURITY_PRINCIPAL, "foo");
//          props.put(Context.SECURITY_CREDENTIALS, "bar");
            props.put(Context.PROVIDER_URL, "localhost:1099");
            props.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces");

            Context ctx = new InitialContext(props);

            CommercialCalculatorRemote calc =
                (CommercialCalculatorRemote) ctx.lookup("CommercialCalculator/remote");
            System.out.println(calc.multiply(2, 2));
            System.out.println(calc.add(1, 2));
        } finally {
            if (securityClient != null) {
                securityClient.logout();
            }
        }
    }
}

Zachęcam czytelników do zabawy w komentowanie i odkomentowywanie na przemian linii 13, 14 oraz 32, 33.

Źródła projektów: Tutorial 6 All.zip.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: