2012-10-25 2 views
5

Я изучаю JAAS, и я реализую простой пример использования в webapp, используя Tomcat с JaasRealm.Tomcat-Jaas - Как получить предмет?

Теперь моя проблема в том, что я не знаю, как получить объект, так как код Subject subject = Subject.getSubject(AccessController.getContext()); всегда возвращает null.

Я использую Tomcat 7.0.27. Есть что-то, что я пропустил? Другими словами, как я могу управлять авторизацией в Java EE с помощью JAAS? Например, как я могу реализовать действие в безопасном контексте JAAS?

+0

Убедитесь, что ваша область используется для веб-приложение, то вы можете попробовать Servlets API, 'HttpServletRequest.getUserPrincipal()' –

+0

Я знал, что и она работает, но мне нужно, чтобы получить предмет, чтобы получить также roleprincipal – sasaman85

ответ

8

я знал, что и она работает, но мне нужно, чтобы получить предмет, чтобы получить также roleprincipal

К сожалению, это не работает, как, что в Java EE. Предмет JAAS - это всего лишь «сумка принципов», а какая из них представляет собой принципал пользователя/вызывающего абонента и/или принципала (-ов) роли просто не стандартизирована. Здесь каждый другой контейнер делает все по-другому. Javadoc for Tomcat's JAASRealm описывает это и объясняет Tomcat конкретной конвенции (курсив мой):

Спецификация JAAS описывает результат успешной регистрации в качестве экземпляра javax.security.auth.Subject, которая может содержать ноль или более java.security.Principal objects в возвращаемом значении метода Subject.getPrincipals(). Однако она не дает никаких указаний на как отличить принципалов, которые описывают конкретного пользователя (и , таким образом, целесообразно возвращать в качестве значения request.getUserPrincipal() в веб-приложения) от Принципала (ов) что описать авторизованные роли для этого пользователя. Для того, чтобы сохранить как можно больше независимости как можно дальше от лежащего в основе LoginMethod реализации выполняемой JAAS, следующая политика реализуется этим Realm: [...]

Кроме того, из среды Java EE редко даже имеют доступ к теме JAAS, часто даже не с помощью специальных методов поставщика. JAAS далек от универсального стандарта, который, как вам кажется, кажется, особенно, когда речь идет о Java EE.

Единственное, с чем вы можете получить доступ в переносном режиме, - это руководитель звонящего и связанные с ним роли, но даже те, которые не должны быть точными принципами звонящего, которые вы создали в модуле входа в JAAS.

JBoss AS, например, несколько раз копирует этот принцип, используя свои собственные классы. Итак, если ваш модуль JAAS сохранил kaz.zak.FooPrincipal в теме для принципала пользователя/вызывающего абонента, то HttpServletRequest#getUserPrincipal() может вернуть org.jboss.security.SimplePrincipal. Единственное, что гарантировано, это то, что getName() на этом экземпляре вернет ту же строку.

Для некоторых более фона на эту тему:

Последний источник в основном говорит то же самое, в разных формулировках;

Несмотря на то, что можно использовать JAAS в пределах Tomcat в качестве аутентификации механизма (JAASRealm), гибкость рамках JAAS теряется после того, как пользователь аутентифицирован. Это связано с тем, что принципы - это , которые используются для обозначения понятий «пользователь» и «роль» и больше не являются , доступными в контексте безопасности, в котором выполняется webapp. Результат аутентификации можно получить только через request.getRemoteUser() и request.isUserInRole().

Это уменьшает структуру JAAS для авторизации до простой пользовательской/ролевой системы , которая теряет свое соединение с политикой безопасности Java .

+0

Спасибо , но я не понимаю, как подключить авторизацию Jaas с tomcat (использование doas и т. д.). – sasaman85

+0

Обычно вы должны написать специальный модуль входа в контейнер, который использует JAAS или какой-либо другой метод, который вы хотите, и выполняет контракт с контейнером. Когда вы программно входите в систему (HttpServletRequest # login) ИЛИ обращаетесь к защищенному ресурсу, аутентификация будет выполнена, и контейнер будет знать об этом. Через ограничения в web.xml () ресурсы, такие как веб-страницы, защищены. Авторизация происходит путем сравнения запрошенных ролей с ролями, которые имеет аутентифицированный пользователь. Если совпадение, пользователь авторизован. –

+0

p.s. JAASRealm от Tomcat является прототипом JASPIC. У меня нет опыта с этим, но это звучит как нечто, что является перекрестком между профилем сервлета и мостом. –

0

Для извлечения темы мы можем использовать комбинацию LoginModule и Valve. Тот факт, что клапаны вызываются до того, как аутентификация ударит, помогает нам здесь. Когда вызывается клапан, он помещает сеанс в ThreadLocal (подобно тому, как JBOSS сохраняет запрос в ThreadLocal), а позже, когда вызывается LoginModule.commit(), он сохраняет объект в сеансе.

Чтобы настроить эту добавить скомпилированный код класса ниже банку и поместите его под $ 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; 
    } 
} 

В $ CATALINA_BASE/конф/server.xml добавить следующие конфигурации клапана в качестве ребенка элемента.

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

В jaas.config файле добавить один и тот же класс, как LoginModule.

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

Теперь после входа в систему, проверку подлинности Объект можно получить с помощью следующее.

session.getAttribute(ContainerServices.SUBJECT_KEY);