当前位置: 首页 > 工具软件 > Spring LDAP > 使用案例 >

spring ldap 使用心得

公冶光亮
2023-12-01

详细概念参考:详细介绍

什么是ldap

DAP的英文全称是Lightweight Directory Access Protocol,简称为LDAP。LDAP是轻量目录访问协议。目录服务是一个特殊的数据库,用来保存描述性的、基于属性的详细信息,支持过滤功能。它成树状结构组织数据,类似文件目录一样。目录数据库和关系数据库不同,它有优异的读性能,但写性能差,并且没有事务处理、回滚等复杂功能,不适于存储修改频繁的数据。所以目录天生是用来查询的,就好象它的名字一样。

为什么要使用LDAP

LDAP是开放的Internet标准,支持跨平台的Internet协议,在业界中得到广泛认可的,并且市场上或者开源社区上的大多产品都加入了对LDAP的支持,因此对于这类系统,不需单独定制,只需要通过LDAP做简单的配置就可以与服务器做认证交互。“简单粗暴”,可以大大降低重复开发和对接的成本。

LDAP概念

每一个系统、协议都会有属于自己的模型,LDAP也不例外,在了解LDAP的基本模型之前我们需要先了解几个LDAP的目录树概念:

(一)目录树概念

  1. 目录树:在一个目录服务系统中,整个目录信息集可以表示为一个目录信息树,树中的每个节点是一个条目。

  2. 条目:每个条目就是一条记录,每个条目有自己的唯一可区别的名称(DN)。

  3. 对象类:与某个实体类型对应的一组属性,对象类是可以继承的,这样父类的必须属性也会被继承下来。

  4. 属性:描述条目的某个方面的信息,一个属性由一个属性类型和一个或多个属性值组成,属性有必须属性和非必须属性。

(二)DC、UID、OU、CN、SN、DN、RDN

关键字英文全称含义
dcDomain Component域名的部分,其格式是将完整的域名分成几部分,如域名为example.com变成dc=example,dc=com(一条记录的所属位置)
uidUser Id用户ID songtao.xu(一条记录的ID)
ouOrganization Unit组织单位,组织单位可以包含其他各种对象(包括其他组织单元),如“oa组”(一条记录的所属组织)
cnCommon Name公共名称,如“Thomas Johansson”(一条记录的名称)
snSurname姓,如“许”
dnDistinguished Name“uid=songtao.xu,ou=oa组,dc=example,dc=com”,一条记录的位置(唯一)
rdnRelative dn相对辨别名,类似于文件系统中的相对路径,它是与目录树结构无关的部分,如“uid=tom”或“cn= Thomas Johansson”

java中如何使用

