2012-10-25 16 views
5

Ich studiere JAAS und ich implementiere ein einfaches Beispiel für die Verwendung in einer Webapp mit Tomcat mit einem JaasRealm.Tomcat-Jaas - Wie finde ich das Thema?

Jetzt ist mein Problem, dass ich nicht weiß, wie Sie das Thema abrufen, da Code wie Subject subject = Subject.getSubject(AccessController.getContext()); immer Null zurückgibt.

Ich benutze Tomcat 7.0.27. Gibt es etwas, das ich vermisst habe? In anderen Worten, wie kann ich Autorisierung in Java EE mit JAAS verwalten? Wie kann ich zum Beispiel eine Aktion im sicheren Kontext von JAAS implementieren?

+0

Seien Sie sicher, dass Ihr Reich für Ihre Webapp verwendet wird, dann können Sie versuchen, Servlets API 'HttpServletRequest.getUserPrincipal()' –

+0

ich das wusste und es funktioniert, aber ich brauche Thema abzurufen auch bekommen Roleprincipal – sasaman85

Antwort

8

wusste ich, dass es funktioniert, aber ich brauche auch so funktioniert es Roleprincipal

Leider nicht in Java EE, erhalten unter abgerufen werden. Der JAAS Subject ist nur ein "Sack von Principals", und welcher von diesen repräsentiert den Benutzer/Anrufer Principal und/oder die Rolle Principal (s) ist einfach nicht standardisiert. Jeder andere Container macht die Dinge hier anders. Die Javadoc for Tomcat's JAASRealm beschreibt diese und erklärt die Tomcat spezifische Konvention (Hervorhebung von mir):

Die JAAS-Spezifikation beschreibt das Ergebnis einer erfolgreichen Anmeldung als javax.security.auth.Subject Instanz, die null oder mehr enthalten java.security.Principal-Objekte im Rückgabewert der Subject.getPrincipals() -Methode. Allerdings sieht es keine Anleitung auf wie Principals zu unterscheiden, die die einzelnen Benutzer beschreiben (und sind daher angemessen, als der Wert des request.getUserPrincipal() in einer Web-Anwendung zurückzukehren) vom Auftraggeber (n) dass Beschreiben Sie die autorisierten Rollen für diesen Benutzer. Um so viel Unabhängigkeit wie möglich von der zugrunde liegenden LoginMethod Implementierung zu halten von JAAS ausgeführt wird, wird die folgende Politik dieses Realm umgesetzt: [...]

Abgesehen davon, von einem Java EE-Umgebung Sie selten sogar Zugriff auf den JAAS-Betreff, oft nicht einmal über herstellerspezifische Methoden. JAAS ist weit entfernt von dem universellen Standard, von dem Sie glauben, dass er es ist, besonders wenn es um Java EE geht.

Die einzigen Dinge, auf die Sie auf portable Weise zugreifen können, sind der Anrufer-Principal und die damit verbundenen Rollen, aber auch diese müssen nicht der genaue Anrufer sein, den Ihr JAAS Login-Modul erstellt hat.

JBoss AS zum Beispiel kopiert diesen Principal einige Male mit seinen eigenen Klassen. Wenn also Ihr JAAS-Modul einen kaz.zak.FooPrincipal im Betreff für den Benutzer/Anrufer-Principal gespeichert hat, kann HttpServletRequest#getUserPrincipal() einen org.jboss.security.SimplePrincipal zurückgeben. Das einzige, was garantiert ist, ist, dass getName() für diese Instanz die gleiche Zeichenfolge zurückgibt.

Für etwas mehr Hintergrund zu diesem Thema:

Die letzte Quelle sagt, im Grunde das Gleiche, in anderer Formulierung;

Obwohl es möglich ist, innerhalb von JAAS Tomcat als Authentifizierungs Mechanismus (JAASRealm) zu verwenden, die Flexibilität des JAAS Rahmen verloren geht Sobald der Benutzer authentifiziert ist. Dies liegt daran, dass die Principals verwendet werden, um die Konzepte von "Benutzer" und "Rolle" zu bezeichnen, und nicht mehr im Sicherheitskontext verfügbar sind, in dem die Webanwendung ausgeführt wird. Das Ergebnis der Authentifizierung ist nur über request.getRemoteUser() und request.isUserInRole() verfügbar.

Dadurch wird das JAAS-Framework für Autorisierungszwecke auf ein einfaches Benutzer-/Rollensystem reduziert, das die Verbindung mit der Java-Sicherheitsrichtlinie verliert.

+0

Dank , aber ich verstehe nicht, wie man die Jaas-Autorisierung mit Tomcat verbindet (Verwendung von Doas usw.) – sasaman85

+0

Normalerweise würde man ein containerspezifisches Login-Modul schreiben, das JAAS oder was auch immer Tech nutzt und den Containervertrag erfüllt. Wenn Sie sich programmtechnisch anmelden (HttpServletRequest # login) ODER auf eine geschützte Ressource zugreifen, wird die Authentifizierung durchgeführt und der Container wird sich dessen bewusst sein. Über Einschränkungen in web.xml () werden Ressourcen wie Webseiten gesichert. Die Autorisierung erfolgt durch den Vergleich der angeforderten Rollen mit den Rollen, die der authentifizierte Benutzer besitzt. Wenn die Übereinstimmung besteht, ist der Benutzer berechtigt. –

+0

p.s. Tomcat's JAASRealm ist ein Prototyp von JASPIC. Ich habe keine Erfahrung damit, aber es klingt wie etwas, das eine Kreuzung zwischen dem Servlet-Profil und dem Bridge-Profil ist. –

0

Um Betreff abrufen können wir die Kombination von LoginModule und Valve verwenden. Die Tatsache, dass Ventile aufgerufen werden, bevor die Authentifizierung einsetzt, hilft uns hier. Wenn das Ventil aufgerufen wird, verschiebt es die Sitzung in ThreadLocal (ähnlich wie JBOSS die Anforderung in ThreadLocal speichert) und später, wenn LoginModule.commit() aufgerufen wird, speichert es den Betreff in der Sitzung.

dieses Add kompilierten Code für die Klasse zu konfigurieren, unten an einem Glas und legen Sie es unter $ 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; 
    } 
} 

In $ CATALINA_BASE/conf/server.xml des Kindes folgende Ventilkonfiguration als Element hinzufügen.

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

In jaas.config Datei die gleiche Klasse wie Loginmodule hinzufügen.

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

Jetzt, nachdem Sie sich anmelden, können authentifizierte Subject mit folgenden abgerufen werden.

session.getAttribute(ContainerServices.SUBJECT_KEY); 
Verwandte Themen