Jakarta ee 如何在EJB/MDB调用期间更改用户主体?
我有一个应用程序,其中一些操作由MDB执行。这些MDB都使用Jakarta ee 如何在EJB/MDB调用期间更改用户主体?,jakarta-ee,authentication,ejb,jaas,Jakarta Ee,Authentication,Ejb,Jaas,我有一个应用程序,其中一些操作由MDB执行。这些MDB都使用@RunAs(SYSTEM)注释将它们标记为系统元素 其中一个MDB必须运行一些通过@RolesAllowed(WORKSPACE)保护的代码,系统角色显然没有这些代码,但启动该过程的用户(请注意,是人)有这些代码 所以,我的问题很简单:有没有办法(例如通过异步调用)让我的MDB将其主体更改为我的用户而不是系统?我假设系统是一个角色,而对于user,您真的是指发送JMS消息来表示MDB正在侦听的队列的用户吗 如果您想将主体设置为该用户的
@RunAs(SYSTEM)
注释将它们标记为系统元素
其中一个MDB必须运行一些通过@RolesAllowed(WORKSPACE)
保护的代码,系统角色显然没有这些代码,但启动该过程的用户(请注意,是人)有这些代码
所以,我的问题很简单:有没有办法(例如通过异步调用)让我的MDB将其主体更改为我的用户而不是系统?我假设系统是一个角色,而对于user,您真的是指发送JMS消息来表示MDB正在侦听的队列的用户吗
如果您想将主体设置为该用户的确切角色(基本上传播用户的安全上下文或从MDB中进行容器登录),那么很遗憾,这是不可能的。有一个在EJB中标准化容器登录的请求(请参阅EJB规范JIRA),但现在这对您没有帮助
解决方法可以是JAX-RS资源,它可以使用ServletAPI触发任何给定用户的登录。在这里您必须小心,不要创建一个巨大的安全漏洞(例如只允许通过用户名登录),但这是一个选项
如果您只需要角色工作区,那么您不能简单地使用第二个@RunAs吗?就像Mike Braun的回答所建议的那样,根据JavaEE规范,这是不可能的
这是不幸的。但是,有一点不那么不幸的是,在@RunAs
的应用服务器实现中隐藏了一些代码来完成这类事情(特定于应用服务器)。在Glassfish中,该特定代码在类中,尤其是在其LoginContextDriver#loginPrincipal
方法中
因此,为了让代码的一部分使用特定的主体,我定义了一个接口
public interface Sudoer {
public <Result> Result sudo(String user, SudoOperation<Result> operation);
}
公共接口Sudoer{
公共结果sudo(字符串用户,SudoOperation操作);
}
我为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();
}
}
}
公共类GlassfishSudoer实现Sudoer{
@凌驾
公共结果sudo(字符串用户,SudoOperation操作){
试一试{
LoginContextDriver.loginPrincipal(用户,“autocat”);
返回操作。perform();
}捕获(例外e){
抛出新的UnableToSudoException(e);
}最后{
LoginContextDriver.logout();
}
}
}
当使用它时,想要有一些代码“sudoed”的部分只需要提供SudoOperation的实现,比如
component.sudo(userLogin, new SudoOperation<Void>() {
public Void perform() {
/* do some sudoed code */
return null;
}
});
component.sudo(用户登录,新的SudoOperation(){
公开执行{
/*做一些无用的代码*/
返回null;
}
});
这种方法的优点是,如果给定的应用程序服务器有一些代码来处理@RunAs
,您可以使用这些代码来实现自己的sudoer(我正在考虑将其提取到sudo ejb库中…。请看一下:
这是一种更通用的方法。为我在JBoss工作。你能提供一个这种方法的例子吗?我知道jax rs,但如何通过servlet api登录?@dermoritz使用HttpServletRequest.authenticate()或HttpServletRequest.login()