理解 LDAP 组成员资格搜索(静态与动态)

简介
阅读本文档的前提是已理解 BEA 支持模式“LDAP 问题”的内容。
此模式的适用对象是希望在动态组机制及静态组机制下使用 LDAP 服务器的客户。
 
它还详细介绍了如何更好地阅读和解释调试信息。我们希望在您阅读完本文档后,能够以对贵组织最优化的方式正确配置自己的 Authentication Provider。

以下所有测试均是使用 Sun LDAP Directory 5.1 执行的。这些信息适用于任何 LDAP 服务器。LDAP 动态组可以在安装有 WebLogic 的任何支持 LDAP 的服务器上运行。

快速链接
通过示例理解
我们将在开始阐述正题前提供一个有关 LDAP 服务器内对象的示例,可以通过它加深对 WebLogic 的组成员资格处理方式的理解。

您将在本示例中看到的日志输出是在将下列属性设置为 true 的情况下获得的:
<ServerDebug
    DebugSecurityAdjudicator="true”    // for security adjucator debug
    DebugSecurityAtn="true"       // for security authentication debug
    DebugSecurityAtz="true"        // for security authorization debug
    DebugSecurityRoleMap="true”      // for security role mapping debug
Name="MyServer"/>


在命令行中使用系统属性设置启用了调试到 stdout
   -Dweblogic.StdoutDebugEnabled=true

已有组 BEA 并具有下列属性(LDIF 格式):
cn=BEA,ou=Groups, dc=emea,dc=bea,dc=comversion: 1
dn: cn=BEA,ou=Groups, dc=emea,dc=bea,dc=com
cn: BEA
objectClass: top
objectClass: groupofuniquenames
objectClass: groupofurls
uniqueMember: uid=user0,ou=People, dc=emea,dc=bea,dc=com
memberURL: ldap:///dc=emea,dc=bea,dc=com??sub?(&(|(objectclass=person)
(objectclass=groupofuniquenames))(mail=*user2*))

有 3 个用户,它们都是组 BEA 的成员(User0、User1 和 User2)。

User0 – 这是组 BEA 在其 uniqueMember 属性(LDIF 格式)中静态引用的用户:
version: 1
dn: uid=user0,ou=People, dc=emea,dc=bea,dc=com
givenName: User0
sn: user0
cn: User0 user0
uid: user0
userPassword: {SSHA}57izD60l7oPbZOBy6poSMw5icVhJPPpvID2LSg==
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetorgperson

User1 –此用户的属性 postalAddress(LDIF 格式)中包含它所属组的完整 DN
(不能在生产阶段将该属性用于此类功能 – 请使用 LDAP 管理员建议使用的属性 - 该属性仅用作示例):
version: 1
dn: uid=user1,ou=People, dc=emea,dc=bea,dc=com
givenName: user1
sn: user1
cn: user1 user1
uid: user1
userPassword: {SSHA}KmMaOD3tb4ln4DCiW6BwDjTew+w8KUMLHllCaQ==
postalAddress: cn=BEA,ou=Groups, dc=emea,dc=bea,dc=com
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetorgperson

User2 – 此用户是运行在组 BEA 的 memberURL 中定义的查询的结果,是组成员
version: 1
dn: uid=user2,ou=People, dc=emea,dc=bea,dc=com
uid: user2
givenName: user2
sn: user2
cn: user2 user2
userPassword: {SSHA}C9S9d15zgBOIMx1hmD4cjONGWB0EXk9GwxT1Ug==
mail: user2@bea.com
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetorgperson

memberURL 中的 LDAP 查询的内容是“查找 mail=*user2* 的所有用户”:ldap:///dc=emea,dc=bea,dc=com??sub?(&(|(objectclass=person)
(objectclass=groupofuniquenames))(mail=*user2*))


LDAP 查询的功能可以非常强大。其优点在于可以确保不以静态方式指定某个用户为组成员。例如,如果以 gender =“Male”查询所有用户(在此情况下,需要假设有 gender 这一属性),就可以动态方式声明您是组“Male”的成员。
此时该查询的内容将与此相似:
ldap:///dc=emea,dc=bea,dc=com??sub?(&(|(objectclass=person)
(objectclass=groupofuniquenames))(gender=Male))


