我有一个应用程序,其中一些操作由MDB执行。这些MDB都使用@RunAs(SYSTEM)
注释将它们标记为系统元素。
其中一个MDB必须通过@RolesAllowed(WORKSPACE)
运行一些代码,SYSTEM
角色没有user
角色,但是user
(一个人,介意你开始这个过程。
所以,我的问题很简单:有没有办法(通过异步调用,作为一个例子)让我的MDB将其主体更改为我的SYSTEM
而不是{{1}}?
答案 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)
它是一种更通用的方法。在我的JBoss工作。