2012-10-25 14 views
5

Studiuję JAAS i wdrażam prosty przykład do użycia w webappie używając Tomcat z JaasRealm.Tomcat-Jaas - Jak odzyskać temat?

Teraz mój problem polega na tym, że nie wiem, jak odzyskać temat, ponieważ kod taki jak Subject subject = Subject.getSubject(AccessController.getContext()); zawsze zwraca wartość null.

Używam Tomcat 7.0.27. Czy jest coś, co przeoczyłem? Innymi słowy, w jaki sposób mogę zarządzać autoryzacją w Java EE z JAAS? Na przykład jak mogę wdrożyć działanie w bezpiecznym kontekście JAAS?

+0

Bądź pewny, że Twoje królestwo jest używany dla webapp, to można spróbować Servlety API 'HttpServletRequest.getUserPrincipal()' –

+0

i wiedziałem, że to działa, ale muszę odzyskać podlegają również uzyskać roleprincipal – sasaman85

Odpowiedz

8

Wiedziałem, że i to działa, ale muszę odzyskać podlegają również uzyskać roleprincipal

Niestety, to nie działa w ten sposób w Java EE. Przedmiot JAAS jest po prostu "workiem zleceniodawców", a który z nich reprezentuje użytkownika/dzwoniącego zleceniodawcę i/lub główny podmiot (role) po prostu nie jest znormalizowany. Każdy inny pojemnik robi tutaj różne rzeczy. Javadoc for Tomcat's JAASRealm ten opisuje i wyjaśnia Tomcat specyficzną konwencję (kopalnia nacisk):

JAA Specyfikacja opisuje wynik udanego logowania jako przykład javax.security.auth.Subject, która może zawierać zero lub więcej java.security.Przykładowe obiekty w wartości zwracanej metody Subject.getPrincipals(). Jednak dostarcza żadnych wskazówek na Jak odróżnić podmiotów, które opisują indywidualnego użytkownika (i są zatem właściwe, aby powrócić jako wartość request.getUserPrincipal() w aplikacji internetowej) ze Zleceniodawcą (ów) że opisać autoryzowane role dla tego użytkownika. Aby zachować jak najwięcej jak to możliwe niezależność od leżącej LoginMethod realizacji zawartej przez JAAS, następujące zasady są realizowane przez ten Realm: [...]

Poza tym, ze środowiska Java EE rzadko nawet mieć dostęp do tematu JAAS, często nawet za pomocą metod określonych przez sprzedawcę. JAAS jest daleki od uniwersalnego standardu, który wydaje się, że tak jest, szczególnie gdy dotyczy Java EE.

Jedyne rzeczy, do których można uzyskać dostęp w sposób przenośny, to osoba dzwoniąca i związane z nią role, ale nawet te nie muszą być dokładnymi osobami dzwoniącymi, które zbudował moduł logowania JAAS.

JBoss AS na przykład kilka razy kopiuje tę instrukcję, używając własnych klas. Jeśli więc moduł JAAS zapisał numer kaz.zak.FooPrincipal w temacie dla użytkownika/osoby dzwoniącej, wówczas HttpServletRequest#getUserPrincipal() może zwrócić wartość org.jboss.security.SimplePrincipal. Gwarantujemy tylko, że getName() na tej instancji zwróci ten sam ciąg.

jakiegoś tła więcej na ten temat:

Ostatnim źródłem zasadzie mówi to samo, w innym brzmieniu;

Chociaż jest możliwe zastosowanie JAAS ciągu Tomcatem jako uwierzytelnienie mechanizm (JAASRealm), elastyczność ram JAAS traci gdy użytkownik jest uwierzytelniany. Wynika to z tego, że podmioty główne to używane do oznaczania pojęć "użytkownik" i "rola" i nie są już dostępne w kontekście zabezpieczeń, w którym wykonywana jest aplikacja webapp. Wynik uwierzytelnienia jest dostępny tylko za pośrednictwem request.getRemoteUser() i request.isUserInRole().

Spowoduje to zmniejszenie struktury JAAS do celów autoryzacji do prostego użytkownika/systemu roli , który traci połączenie z polityką Java Security .

+0

Thanks , ale nie rozumiem, jak połączyć autoryzację Jaas z tomcat (korzystanie z doas itp.). – sasaman85

+0

Zwykle napiszesz moduł logowania do kontenera, który wykorzystuje JAAS lub inną technologię, którą chcesz i spełnia kontrakt kontenera. Kiedy programujesz się logicznie (HttpServletRequest # login) LUB uzyskujesz dostęp do chronionego zasobu, uwierzytelnianie zostanie wykonane, a kontener będzie tego świadomy. Poprzez ograniczenia w web.xml () zasoby takie jak strony internetowe są zabezpieczone. Autoryzacja następuje przez porównanie żądanych ról z rolami, które ma uwierzytelniony użytkownik. Jeśli mecz, użytkownik jest uprawniony. –

+0

p.s. JAASRealm Tomcat jest prototypem JASPIC. Nie mam z tym doświadczenia, ale to brzmi jak coś, co jest skrzyżowaniem profilu Servlet Profile i Bridge. –

0

Do obiektu można użyć kombinacji modułu logowania i zaworu. Fakt, że zawory są wywoływane przed uruchomieniem uwierzytelniania, pomaga nam tutaj. Po wywołaniu zaworu umieszcza sesję w ThreadLocal (podobnie jak JBOSS zapisuje żądanie w ThreadLocal), a później, gdy wywoływana jest funkcja LoginModule.commit(), zapisuje temat w sesji.

Aby skonfigurować ten dodatek kod skompilowany dla klasy niżej do słoika i umieścić go pod $ 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; 
    } 
} 

w $ CATALINA_BASE/conf/server.xml dodać następującej konfiguracji zaworów jako dziecko elementu.

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

W pliku jaas.config dodać tę samą klasę jako LoginModule.

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

Teraz po zalogowaniu, uwierzytelniony Temat można pobrać przy użyciu następujących.

session.getAttribute(ContainerServices.SUBJECT_KEY);