2012-10-25 18 views
5

Sto studiando JAAS e sto implementando un semplice esempio da utilizzare in una webapp che utilizza Tomcat con JaasRealm.Tomcat-Jaas - Come recuperare l'oggetto?

Ora il mio problema è che non so come recuperare l'oggetto poiché il codice come Subject subject = Subject.getSubject(AccessController.getContext()); restituisce sempre null.

Sto usando Tomcat 7.0.27. C'è qualcosa che ho perso? In altri termini, come posso gestire l'autorizzazione in Java EE con JAAS? Ad esempio, come posso implementare un'azione nel contesto sicuro di JAAS?

+0

essere sicuri che il regno è utilizzato per la vostra webapp, allora si può provare di Servlet API 'HttpServletRequest.getUserPrincipal()' –

+0

sapevo che e funziona, ma ho bisogno di recuperare soggetti per ottenere anche roleprincipal – sasaman85

risposta

8

Sapevo che e funziona, ma ho bisogno di recuperare soggetti per ottenere anche roleprincipal

Purtroppo, non funziona così in Java EE. L'oggetto JAAS è solo un "sacco di principi", e quale di questi rappresenta il principale utente/chiamante e/o il ruolo principale (i) non è semplicemente standardizzato. Ogni altro contenitore fa le cose diversamente qui. Il Javadoc for Tomcat's JAASRealm descrive questo e spiega la convenzione specifica Tomcat (sottolineatura mia):

il JAAS Specifica descrive il risultato di un accesso riuscito un'istanza javax.security.auth.Subject, che può contenere zero o più java.security.Principal oggetti nel valore restituito dal metodo Subject.getPrincipals() . Tuttavia, esso non fornisce indicazioni sulla come distinguere presidi che descrivono il singolo utente (e sono pertanto opportuno restituire come valore request.getUserPrincipal() in un'applicazione web) dal Principal (s) che descrivere i ruoli autorizzati per questo utente. Per mantenere il più indipendenza possibile dalla sottostante LoginMethod implementazione eseguita da JAAS, la seguente politica viene attuata da questo regno: [...]

Oltre a ciò, da un ambiente Java EE che raramente anche avere accesso al soggetto JAAS, spesso nemmeno tramite metodi specifici del venditore. JAAS è lontano dallo standard universale che sembra pensarlo, specialmente quando riguarda Java EE.

Le uniche cose a cui è possibile accedere in modo portabile sono l'identità del chiamante ei ruoli ad esso associati, ma anche quelli non devono essere l'esatta identità del chiamante costruita dal modulo di login JAAS.

JBoss AS, ad esempio, copia questo principal un paio di volte utilizzando le sue classi. Pertanto, se il modulo JAAS memorizza un kaz.zak.FooPrincipal nell'oggetto per l'utente/il chiamante, allora HttpServletRequest#getUserPrincipal() potrebbe restituire un org.jboss.security.SimplePrincipal. L'unica cosa garantita è che getName() su quell'istanza restituirà la stessa stringa.

Per alcuni più di fondo su questo argomento:

L'ultima fonte dice fondamentalmente la stessa cosa, in una formulazione diversa;

Sebbene sia possibile utilizzare JAAS all'interno Tomcat come meccanismo di autenticazione (JAASRealm), la flessibilità del quadro JAAS si perde volta che l'utente è autenticato. Questo perché le entità principali sono utilizzate per indicare i concetti di "utente" e "ruolo" e non sono più disponibili nel contesto di sicurezza in cui viene eseguita la webapp. Il risultato dell'autenticazione è disponibile solo tramite request.getRemoteUser() e request.isUserInRole().

Questo riduce il framework JAAS a fini di autorizzazione a un semplice sistema utente/ruolo che perde la connessione con la politica Java Security .

+0

Grazie , ma non capisco come collegare l'autorizzazione Jaas con tomcat (uso di doas, ecc.) – sasaman85

+0