可以复制该查询的结果 - ldap:///dc=emea,dc=bea,dc=com??sub?(&(|(objectclass=person)
(objectclass=groupofuniquenames))(mail=*user2*))
-
并将其粘贴到 Internet Explorer 浏览器中(在 url 中指定 LDAP 主机 + 端口),随后会显示:

LDAP 抓屏

这意味着 user2 是查询的结果。

返回页首

使用的 Provider 配置

以下这段摘录取自 config.xml 文件:

<weblogic.security.providers.authentication.IPlanetAuthenticator
    ControlFlag="OPTIONAL"
    Credential="<my credentials>"
    DynamicGroupNameAttribute="cn"
    DynamicGroupObjectClass="groupofURLs"
    DynamicMemberURLAttribute="memberURL"
    GroupBaseDN="ou=groups, dc=emea,dc=bea,dc=com"
    GroupFromNameFilter="(|(&amp;(cn=%g)(objectclass=groupofUniqueNames))
(&amp;(cn=%g)(objectclass=groupOfURLs)))"

    Host="smalbois01"
    Name="Security:Name=myrealmIPlanetAuthenticator" Port="399"
    Principal="cn=Directory Manager"
    Realm="Security:Name=myrealm"
    StaticGroupDNsfromMemberDNFilter="(&amp;(uniquemember=%M)
(objectclass=groupofuniquenames))"

    StaticGroupNameAttribute="cn"
    StaticGroupObjectClass="groupofuniquenames"
    StaticMemberDNAttribute="member"
    UserBaseDN="ou=people, dc=emea,dc=bea,dc=com"
    UserDynamicGroupDNAttribute="postalAddress"
    UserFromNameFilter="(&amp;(uid=%u)(objectclass=person))"
    UserNameAttribute="uid" UserObjectClass="person" GroupSearchScope="subtree" UserSearchScope="subtree" />

以粗体字符表示的属性将是要通过示例加以研究的属性。

返回页首

在组成员资格支持上可以使用的方案有哪些?
可以使用 3 个方案来确定用户属于哪个组:

方案 0 – 此方案用于以静态方式使用 StaticGroupDNsfromMemberDNFilter 过滤器来查找组成员资格。

方案 1 - 人员条目在此处有其所属组的 DN 的列表。对于此类型,请设置用户动态组 DN 属性 (UserDynamicGroupDNAttribute)。WLS 通过读取人员对象上的该属性并从中获取组来确定组成员资格。

