2012-10-17 12 views
3

我有一個應用程序,其中一些操作由MDB執行。這些MDB全部使用@RunAs(SYSTEM)註釋將它們標記爲系統元素。如何在EJB/MDB調用期間更改用戶主體?

其中一個MDB的具有運行一些代碼,通過@RolesAllowed(WORKSPACE),其中SYSTEM角色沒有,很明顯protecetd,但啓動進程的user(一個人,請不要忘記)了。

所以,我的問題很簡單:是否有任何方法(通過異步調用,作爲示例)讓我的MDB將其主體更改爲我的user而不是SYSTEM

回答

2

像麥克布勞恩回答建議,這是不是可能根據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

我認爲SYSTEM是一個角色,而與用戶你真的是誰派例如JMS消息說隊列中的MDB監聽的用戶?

如果您想要爲該用戶設置一個具有確切角色的主體(基本上傳播用戶的安全上下文或從MDB內部執行容器登錄),那麼很遺憾這是不可能的。有一個請求來標準化EJB中的容器登錄(請參閱EJB規範JIRA),但現在不會對您有所幫助。

解決方法可能是JAX-RS資源,它可以使用Servlet API觸發任何給定用戶的登錄。在這裏你必須小心不要造成漏洞(例如只允許用戶名登錄),但這是一個選項。

如果您只需要角色WORKSPACE,那麼您不能簡單地使用第二個@RunAs?

+0

你能懇求爲這種方法提供一個例子嗎?我知道jax rs,但是如何通過servlet api登錄? – dermoritz

+1

@dermoritz使用HttpServletRequest.authenticate()或HttpServletRequest.login() –

相關問題