Normalmente si scriverebbe un modulo di login specifico del contenitore, che sfrutta JAAS o qualsiasi altra tecnologia si desideri e adempie al contratto del contenitore. Quando esegui l'accesso a livello di codice (HttpServletRequest # login) OPPURE accedi a una risorsa protetta, l'autenticazione verrà eseguita e il contenitore ne sarà a conoscenza. Tramite vincoli nelle risorse web.xml () come le pagine web sono protette. L'autorizzazione avviene confrontando i ruoli richiesti con i ruoli che l'utente autenticato ha. Se la partita, l'utente è autorizzato. –

+0

p.s. JAASRealm di Tomcat è un prototipo di JASPIC. Non ho esperienza con questo, ma suona come qualcosa che è un incrocio tra il profilo Servlet e il profilo Bridge. –

0

Per recuperare l'oggetto, è possibile utilizzare la combinazione di LoginModule e Valve. Il fatto che le valvole vengano invocate prima dell'attivazione dell'identificazione ci sta aiutando qui. Quando la valvola viene invocata mette la sessione in ThreadLocal (simile a come JBOSS salva la richiesta in ThreadLocal) e in seguito quando viene richiamato LoginModule.commit(), salva l'oggetto nella sessione.

Per configurare questo componente aggiuntivo codice compilato per la classe di seguito per un barattolo e posizionarlo sotto $ CATALINA_BASE/lib/

package my.test; 

import java.io.IOException; 
import java.util.Map; 

import javax.security.auth.Subject; 
import javax.security.auth.callback.CallbackHandler; 
import javax.security.auth.login.LoginException; 
import javax.security.auth.spi.LoginModule; 
import javax.servlet.ServletException; 

import org.apache.catalina.Session; 
import org.apache.catalina.connector.Request; 
import org.apache.catalina.connector.Response; 
import org.apache.catalina.valves.ValveBase; 

/** 
* Use following class to retrieve subject in your HTTPServlet when using Tomcat. 
*/ 
public class ContainerServices extends ValveBase implements LoginModule { 

    // Key to revtieve subject from session. 
    public static final String SUBJECT_KEY = 
     "javax.security.auth.Subject.container"; 

    /** 
    * Session for current thread. 
    */ 
    static InheritableThreadLocal<Session> sessionHolder = 
     new InheritableThreadLocal<Session>(); 

    // JAAS Subject being authenticated. 
    private Subject subject; 

    // Invoke the value. 
    public void invoke(Request request, Response response) throws IOException, 
      ServletException { 

     sessionHolder.set(request.getSessionInternal(true)); 

     try { 
      // Next in the invocation chain 
      getNext().invoke(request, response); 
     } finally { 
      sessionHolder.remove(); 
     } 
    } 

    // Initialize the login module 
    public void initialize(Subject subject, CallbackHandler callbackHandler, 
     Map<String, ?> sharedState, Map<String, ?> options) { 
     this.subject = subject; 
    } 

    // Store subject to session. 
    public boolean commit() throws LoginException { 

     Session session = sessionHolder.get(); 

     if (session != null) { 
      session.getSession().setAttribute(ContainerServices.SUBJECT_KEY, subject); 
     } 

     return true; 
    } 

    // not used 
    public boolean abort() throws LoginException { 
     return false; 
    } 

    // not used 
    public boolean login() throws LoginException { 
     return true; 
    } 

    // not used 
    public boolean logout() throws LoginException { 
     return true; 
    } 
} 

A $ CATALINA_BASE/conf/server.xml aggiungere seguente configurazione Valve come figlio dell'elemento.

<Valve className="my.test.ContainerServices" /> 

Nel file di jaas.config aggiungere la stessa classe di LoginModule.

DummyAppLogin { 
    my.test.ContainerServices required debug=true; 
    my.test.DummyAppLoginModule required debug=true; 
}; 

Ora, dopo aver effettuato il login, autenticato soggetto può essere recuperato utilizzando segue.

session.getAttribute(ContainerServices.SUBJECT_KEY);