我有一個應用程序,其中一些操作由MDB執行。這些MDB全部使用@RunAs(SYSTEM)
註釋將它們標記爲系統元素。如何在EJB/MDB調用期間更改用戶主體?
其中一個MDB的具有運行一些代碼,通過@RolesAllowed(WORKSPACE)
,其中SYSTEM
角色沒有,很明顯protecetd,但啓動進程的user
(一個人,請不要忘記)了。
所以,我的問題很簡單:是否有任何方法(通過異步調用,作爲示例)讓我的MDB將其主體更改爲我的user
而不是SYSTEM
?
我有一個應用程序,其中一些操作由MDB執行。這些MDB全部使用@RunAs(SYSTEM)
註釋將它們標記爲系統元素。如何在EJB/MDB調用期間更改用戶主體?
其中一個MDB的具有運行一些代碼,通過@RolesAllowed(WORKSPACE)
,其中SYSTEM
角色沒有,很明顯protecetd,但啓動進程的user
(一個人,請不要忘記)了。
所以,我的問題很簡單:是否有任何方法(通過異步調用,作爲示例)讓我的MDB將其主體更改爲我的user
而不是SYSTEM
?
像麥克布勞恩回答建議,這是不是可能根據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中爲我工作。
你能懇求爲這種方法提供一個例子嗎?我知道jax rs,但是如何通過servlet api登錄? – dermoritz
@dermoritz使用HttpServletRequest.authenticate()或HttpServletRequest.login() –