// 只要不抛出异常就是验证通过
    public LdapContext adLogin(String username,String password) {
        String server = ldapConfig.getUrl();
        try {
            Hashtable<String, String> env = new Hashtable<String, String>();
            //用户名称,cn,ou,dc 分别:用户,组,域
            env.put(Context.SECURITY_PRINCIPAL, username);
            //用户密码 cn 的密码
            env.put(Context.SECURITY_CREDENTIALS, password);
            //url 格式:协议://ip:端口/组,域   ,直接连接到域或者组上面
            env.put(Context.PROVIDER_URL, server);
            //LDAP 工厂
            env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
            //验证的类型     "none", "simple", "strong"
            env.put(Context.SECURITY_AUTHENTICATION, "simple");
            LdapContext ldapContext = new InitialLdapContext(env, null);
            logger.info("ldapContext:" + ldapContext);
            logger.info("用户" + username + "登录验证成功");
            return ldapContext;

        } catch (NamingException e) {
            logger.info("用户" + username + "登录验证失败");
            logger.info("错误信息:"+e.getExplanation());
            return null;
        }
    }


    public List<UserLdap> getUserKey(String name){
        //通过配置获取ldap获取账户名  也可以直接写自己的密码 我写在了yml配置
        String userName = ldapConfig.getUserName();
        //获取密码
        String password = ldapConfig.getPassword();
        logger.info("需要查询的ad信息:{}",name);
        List<UserLdap> resultList = new ArrayList<>();
        //连接到域控
        LdapContext ldapContext = adLogin(userName,password);
        if (ldapContext!=null){
            try {
                // 域节点
                String searchBase = rootDnFromDomain(ldapConfig.getDomain());
                // LDAP搜索过滤器类
                //cn=*name*模糊查询
                //cn=name 精确查询
                // String searchFilter = "(objectClass="+type+")";
                //查询域帐号
                String searchFilter = "(sAMAccountName=*"+name+"*)";

                // 创建搜索控制器
                SearchControls searchCtls = new SearchControls();
                String  returnedAtts[]={"mobile","telephoneNumber","displayname","sAMAccountName"};
                //设置指定返回的字段,不设置则返回全部
                searchCtls.setReturningAttributes(returnedAtts);
                //  设置搜索范围 深度
                searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
                // 根据设置的域节点、过滤器类和搜索控制器搜索LDAP得到结果
                NamingEnumeration answer = ldapContext.search(searchBase, searchFilter,searchCtls);
                // 初始化搜索结果数为0
                int totalResults = 0;
                int rows = 0;
                // 遍历结果集
                while (answer.hasMoreElements()) {
                    // 得到符合搜索条件的DN
                    SearchResult sr = (SearchResult) answer.next();

                    String dn = sr.getName();

                    // 得到符合条件的属性集
                    Attributes Attrs = sr.getAttributes();
                    if (Attrs != null) {
                        try {
                            UserLdap lu = new UserLdap();
                            ++rows;
                            for (NamingEnumeration ne = Attrs.getAll(); ne.hasMore();) {
                                // 得到下一个属性
                                Attribute Attr = (Attribute) ne.next();

                                String id = Attr.getID();
                                String value = Attr.get().toString();
                                if ("displayName".equals(id)){
                                    lu.setUsername(value);
                                }else if ("sAMAccountName".equals(id)){
                                    lu.setsAMAccountName(value);
                                }else if ("mobile".equals(id)){
                                    lu.setMobile(value);
                                }else if ("telephoneNumber".equals(id)){
                                    lu.setTelephoneNumber(value);
                                }
                            }

                            if (lu.getMobile()!=null &&lu.getsAMAccountName()!=null &&lu.getUsername()!=null &&lu.getTelephoneNumber()!=null  ){
                                resultList.add(lu);
                            }
                        } catch (NamingException e) {
                            logger.info("Throw Exception : " + e.getMessage());
                        }
                    }
                }
                logger.info("总共用户数:" + rows);
            } catch (NamingException e) {
                logger.info("Throw Exception : " + e.getMessage());
            }finally {
                try{
                    ldapContext.close();
                }catch (Exception e){
                    logger.error("ldapContext关闭错误" + e);
                }
            }
        }
        return resultList;
    }

更加具体的操作 可以去百度看看

spring LDAP

LDAP配置

@Configuration
@Data
public class LdapConfig {

    @Value("${ldap.username}")
    private String userName;

    @Value("${ldap.password}")
    private String password;

    @Value("${ldap.url}")
    private String Url;

    @Value("${ldap.domain}")
    private String domain;

    @Value("${ldap.enabled}")
    private String enabled;

    @Value("${ldap.search-filter}")
    private String searchFilter;
}

配置ldapTemplate

@Configuration
public class LdapConfiguration {

    @Autowired
    private LdapConfig ldapConfig;


    @Bean
    public LdapContextSource contextSource() {
        LdapContextSource contextSource = new LdapContextSource();
        Map<String, Object> config = Maps.newHashMap();
        contextSource.setUrl(ldapConfig.getUrl());
        contextSource.setBase(rootDnFromDomain(ldapConfig.getDomain()));
        contextSource.setUserDn(ldapConfig.getUserName());
        contextSource.setPassword(ldapConfig.getPassword());
        // 解决乱码
        config.put("java.naming.ldap.attributes.binary", "objectGUID");
        contextSource.setPooled(true);
        contextSource.setBaseEnvironmentProperties(config);
        return contextSource;
    }

