从FacesContext获取LDAContext的最简单方法是什么



我从JSF页面调用了一个Java doLogin()方法,该方法从用户那里获取id(String netId)和密码(String password)。doLogin()在Active Directory登录中使用netId作为主体来启动身份验证。之后,我想从保护我的应用程序的目录中获得除主体名称之外的其他属性。

我的安全配置在容器&它起作用,这样

HttpSession ses = FacesContext.getCurrentInstance().getExternalContext().getSession (false);
HttpServletRequest req = FacesContext.getCurrentInstance().getExternalContext().getRequest();
req.login(netID, password);

成功并且

req.getUserPrincipal().getName();

返回用户的CCD_ 6。但是,我的应用程序仅将netId用于身份验证。访问另一个数据库的应用程序的其他部分需要其他属性(例如commonName)。我想做一些类似的事情

usefulLDAPobj = *getLDAPSession from "somewhere" in the HTTP Session, the FacesContext or some other available object*
String cn = usefulLDAPobj.getAttributeFromProfile ("cn");
ses.setAttribute("username", cn);

从那时起,在我的Hibernate ORM中使用存储在会话中的username。

我知道头脑简单的usefulLDAPobj.getAttributeFromProfile ("cn")会更复杂,但如果我能找到一个可以访问LDAP目录的起点,我就可以填写它。

由于容器正在建立一个明显的LDAP连接,我觉得必须有一种方法让我使用它,而不必手动用程序建立LdapContext;这将需要代码知道web服务器(JBoss EAP 6.2)已经知道的所有LDAP server / bind-DN / bind-password configuration(从CCD_ 12中定义的CCD_。例如,像getUserPrincipal()isUserInRole()这样的方法需要访问我想要访问的目录配置文件

所以我的问题是:有没有一种方法可以从FacesContext或HTTPServlet请求或HTTPServlet可访问的任何对象中获取LDAP连接或上下文?

从FacesConext获取LdapConext的最简单方法是什么?

根本没有办法,更不用说简单的办法了。JSF不假定存在LDAP服务器,也不提供任何与LDAP相关的API。

由于容器正在建立一个明显的LDAP连接

当你登录时。不是永久性的。如果有LDAP服务器的话。JSF不知道容器是如何让你登录的

我觉得一定有办法。。。

没有。

我认为这个问题的一个有用答案是没有办法直接从FacesContext获得LDAPContext,但通过编写容器特定的登录模块和Principal类,您可以通过FacesContext获得的HttpServletRequest传递额外的数据

我将把我的解决方案的详细信息放在这里,因为尽管它与FacesContext没有直接关系,但它提供了我在问题正文中所要求的内容,这是一种从LDAP配置文件中获取额外用户数据的方法,同时避免了创建一个完全独立的LDAPContext的需要。

我特别想要的是CN,我可以在不进行额外搜索的情况下从DN中解析它。如果我需要任何其他数据,我假设我可以使用下面的findUserDN()中的ctx来获得。

我想我用这个解决方案让我的应用程序依赖于JBoss,如果这是不可取的,我会搜索一个独立于JBoss的登录模块类来扩展(不知道这是容易的、困难的还是不可能的)。

这是我的解决方案:

  1. 覆盖AdvancedADLoginModule 中的findUserDN(LdapContext ctx)

    package ca.mycompany.myapp.jboss;
    import java.security.Principal;
    import javax.naming.ldap.LdapContext;
    import javax.security.auth.login.LoginException;
    import org.jboss.security.negotiation.AdvancedADLoginModule;
    public class NameFetchingADLoginModule extends AdvancedADLoginModule
        @Override
        protected String findUserDN(LdapContext ctx) throws LoginException
        {
            String lclUserDN = super.findUserDN(ctx);
            Principal principal = getIdentity();
            if (principal instanceof PrincipalWithDisplayName)
            {
                String displayName = lclUserDN.substring(3, lclUserDN.indexOf(','));
                ((PrincipalWithDisplayName) principal).setDisplayName (displayName);
            }
            return lclUserDN;
        }
    }
    
  2. 扩展Principal以提供displayName属性

    package ca.mycompany.myapp.jboss;
    import java.io.Serializable;
    import java.security.Principal;
    public class PrincipalWithDisplayName implements Serializable, Principal
    {
        private static final long serialVersionUID = 1L;
        private final String name;
        // additional attribute provided by this subclass
        private String displayName;
        public PrincipalWithDisplayName(final String name) {
            this.name = name;
        }
        // new and overriding getters and setters, equals() and hashCode() removed for brevity
    }
    
  3. 在doLogin()方法中使用新的登录模块和Principal

代码段:

    String displayName = "";
    HttpSession ses = FacesContext.getCurrentInstance().getExternalContext().getSession (false);
    HttpServletRequest req = FacesContext.getCurrentInstance().getExternalContext().getRequest();
    try {           
        req.login(userName, password); // this throws an exception if authentication fails
        Principal lclUser = req.getUserPrincipal();
        if (lclUser instanceof PrincipalWithDisplayName)
        {
            displayName = ((PrincipalWithDisplayName) lclUser).getDisplayName ();
        }
        // get Http Session and store username
        //
        HttpSession session = HttpUtil.getSession();
        sess.setAttribute("username", displayName);
        ...
  1. standalone.xml中配置JBoss EAP 6.2以使用新类

代码段:

<subsystem xmlns="urn:jboss:domain:security:1.2">
    <security-domains>
        <security-domain name="company_ad" cache-type="default">
            <authentication>
                <login-module code="ca.mycompany.myapp.jboss.NameFetchingADLoginModule" flag="required">
                    <module-option name="java.naming.factory.initial" value="com.sun.jndi.ldap.LdapCtxFactory"/>
                    <module-option name="java.naming.provider.url" value="ldap://servernm.mycompany.tst:389"/>
                    <module-option name="java.naming.security.authentication" value="simple"/>
                    <module-option name="bindDN" value="CN=AuthGuy,OU=Accounts,OU=Company User Accounts,DC=company,DC=tst"/>
                    <module-option name="bindCredential" value="Snowden1"/>
                    <module-option name="baseCtxDN" value="OU=Company User Accounts,DC=company,DC=tst"/>
                    <module-option name="baseFilter" value="(sAMnetID={0})"/>
                    <module-option name="searchScope" value="SUBTREE_SCOPE"/>
                    <module-option name="allowEmptyPassword" value="false"/>
                    <module-option name="rolesCtxDN" value="OU=Company User Accounts,DC=company,DC=tst"/>
                    <module-option name="roleFilter" value="(sAMAccountName={0})"/>
                    <module-option name="roleAttributeID" value="memberOf"/>
                    <module-option name="roleAttributeIsDN" value="true"/>
                    <module-option name="roleNameAttributeID" value="cn"/>
                    <module-option name="recurseRoles" value="1"/>
                    <module-option name="principalClass" value="ca.mycompany.myapp.jboss.PrincipalWithDisplayName"/>
                </login-module>
            </authentication>
        </security-domain>
    </security-domains>
</subsystem>

相关内容

  • 没有找到相关文章

最新更新