認證

2012-01-31 82 views
4

後以編程方式添加角色,我有以下JSF 2.1的登錄表單,在Glassfish的3.1認證

<h:form id="loginForm"> 
     <h:panelGrid columns="2" cellspacing="5"> 
      <h:outputText value="Username" /> 
      <h:inputText value="#{loginHandler.username}" /> 
      <h:outputText value="Password:" /> 
      <h:inputText value="#{loginHandler.password}" /> 
      <h:outputLabel value="" /> 
      <h:commandButton value="Login" action="#{loginHandler.login}" /> 
     </h:panelGrid> 
    </h:form> 

運行而下面的支持bean。

public String login() throws IOException, LoginException { 

    log.debug("Trying to login with username " + username); 

    HttpSession session = getRequest().getSession(true); 

    try { 
     getRequest().login(username, password); 

     // if OK, add Roles 
        ???????? 
        ................... 

    } catch (ServletException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 


    log.debug("USER principal === " + getRequest().getUserPrincipal()); 

    return "home"; 
} 

問題是,如何在成功登錄後以編程方式向UserPrincipal添加角色?

更新1:我試圖通過使用下面的代碼,但主題== null來獲取主題。

Subject thisSubject = Subject.getSubject(AccessController 
       .getContext()); 

感謝, 科恩

+0

是否要硬編碼每個用戶的角色?如果你使用容器認證,角色應該來自認證領域。 – oers 2012-02-01 09:18:55

+0

嗨,我需要查詢另一個LDAP樹的某些角色,並將這些角色分配給用戶。角色在web.xml中定義。因此,身份驗證是容器管理的,但分配角色不是。 – 2012-02-01 09:31:13

回答

2

OK,我已經找到了一個解決辦法,這是我的觀點不是100%正確的,但建議,歡迎:)

public void login() throws IOException, LoginException { 

    log.debug("Trying to login with username " + username); 

    try { 
     getRequest().login(username, password); 

     HttpSession session = getRequest().getSession(true); 
     Subject subject = (Subject) session 
       .getAttribute("javax.security.auth.subject"); 

     if (subject == null) { 

      log.debug("Subject is null, creating new one"); 

      subject = new Subject(); 
      subject.getPrincipals().add(new PlainRolePrincipal("USER")); 
      subject.getPrincipals().add(new PlainRolePrincipal("ADMIN")); 

     } 

     log.debug("HAS USER " + getRequest().isUserInRole("USER")); 
     log.debug("HAS ADMIN " + getRequest().isUserInRole("ADMIN")); 
     log.debug("HAS REPORT " + getRequest().isUserInRole("REPORT")); 

     session.setAttribute("javax.security.auth.subject", subject); 

     log.debug("USER principal === " + getRequest().getUserPrincipal()); 

     FacesContext.getCurrentInstance().getExternalContext() 
       .redirect("pages/home.jsf"); 

    } catch (ServletException e) { 

     FacesContext.getCurrentInstance().addMessage("Login", 
       new FacesMessage("Invalid Username/Password combination")); 

     e.printStackTrace(); 
    } 

} 

而且我使用以下信息bean來檢索主題並檢查主體。

@ManagedBean(name = "userInfo") 
@SessionScoped 
public class UserInformation { 

/** 
* Fetches current logged in username. 
* 
* @return 
*/ 
public String getUsername() { 

    return FacesContext.getCurrentInstance().getExternalContext() 
      .getRemoteUser(); 

} 



public boolean isUserInRole(String roleName) { 
    Subject subject = (Subject) getRequest().getSession().getAttribute(
      "javax.security.auth.subject"); 

    for (Principal p : subject.getPrincipals()) { 
     if (p.getName().equals(roleName)) { 
      return true; 
     } 
    } 

    return false; 
} 


public static HttpServletRequest getRequest() { 
    Object request = FacesContext.getCurrentInstance().getExternalContext() 
      .getRequest(); 
    return request instanceof HttpServletRequest ? (HttpServletRequest) request 
      : null; 
} 

}

所以我的解決方法的isUserInRole機制,因爲身份驗證時,該角色被設定的真正的isUserInRole方法返回只在用戶真實。

從JSF頁面我現在可以做

<p:menuitem value="Create" action="#{menuController.XXXXXCreate}" 
       ajax="false" helpText="Create new XXXXX" 
       disabled="#{!userInfo.isUserInRole('ADMIN')}" /> 

希望這有助於其他用戶,任何改進建議,歡迎!

+0

你從哪裏找到屬性:「javax.security.auth.subject」?這是一個發佈的屬性,不太可能改變。我很好奇也使用它。 你是什麼意思:「所以我解決isUserInRole機制,」? – BillR 2012-09-10 02:22:21

5

我想出了以下解決方案登錄後以編程方式添加角色,其工作至少在GlassFish 3.1.2建立23

import com.sun.enterprise.security.SecurityContext; 
import com.sun.enterprise.security.web.integration.PrincipalGroupFactory; 
import java.security.Principal; 
import java.util.Set; 
import javax.security.auth.Subject; 
import org.glassfish.security.common.Group; 

public class GlassFishUtils { 
    public static void addGroupToCurrentUser(String groupName, String realmName) { 
     Subject subject = SecurityContext.getCurrent().getSubject(); 
     Set<Principal> principals = subject.getPrincipals(); 
     Group group = PrincipalGroupFactory.getGroupInstance(groupName, realmName); 
     if (!principals.contains(group)) 
      principals.add(group); 
    } 
} 

您需要添加從GlassFish的security.jarcommon-util.jar到項目庫。

並且不要忘記在web.xml中爲您想添加的角色創建一個<security-role>部分。

請注意,我使用的功能似乎不是已發佈的穩定API的一部分,因此無法保證在未來的GlassFish版本中這些功能仍能正常工作。

我收到了關於如何從GlassFish的sun.appserv.security.AppservPasswordLoginModule.commit()的源代碼添加角色的信息。 如果將來的GlassFish發佈會破壞我的代碼,那麼此函數將是一個很好的開始以瞭解如何修復它的地方。

+0

「真名」是指什麼?成爲主體的登錄名?就像在JSF中一樣,你做了一個:FacesContext.getCurrentInstance()。getExternalContext()。getUserPrincipal();是嗎?沒有? – BillR 2012-09-10 02:28:50

+0

這不是「真正的」,而是「領域」,就像在JAAS身份驗證領域一樣。有關領域的更多信息,請參閱http://docs.oracle.com/cd/E19798-01/821-1841/bnbxj/index.html。 realmName參數是標識領域的字符串,如在GlassFish中配置的。 – SvdB 2012-09-11 10:55:03

+0

< BIG grin&gt。那麼我需要新的眼鏡。大聲笑。是的,我知道realM的名字。我已經定製了JDBC領域來做更多我需要做的事情,並繞過他們期望桌子被設置的愚蠢的方式(以及允許處理鹽漬密碼等)。:)感謝您的答案。至少這看起來值得一試。謝謝。 – BillR 2012-09-11 16:23:09