    @Bean
    public LdapTemplate ldapTemplate() {
        LdapTemplate ldapTemplate = new LdapTemplate(contextSource());
        //忽略查找结果时出现异常
        ldapTemplate.setIgnorePartialResultException(true);
        return ldapTemplate;
    }

    private String rootDnFromDomain(String domain) {
        String[] tokens = StringUtils.tokenizeToStringArray(domain, ".");
        StringBuilder root = new StringBuilder();
        int length = tokens.length;
        for (int i = 0; i < length; ++i) {
            String token = tokens[i];
            if (root.length() > 0) {
                root.append(',');
            }
            root.append("dc=").append(token);
        }
        return root.toString();
    }
}

    /**
     * 查找用户
     * @param name
     * @return 用户
     */
    @Override
    public UserLdap findUser(String name) {
        AndFilter filter = new AndFilter();
        filter.and(new LikeFilter("sAMAccountName",name));
        List<UserLdap> list = ldapTemplate.search("", filter.encode(), new AttributesMapper() {
            @Override
            public Object mapFromAttributes(Attributes attributes) throws NamingException {
                if (attributes != null) {
                    try {
                        UserLdap lu = new UserLdap();
                        for (NamingEnumeration ne = attributes.getAll(); ne.hasMore();) {
                            // 得到下一个属性
                            Attribute attr = (Attribute) ne.next();
                            String id = attr.getID();
                            String value = attr.get().toString();
                            if ("displayName".equals(id)){
                                lu.setUsername(value);
                            }else if ("sAMAccountName".equals(id)){
                                lu.setsAMAccountName(value);
                            }else if ("mobile".equals(id)){
                                lu.setMobile(value);
                            }else if ("telephoneNumber".equals(id)){
                                lu.setTelephoneNumber(value);
                            }
                        }
                        if (lu.getsAMAccountName()!=null){
                            return lu;
                        }
                        return null;
                    } catch (NamingException e) {
                        logger.error("LDAP findUser error : ",e);
                    }
                }
                return null;
            }
        });
        if (list.size()<1) {
            return null;
        }
        return list.get(0);
    }

    /**
     * 模糊搜索用户
     * @param name
     * @return 用列表
     */
    @Override
    public List<UserLdap> searchUsers(String name) {
        AndFilter filter = new AndFilter();
        filter.and(new LikeFilter("sAMAccountName","*" + name + "*"));
        List<UserLdap> list = ldapTemplate.search("", filter.encode(), new AttributesMapper() {
            @Override
            public Object mapFromAttributes(Attributes attributes) throws NamingException {
                if (attributes != null) {
                    try {
                        UserLdap lu = new UserLdap();
                        for (NamingEnumeration ne = attributes.getAll(); ne.hasMore();) {
                            // 得到下一个属性
                            Attribute attr = (Attribute) ne.next();
                            String id = attr.getID();
                            String value = attr.get().toString();
                            if ("displayName".equals(id)){
                                lu.setUsername(value);
                            }else if ("sAMAccountName".equals(id)){
                                lu.setsAMAccountName(value);
                            }else if ("mobile".equals(id)){
                                lu.setMobile(value);
                            }else if ("telephoneNumber".equals(id)){
                                lu.setTelephoneNumber(value);
                            }
                        }
                        if (lu.getsAMAccountName()!=null){
                            return lu;
                        }
                        return null;
                    } catch (NamingException e) {
                        logger.error("LDAP searchUsers error : ",e);
                    }
                }
                return null;
            }
        });
        if (list.isEmpty()) {
            return new ArrayList<>();
        }
        return list;
    }
 类似资料: