如何在EJB / MDB调用期间更改用户主体?

时间:2012-10-17 13:54:17

标签: java-ee authentication ejb jaas

我有一个应用程序,其中一些操作由MDB执行。这些MDB都使用@RunAs(SYSTEM)注释将它们标记为系统元素。

其中一个MDB必须通过@RolesAllowed(WORKSPACE)运行一些代码,SYSTEM角色没有user角色,但是user(一个人,介意你开始这个过程。

所以,我的问题很简单:有没有办法(通过异步调用,作为一个例子)让我的MDB将其主体更改为我的SYSTEM而不是{{1}}?

3 个答案:

答案 0 :(得分:2)

我认为 SYSTEM 是一个角色,而对于用户,你真的是指发送例如JMS消息来说出MDB正在侦听的队列的用户? / p>

如果要设置具有该用户的确切角色的Principal(基本上传播用户的安全上下文或从MDB中进行容器登录),那么遗憾的是这是不可能的。有一个请求标准化EJB中的容器登录(请参阅EJB规范JIRA),但这对您现在没有帮助。

此解决方法可能是JAX-RS资源,它可以使用Servlet API触发任何给定用户的登录。你必须要小心,不要创建一个有缺陷的安全漏洞(例如,只允许通过用户名登录),但这是一个选项。

如果您只需要 WORKSPACE 这个角色,那么您不能简单地使用第二个@RunAs吗?

答案 1 :(得分:2)

就像Mike Braun的回答一样,根据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库中) ...)。

答案 2 :(得分:0)

看看: A recent question here

它是一种更通用的方法。在我的JBoss工作。