Как я могу изменить принципала пользователя во время вызова EJB/MDB?
У меня есть приложение, в котором некоторые операции выполняются MDB. Эти MDB все используют @RunAs(SYSTEM)
аннотация, чтобы пометить их как системные элементы.
Один из этих MDB должен запустить некоторый код, который защищен через @RolesAllowed(WORKSPACE)
, который SYSTEM
Роль не имеет, очевидно, но который user
(человек, заметьте), который начал процесс.
Итак, мой вопрос довольно прост: есть ли способ (например, с помощью асинхронного вызова), чтобы мой MDB изменил свой принципал на мой user
вместо SYSTEM
?
3 ответа
Как предполагает ответ Майка Брауна, это невозможно в соответствии со спецификациями 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...).
Я предполагаю, что SYSTEM - это роль, а под пользователем вы на самом деле имеете в виду пользователя, который отправляет, например, сообщение JMS, чтобы сказать очередь, которую прослушивает MDB?
Если вы хотите установить принципала с точными ролями в качестве этого пользователя (в основном, распространять контекст безопасности пользователя или выполнять вход в контейнер из MDB), то это, к сожалению, невозможно. Существует запрос на стандартизацию входа в контейнер в EJB (см. Спецификацию EJB JIRA), но это вам сейчас не поможет.
Обходным путем для этого может быть ресурс JAX-RS, который может использовать Servlet API для запуска входа в систему любого данного пользователя. Здесь вы должны быть осторожны, чтобы не создавать явную утечку безопасности (например, разрешив вход только по имени пользователя), но это вариант.
Если вам нужна только роль WORKSPACE, то не могли бы вы просто использовать второй @RunAs?
Посмотрите на: недавний вопрос здесь
Это более общий подход. Работаю в JBoss для меня.