无法通过ldap获得Spring安全权限

时间:2014-06-01 15:09:00

标签: java spring spring-mvc spring-security ldap

我正在尝试使用spring security来授权用户。到目前为止,我可以用ldap对它们进行身份验证,但还是无法获得当局。

我还将ldap与Apache Directory Studio连接并查询用户信息,我可以在用户中找到权限。但是spring security ldap配置无法收集它们。

这是application-config.xml的ldap部分:

<sec:authentication-manager>
  <sec:ldap-authentication-provider 
    user-dn-pattern="uid={0},ou=myComp,o=myComp,dc=myComp,dc=ldap"
    group-search-base="dc=myComp,dc=ldap"
    group-search-filter="uniqueMember={0}"
    role-prefix="none" />

以下是Apache Directory Studio的屏幕截图,其中包含我的信息:

ADS screenshot of my user info

如您所见,我的角色信息位于用户的 nsRole 属性中。但是,除非我查询nsRole属性,否则在我的用户信息中看不到它。所以问题是,我可以通过添加/更改ldap配置的配置获得这些权限吗?或者我是否必须编写自己的身份验证提供程序并连接ldap服务器并手动查询nsRole属性?

非常感谢..

注意:这是一个自定义java代码,它连接ldap服务器并成功查询我的用户角色。     包ldap;

import java.util.Hashtable;

import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;

public class LdapTest2 {

    public static void main(String[] args) {
        Hashtable env = new Hashtable(11);
        env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
        env.put(Context.PROVIDER_URL, "ldap://myCompldap.mycomp.local:389/");
        env.put(Context.SECURITY_AUTHENTICATION, "simple");
        env.put(Context.SECURITY_PRINCIPAL, "uid=myUser,ou=myComp,o=myComp,dc=myComp,dc=ldap");
        env.put(Context.SECURITY_CREDENTIALS, "myPass");

        try {
            LdapContext ctx = new InitialLdapContext(env, null);
            ctx.setRequestControls(null);
            NamingEnumeration<?> namingEnum = ctx.search("uid=myUser,ou=myComp,o=myComp,dc=myComp,dc=ldap", "(objectClass=*)", getSimpleSearchControls());
            while (namingEnum.hasMore ()) {
                SearchResult result = (SearchResult) namingEnum.next ();
                Attributes attrs = result.getAttributes ();
                Attribute lattr = attrs.get("nsrole");

                NamingEnumeration allRoles = lattr.getAll();
                while(allRoles.hasMore()) {
                    Object role = allRoles.next();
                    System.out.println(role);
                }

            } 
            namingEnum.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static SearchControls getSimpleSearchControls() {
        SearchControls searchControls = new SearchControls();
        searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
        searchControls.setTimeLimit(30000);
        String[] attrIDs = {"nsRole"};
        searchControls.setReturningAttributes(attrIDs);
        return searchControls;
    }

}

2 个答案:

答案 0 :(得分:2)

由于您的用户角色是用户目录条目的一部分,因此您应该能够使用自定义UserDetailsContextMapper加载它们。将自定义角色加载代码移至mapUserFromContext方法。您可以使用NullLdapAuthoritiesPopulator跳过正常的角色搜索。

您需要configure the authentication provider explicitly

<bean id="ldapAuthProvider" class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">
   <constructor-arg>
       <bean class="org.springframework.security.ldap.authentication.BindAuthenticator">
           <constructor-arg ref="contextSource"/>
           <property name="userDnPatterns">
             <list><value>uid={0},ou=myComp,o=myComp,dc=myComp,dc=ldap</value></list>
           </property>
       </bean>
   </constructor-arg>
   <constructor-arg>
       <bean class="org.springframework.security.ldap.authentication.NullLdapAuthoritiesPopulator" />
   </constructor-arg>
   <property name="userDetailsContextMapper" ref="yourContextMapperImplementation" />
</bean>

答案 1 :(得分:0)

spring security假设您的ldap树就是这样。

o=myComp,dc=com,dc=tr
      |
      |----ou=users (node)
      |      |
      |      |
      |      |-----uid=myuser1,dc=myComp,dc=com,dc=tr (node)
      |      |
      |      |-----uid=myuser2,dc=myComp,dc=com,dc=tr (node)
      |
      |
      |----ou=groups (node)
             |
             |
             |-----cn=myRole (node)
                       |
                  uniqueMember: uid=myuser1,dc=myComp,dc=com,dc=tr (attribute on myRole)
                  uniqueMember: uid=myuser2,dc=myComp,dc=com,dc=tr (attribute on myRole)

但你的ldap树是不同的。所以找不到角色。你的树没错。您可以使用自定义userDetailsContextMapper作为@LukeTaylor说。但角色和用户应该在不同的节点中。如果你把角色作为attibute放在用户节点上,我认为当你想要更新角色时这没用。例如如果要删除角色或更改角色名称,则应更新所有用户节点。但是如果您为每个角色创建节点,那么您只需删除或重命名一个节点。

<强>更新

如果您更新ldap树。它应该工作

  <sec:ldap-authentication-provider 
    user-dn-pattern="uid={0},ou=myComp,o=myComp,dc=myComp,dc=ldap"
    group-search-base="ou=groups"
    group-search-filter="roleOccupant={0}"
    role-prefix="none" />

注意:对于角色节点,请使用organizationalRole objectClass。因为groupOfUniqueNames只需要一个uniqueMember。但organizationalRole不要求。