JAAS
e JBoss
In
JBoss la sicurezza viene gestita dal modulo JBossSX
basato sullo standard JAAS.
Il cuore della sicurezza del modulo JBossSX è
la classe JaasSecurityManager che implementa due interfacce
proprietarie:
1)
AuthenticationManager: gli viene accreditato il compito
di controllare la validazione delle credentials associate
al principals.
2) RealmMapping: è responsabile nella mappatura
delle role e dei principals.
Come
tutti i servizi di JBoss anche al JaasSecurityManager
sono associati degli MBean definiti nel file jboss.jcml:
<!--
========================================================
-->
<!-- Security -->
<!-- ========================================================
-->
<!--
JAAS security manager and realm mapping -->
<mbean code="org.jboss.security.plugins.JaasSecurityManagerService"
name="Security:name=JaasSecurityManager">
<attribute
name="SecurityManagerClassName">
org.jboss.security.plugins.JaasSecurityManager
</attribute>
<attribute name="LoginConfig">
Security:name=DefaultLoginConfig
</attribute>
</mbean>
<mbean code="org.jboss.security.plugins.DefaultLoginConfig"
name="Security:name=DefaultLoginConfig">
<attribute name="AuthConfig">auth.conf</attribute>
</mbean>
L'associazione
del JaasSecurityManager al modulo di login, atto a creare
il mio Subject con le proprie credenziali, avviene nel
file auth.conf.
La struttura è la seguente:
nome_dominio1
{
classe modulo di login
eventuali parametri
};
nome_dominio2 {
classe modulo di login
eventuali parametri
};
etc
.
Per
quanto riguarda i moduli di login JBoss mi mette a disposizioni
classi predefinite; questo non toglie che l'utente possa
implementarsi un proprio modulo di login.
La traccia da seguire è la seguente: devo implementare
la classe AbstractLoginModule e fare l'override di tutti
i metodi abstract in essa contenuti.
Qui viene utilizzata la classe org.jboss.security.auth.spi.DatabaseServerLoginModule
DatabaseServerLoginModule
La
classe DatabaseServerLoginModule è un modulo
di login che si appoggia ad un database per memorizzare
all'interno di tabelle le mie roles e i miei principals.
Le due tabelle sono:
CREATE
TABLE Principals (
PrincipalID VARCHAR(64) PRIMARY KEY,
Password VARCHAR(64) )
);
CREATE
TABLE Roles (
PrincipalID VARCHAR(64),
Role VARCHAR(64),
RoleGroup VARCHAR(64) )
);
Nella
prima tabella ho l'associazione tra principals e password;
nella seconda ho l'associazione fra principals e roles.
I parametri della classe sono fra gli altri:
a)
il modulo di login rappresentato dalla classe specificata.
b) dsJndiName: rappresenta il JNDI name associato al
mio database attraverso la configurazione precedentemente
fatta nel file jboss.xml.
c),d) sono le query utilizzate per interrogare le tabelle
nel database.
Vediamo
un esempio:
dominio1
{
a) org.jboss.security.auth.spi.DatabaseServerLoginModule
required
b) dsJndiName="java:/DefaultDS"
c) principalsQuery="select Password from Principals
where PrincipalID=?"
d) rolesQuery="select Role, RoleGroup from Roles
where PrincipalID=?";
};
File jboss.xml
La
mappatura interna a JBoss avviene attraverso il solito
file jboss.xml:
Figura 1
Il
tag 'security-domain' mi identifica il nome logico (JNDI)
del security manager utilizzato da JBoss per la gestione
della sicurezza a livello di EJB appartenenti alla mia
applicazione.
Un esempio di codice per associare il mio dominio di
sicurezza con il mio EJB è il seguente:
<?xml
version="1.0" encoding="UTF-8"?>
<jboss>
<security-domain>java:/jaas/dominio1</security-domain>
<enterprise-beans>
<session>
<ejb-name>Bean1</ejb-name>
<jndi-name>ejb/Bean1</jndi-name>
</session>
</enterprise-beans>
</jboss>
premesso
l'esistenza del file ejb-jar.xml:
<?xml
version="1.0" encoding="UTF-8"?>
<!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems,
Inc.//DTD Enterprise JavaBeans 1.1//EN"
"http://java.sun.com/j2ee/dtds/ejb-jar_1_1.dtd">
<ejb-jar>
<enterprise-beans>
<session>
<ejb-name>StatelessSession</ejb-name>
<home>Bean1Home</home>
<remote>Bean1Remote</remote>
<ejb-class>Bean1</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
</session>
</enterprise-beans>
<assembly-descriptor>
<security-role>
<role-name> role1</role-name>
</security-role>
<method-permission>
<role-name>role1</role-name>
<method>
<ejb-name>Bean1</ejb-name>
<method-name>*</method-name>
</method>
</method-permission>
<method-permission>
<role-name>role2</role-name>
<method>
<ejb-name>Bean1</ejb-name>
<method-name>create</method-name>
</method>
<method>
<ejb-name> Bean1</ejb-name>
<method-name>remove</method-name>
</method>
<method>
<ejb-name> Bean1</ejb-name>
<method-name>make</method-name>
</method>
</method-permission>
</assembly-descriptor>
</ejb-jar>
A
questo punto qualsiasi utente precedentemente configurato
al quale è associata una roles di tipo role1
avrà l'accesso a qualsiasi metodo del mio EJB
mentre a chi associata la role2 potrà utilizzare
solo i metodi create, remove e make. A qualsiasi altro
utente che non soddisfa queste condizioni viene vietato
l'utilizzo dell'EJB.
Proxy
security
JBoss
mi mette a disposizione un' ulteriore metodologia per
ampliare la sicurezza associata alla mia applicazione,
separando la parte di controllo (proxy) dalla logica
di business.
Lo sviluppatore si dovrà concentrare su due fronti
differenti e ben separati: la/le classi EJB, i/il sucurity
proxy da associare ai vari EJB. Sarà poi compito
del container invocare un particolare metodo del mio
security-proxy e permettere o meno l'invocazione del
codice del mio EJB, se le politiche di sicurezza implementata
dallo sviluppatore risultano soddisfatte . In particolare
il container creerà un istanza del MioSecurityProxy
che verrà utilizzata per tutte le istanze del
EJB (Bean1).
Per
ottenere questo risultato devo creare una classe che
implementare l'interfaccia org.jboss.security.Proxy
che ha due metodi invokeHome e invoke che vengono chiamati
dal container prima di accedere all' EJB stesso.
In particolare il metodo invokeHome mi viene invocato
dal container per controllare le credenziali dell'utente
e permette quindi l'invocazione dei metodi contenuti
nella home interface del mio EJB; mentre invoke viene
invocato per controllare le credenziali per permettere
l'accesso o meno dei metodi contenuti nella remote interface.
Per poter utilizzare la nuova classe creata ad-hoc la
devo specificare nel file jboss.xml attraverso il tag
security-proxy:
<?xml
version="1.0" encoding="UTF-8"?>
<jboss>
<security-domain>java:/jaas/dominio1</security-domain>
<enterprise-beans>
<session>
<ejb-name>Bean1</ejb-name>
<jndi-name>ejb/Bean1</jndi-name>
<security-proxy>MioSecurityProxy</security-proxy>
</session>
</enterprise-beans>
</jboss>
Per esempio una bozza di Proxy:
public
class MioSecurityProxy implements SecurityProxy {
private Category _log = Category.getInstance(
getClass().getName());
private ThreadLocal _ctx = new ThreadLocal();
public void setEJBContext(EJBContext ctx)
{
_ctx.set(ctx);
}
public void invokeHome(Method m, Object[]
args){
//Codice per la validazione
per accedere ai metodi della
//Home interface
}
private Connection getConnection(){
try{
Context in = new
InitialContext();
DataSource ds =
(DataSource)in.lookup("java:comp/
env/jdbc/MySqlDS");
return ds.getConnection();
}catch(Exception e){
e.printStackTrace();
}
return null;
}
public void invoke(Method m, Object[] args,
Object bean)
throws
SecurityException {
//Codice per la validazione
per accedere ai metodi della
//Remote interface
...
...
}
}
Conclusioni
Sicuramente
la parte di sicurezza basata sul 'proxy' è molto
interessante in quanto il mio EJB svolge solo il compito
di esecutore della business logic; purtroppo il lavoro
che faccio per gestire la sicurezza in classi separate
(proxy) è limitato al solo ambiente di JBoss
e quindi non portabile.
Bibliografia
[1] * "Manual - online HTML version"- www.jboss.org
[2] * SCOTT STARK, MARC FLEURY "JBoss Administration
and Development "- JBoss Group
[3] * Davide Brusamolino "Configurare una connessione
a db con JBoss 2.4.x" - Mokabyte Aprile 2003
|