Как я могу изменить принципала пользователя во время вызова EJB/MDB?

У меня есть приложение, в котором некоторые операции выполняются MDB. Все эти MDB используют аннотацию @RunAs(SYSTEM), чтобы пометить их как системные элементы.

Один из этих MDB должен запускать некоторый код, защищенный через @RolesAllowed(WORKSPACE), которого, очевидно, нет у роли SYSTEM, но который есть у user (заметьте, человека), запустившего процесс.

Итак, мой вопрос довольно прост: есть ли способ (например, с помощью асинхронного вызова), чтобы моя MDB изменила своего принципала на мой user вместо SYSTEM?


person Riduidel    schedule 17.10.2012    source источник


Ответы (3)


Я предполагаю, что SYSTEM — это роль, а под пользователем вы действительно имеете в виду пользователя, который отправляет, например, сообщение JMS, чтобы указать очередь, которую прослушивает MDB?

Если вы хотите установить принципала с точными ролями в качестве этого пользователя (в основном распространять контекст безопасности пользователя или выполнять вход в контейнер из MDB), то это, к сожалению, невозможно. Есть запрос на стандартизацию входа в контейнер в EJB (см. спецификацию EJB JIRA), но сейчас это вам не поможет.

Обходной путь для этого может быть ресурсом JAX-RS, который может использовать Servlet API для запуска входа в систему любого данного пользователя. Вы должны быть осторожны, чтобы не создать зияющую утечку безопасности (например, разрешив вход только по имени пользователя), но это вариант.

Если вам нужна только роль WORKSPACE, не можете ли вы просто использовать вторую @RunAs?

person Mike Braun    schedule 18.10.2012
comment
Можете ли вы привести пример для этого подхода? я знаю jax rs, но как войти в систему через API сервлета? - person dermoritz; 04.02.2016
comment
@dermoritz используйте HttpServletRequest.authenticate() или HttpServletRequest.login() - person Mike Braun; 26.03.2016

Как предполагает ответ Майка Брауна, это невозможно в соответствии со спецификациями JavaEE.

И это прискорбно. Но что немного менее печально, так это то, что есть некоторый код для выполнения таких вещей (специфический для сервера приложений), скрытый в этой реализации сервера приложений @RunAs. В Glassfish этот конкретный код находится в файле com.sun.enterprise.security.auth.login.LoginContextDriver и особенно в его методе LoginContextDriver#loginPrincipal.

Итак, чтобы одна часть кода использовала определенного принципала, я определил интерфейс

public interface Sudoer {
    public <Result> Result sudo(String user, SudoOperation<Result> operation);
}

который я реализовал для Glassfish так:

public class GlassfishSudoer implements Sudoer {
    @Override
    public <Result> Result sudo(String user, SudoOperation<Result> operation) {
        try {
            LoginContextDriver.loginPrincipal(user, "autocat");
            return operation.perform();
        } catch (Exception e) {
            throw new UnableToSudoException(e);
        } finally {
            LoginContextDriver.logout();
        }
    }
}

И при его использовании часть, которая хочет иметь некоторый код «sudoed», должна только предоставить реализацию SudoOperation, например

    component.sudo(userLogin, new SudoOperation<Void>() {
        public Void perform() {
            /* do some sudoed code */
            return null;
        }
    });

Преимущество этого метода заключается в том, что при условии, что данный сервер приложений имеет некоторый код для обработки @RunAs, вы можете использовать этот код для реализации своего собственного sudoer (я думаю о том, чтобы извлечь его в библиотеку sudo-ejb...).

person Riduidel    schedule 18.10.2012

Взгляните на: недавний вопрос здесь

Это более общий подход. Работа в JBoss для меня.

person roehrijn    schedule 09.11.2012