方案 2 - 第二种类型是动态组基于某种属性 (DynamicMemberURLAttribute) 选择人员之处。对于此类型,请将动态组对象类 (DynamicGroupObjectClass) 设置为组对象的对象类,无论它是什么类(例如,可以是 groupOfURLs。WLS 通过查找所有动态组(所有对象类为 DynamicGroupObjectClass 的组)并根据用户 DN 评估每个 DynamicMemberURLAttribute 中的过滤来确定用户的组成员资格。

这 3 个方案可以一起使用 (AND/OR)。

返回页首

尝试验证用户身份并以静态方式检索组(方案 0)时会出现的情况?
首先,在验证 Web 应用程序的身份(例如,使用基于表单的身份验证)时,需要提供用户名和密码。

在本例中我们使用 user0,因为我们知道使用它可以通过。

WebLogic 将需要根据 LDAP 服务器验证用户的身份:
<Debug> <SecurityDebug> <000000> <LDAP ATN LoginModule initialized>
<Debug> <SecurityDebug> <000000> <LDAP Atn Login>
<Debug> <SecurityDebug> <000000> <LDAP Atn Login username: user0>
<Debug> <SecurityDebug> <000000> <getConnection return conn:LDAPConnection {ldap://smalbois01:399 ldapVersion:3 bindDN:"cn=Directory Manager"}>
<Debug> <SecurityDebug> <000000> <authenticate user:user0>

它首先需要了解该用户是否存在:我们为在 UserSearchScope 中定义的范围内的当前用户在 UserBaseDN 中搜索满足过滤条件 UserFromNameFilter 的所有对象。如果成功,就可得到完整的用户 DN:
<Debug> <SecurityDebug> <000000> <getDNForUser search("ou=people, dc=emea,dc=bea,dc=com", "(&(uid=user0)(objectclass=person))", base DN & below)>
<Debug> <SecurityDebug> <000000> <DN for user user0: uid=user0,ou=People,dc=emea,dc=bea,dc=com>

既然我们已得到用户的完整 DN,即可根据 LDAP 验证用户身份:
<Debug> <SecurityDebug> <000000> <authenticate user:user0 with DN:uid=user0,ou=People, dc=emea,dc=bea,dc=com>
<Debug> <SecurityDebug> <000000> <authentication succeeded>
<Debug> <SecurityDebug> <000000> <returnConnection conn:LDAPConnection {ldap://smalbois01:399 ldapVersion:3 bindDN:"cn=Directory Manager"}>
<Debug> <SecurityDebug> <000000> <LDAP Atn Authenticated User user0>

现在需要了解此用户是否静态地属于任何组。
<Debug> <SecurityDebug> <000000> <List groups that member: user0 belongs to>
<Debug> <SecurityDebug> <000000> <getConnection return conn:LDAPConnection {ldap://smalbois01:399 ldapVersion:3 bindDN:"cn=Directory Manager"}>
<Debug> <SecurityDebug> <000000> <getDNForUser search("ou=people, dc=emea,dc=bea,dc=com", "(&(uid=user0)(objectclass=person))", base DN & below)>
<Debug> <SecurityDebug> <000000> <DN for user user0: uid=user0,ou=People,dc=emea,dc=bea,dc=com>

我们将在 GroupBaseDN 中进行搜索,确定 GroupSearchScope="subtree" 范围内是否有任何 StaticGroupDNsfromMemberDNFilter
<Debug> <SecurityDebug> <000000> <search("ou=groups, dc=emea,dc=bea,dc=com", "(&(uniquemember=uid=user0,ou=People, dc=emea,dc=bea,dc=com)(objectclass=groupofuniquenames))", base DN & below)>

由于有为用户 User0 定义的静态组和组 BEA,因此搜索结果会显示存在一些元素。

<Debug> <SecurityDebug> <000000> <Result has more elements:true>

它将找到它们并显示 user0 是组 BEA 的成员。

<Debug> <SecurityDebug> <000000> <LDAP Atn added group BEA to user user0>

WebLogic 随后决定确定组 BEA 是否为其它组的成员
<Debug> <SecurityDebug> <000000> <List groups that member: BEA belongs to>
<Debug> <SecurityDebug> <000000> <getConnection return conn:LDAPConnection {ldap://smalbois01:399 ldapVersion:3 bindDN:"cn=Directory Manager"}>

它会再次获取该组的完整 DN,使用过滤器 StaticGroupDNsfromMemberDNFilter范围 GroupSearchScope 在 GroupBaseDN 中搜索,确定 BEA 组是否有唯一成员(是另一个组的成员)
<Debug> <SecurityDebug> <000000> <search("ou=groups, dc=emea,dc=bea,dc=com", "(|(&(cn=BEA)(objectclass=groupofUniqueNames))(&(cn=BEA)(objectclass=groupOfURLs)))", base DN & below)>
<Debug> <SecurityDebug> <000000> <DN for group BEA: cn=BEA,ou=Groups, dc=emea,dc=bea,dc=com>
<Debug> <SecurityDebug> <000000> <search("ou=groups, dc=emea,dc=bea,dc=com", "(&(uniquemember=cn=BEA,ou=Groups, dc=emea,dc=bea,dc=com)(objectclass=groupofuniquenames))", base DN & below)>

由于组 BEA 不是另一个组的成员,因此可以结束操作。

<Debug> <SecurityDebug> <000000> <Result has more elements:false>

User0 是组 BEA 的成员

检查完上述静态使用情况后,即可以动态方式查找用户和组。这便是本文档前文中所述的方案 1 和方案 2。

返回页首

使用方案 1 的示例登录时会出现的情况?
对于此测试,我们将以 User1 身份登录。遗憾的是,由于对此的调试不是很多,我们将无法为您逐步介绍 WebLogic 的调试输出。

不过,算法与以下所述的非常相近:

如果 UserDynamicGroupDNAttribute(我们指定了 postalAddress – 请注意,确实只将其用作测试目的 – 但不建议在生产系统中使用此属性。本例中使用此属性的原因是以前未在此服务器上使用过它 - 动态组 DN 属性可以是任何属性。如果 LDAP 中没有对此属性而言有意义的属性名称,则可以扩展 LDAP schema,自行创建属性名称)有值,则:
    {
           我们将保留您登录时使用的当前用户的完整 DN (uid=user1,ou=People, dc=emea,dc=bea,dc=com)
            并获取您可能已在属性 UserDynamicGroupDNAttribute 中定义的组 DN 的列表(在本例中 postalAddress:cn=BEA,ou=Groups, dc=emea,dc=bea,dc=com
       随后我们将得到这些 DN 并获取此组的 DynamicGroupNameAttribute (cn)。
        接下来 WebLogic 会输出:
            <Debug> <SecurityDebug> <000000> <LDAP Atn added group BEA to user user1>

    }

然后,我们会检查该组是否同样是另一个组的成员:
<Debug> <SecurityDebug> <000000> <List groups that member: BEA belongs to>
<Debug> <SecurityDebug> <000000> <getConnection return conn:LDAPConnection {ldap://smalbois01:399 ldapVersion:3 bindDN:"cn=Directory Manager"}>
<Debug> <SecurityDebug> <000000> <search("ou=groups, dc=emea,dc=bea,dc=com", "(|(&(cn=BEA)(objectclass=groupofUniqueNames))(&(cn=BEA)(objectclass=groupOfURLs)))", base DN & below)>
<Debug> <SecurityDebug> <000000> <DN for group BEA: cn=BEA,ou=Groups, dc=emea,dc=bea,dc=com>
<Debug> <SecurityDebug> <000000> <search("ou=groups, dc=emea,dc=bea,dc=com", "(&(uniquemember=cn=BEA,ou=Groups, dc=emea,dc=bea,dc=com)(objectclass=groupofuniquenames))", base DN & below)>

由于不是这种情况,因此输出是:

<Debug> <SecurityDebug> <000000> <Result has more elements:false>

User1 是组 BEA 的成员

返回页首

使用方案 2 的示例登录时会出现的情况?
对于此测试,我们将以 User2 身份登录。

我们先尝试检索所有组

<Debug> <SecurityDebug> <000000> <search(GroupBaseDN,
"(objectclass=DynamicGroupObjectClass)", base DN & below)>


调试后的查询将是:
<Debug> <SecurityDebug> <000000> <search("ou=groups,
dc=emea,dc=bea,dc=com", "(objectclass=groupofURLs)", base DN & below)>


如果检索到一些组,则可执行以下步骤:

只要存在一些组
{
         /* 获得 dyn 组条目 */
        获取当前组并使用属性 DynamicMemberURLAttribute 检索其动态查询。
       由于您的组可能有不止一个 DynamicMemberURLAttribute,因此需要逐一为它们运行查询
        每个对 DynamicMemberURLAttribute 属性的查询
        {
            /* 获得成员 url */
           现在需要从查询 url 提取过滤器。
            url = ldap:///dc=emea,dc=bea,dc=com??sub?(&(|(objectclass=person)
(objectclass=groupofuniquenames))(mail=*user2*))

           
            /* 获得过滤器 */
           本例中得到的是
                filter = (&(|(objectclass=person)(objectclass=groupofuniquenames))(mail=*user2*))

           现在便可着手确定我们进行身份验证的用户是否满足动态组的成员条件。为此,需要进行下列搜索:
           search(经初始身份验证的用户的完整 DN, 过滤器, 范围)

           本例中将是:   
        <10 mars 2005 11 h 58 TU> <Debug> <SecurityDebug> <000000> <search("uid=user2,ou=People, dc=emea,dc=bea,dc=com",             "(&(|(objectclass=person)(objectclass=groupofuniquenames))(mail=*user2*))", base DN & below)>
          如果用户在查询“(&(|(objectclass=person)(objectclass=groupofuniquenames))(mail=*user2*))”内,则
            {
                       检索当前组上属性 DynamicMemberURLAttribute 的值并将其返回。

                       本例中,当前组为 cn=BEA,ou=Groups, dc=emea,dc=bea,dc=com,而 DynamicMemberURLAttribute=cn

                       因此我们返回组 BEA
            <Debug> <SecurityDebug> <000000> <LDAP Atn added group BEA to user user2>

                       然后我们检查此组是否为其它组的成员:

           <Debug> <SecurityDebug> <000000> <List groups that member:BEA belongs to>
            <Debug> <SecurityDebug> <000000> <getConnection return conn:LDAPConnection {ldap://smalbois01:399 ldapVersion:3             bindDN:"cn=Directory Manager"}>
            <Debug> <SecurityDebug> <000000>
            <Search("ou=groups,dc=emea,dc=bea,dc=com","
                (|(&(cn=BEA)(objectclass=groupofUniqueNames))
(&(cn=BEA)(objectclass=groupOfURLs)))", base DN & below)>

            <Debug> <SecurityDebug> <000000>
<DN for group BEA:cn=BEA,ou=Groups, dc=emea,dc=bea,dc=com>

            <Debug> <SecurityDebug> <000000>
<search("ou=groups, dc=emea,dc=bea,dc=com", "(&(uniquemember=cn=BEA,ou=Groups,             dc=emea,dc=bea,dc=com)(objectclass=groupofuniquenames))", base DN & below)>


                       它不是另一个组的成员

            <Debug> <SecurityDebug> <000000> <Result has more elements:false>
                        }
            }
}

返回页首

已知问题
您可以定期查看所用 WLS 版本的“Release Notes”,了解 Service Pack 中的“Known Issues”或“Resolved Issues”的详细信息及浏览与 LDAP 有关的问题。方便起见,下面提供了这些发行说明的链接:
使用搜索功能也可以搜索到“Release Notes”,还可以搜索到其它支持解决办法及与 CR 有关的信息,如需要更多帮助?中所提到的内容。如果客户签订了技术支持合同,则可以登录 http://support.bea.com/,登录后会看到为 Solutions 和 Bug Central 提供的 Browse portlet,可在其中按产品版本浏览最新提供的 CR。

返回页首
需要更多帮助?
如果您已经理解这个模式,但仍需要更多帮助,您可以:
  1. http://support.bea.com/ 上查询 AskBEA(例如,使用“LDAP group memebership”),以查找其它已发布的解决办法。技术支持合同客户:确保已经登录,可以访问提供的与 CR 有关的信息。
  2. http://newsgroups.bea.com/ 上,向 BEA 的某个新闻组提出更详细具体的问题。
如果这还不能解决您的问题,并且您拥有有效的技术支持合同,您可以通过登录以下网站来打开支持案例:http://support.bea.com/

反馈

请给我们提供您的意见,说明此支持诊断模式“理解 LDAP 组成员资格搜索(静态与动态)”一文是否有所帮助、您需要的任何解释,以及对支持诊断模式的新主题的任何要求。

返回页首

免责声明:

依据 BEA 与您签署的维护和支持协议条款,BEA Systems, Inc. 在本网站上提供技术技巧和补丁供您使用。虽然您可以将这些信息和代码与您获得 BEA 授权的软件一起使用,但 BEA 并不对所提供的技术技巧和补丁做任何形式的担保,无论是明确的还是隐含的。

本文档中引用的任何商标是其各自所有者的财产。有关完整的商标信息,请参考您的产品手册。