首页 > 其他分享 >LDAP简单介绍及使用

LDAP简单介绍及使用

时间:2024-05-01 21:55:47浏览次数:28  
标签:LDAP dc 介绍 ldap env 简单 import com

前言

随着企业内部各种开源平台越来越多,例如:gitlab、Jenkins、JumpServer、Rancher等,账号维护变成一件繁琐的事情,这时需要一个统一账号维护的平台,每人只需一个账号,在公司内部平台通用。而大多数开源平台都支持 LDAP,因此只要搭建好 LDAP 服务,将企业内部这些平台都对接到 LDAP,即可实现统一账号管理。

LDAP(Light Directory Access Portocol),它是基于 X.500 标准的轻量级目录访问协议。目录数据库是一个为查询、浏览和搜索而优化的数据库,它成树状结构组织数据,类似文件目录一样。目录数据库和关系数据库不同,它有优异的读性能,但写性能差,并且没有事务处理、回滚等复杂功能,不适于存储修改频繁的数据。所以目录天生是用来查询的,就好象它的名字一样。

LDAP目录服务是由目录数据库和一套访问协议组成的系统。

基本概念

  1. 目录树:在一个目录服务系统中,整个目录信息集可以表示为一个目录信息树,树中的每个节点是一个条目。
  2. 条目:每个条目就是一条记录,每个条目有自己的唯一可区别的名称(DN)。
  3. 对象类:与某个实体类型对应的一组属性,对象类是可以继承的,这样父类的必须属性也会被继承下来。
  4. 属性:描述条目的某个方面的信息,一个属性由一个属性类型和一个或多个属性值组成,属性有必须属性和非必须属性。
关键字 英文全称 含义
dc Domain Component 域名的部分,其格式是将完整的域名分成几部分,如域名为example.com变成dc=example,dc=com(一条记录的所属位置)
uid User Id 用户ID songtao.xu(一条记录的ID)
ou Organization Unit 组织单位,组织单位可以包含其他各种对象(包括其他组织单元),如“oa组”(一条记录的所属组织)
cn Common Name 公共名称,如“Thomas Johansson”(一条记录的名称)
sn Surname 姓,如“许”
dn Distinguished Name “uid=songtao.xu,ou=oa组,dc=example,dc=com”,一条记录的位置(唯一)
rdn Relative dn 相对辨别名,类似于文件系统中的相对路径,它是与目录树结构无关的部分,如“uid=tom”或“cn= Thomas Johansson”

安装服务器

这里我们使用 docker 来部署 openldap

docker pull osixia/openldap
docker run \
    -d \
    -p 389:389 \
    -p 636:636 \
    --env LDAP_ORGANISATION="imooc" \
    --env LDAP_DOMAIN="imooc.com" \
    --env LDAP_ADMIN_PASSWORD="test123456" \
    --name openldap \
    osixia/openldap
  • -p 389:389 TCP/IP访问端口,-p 636:636 SSL连接端口。
  • –name 自行设置容器名称
  • –env LDAP_ORGANISATION 配置LDAP组织名称
  • –env LDAP_DOMAIN 配置LDAP域名
  • –env LDAP_ADMIN_PASSWORD 配置LDAP密码

注意:要开通防火墙的 389 和 636 端口

安装可视化工具:PHPLdapAdmin客户端

docker pull osixia/phpldapadmin
docker run \
    -d \
    -p 8080:80 \
    --name ldap-admin \
    --env PHPLDAPADMIN_HTTPS=false \
    --env PHPLDAPADMIN_LDAP_HOSTS=your_ip \
    osixia/phpldapadmin
  • –env PHPLDAPADMIN_HTTPS=false 禁用HTTPS
  • –env PHPLDAPADMIN_LDAP_HOSTS 配置openLDAP的IP或者域名

注意:要开通防火墙的 8080 端口

在 LDAP 中创建用户

登录

浏览器访问 http://ip:8080

  • 账号为 CN=admin,DC=imooc,DC=com
  • 密码为 test123456

创建 ou

创建用户

dn: uid=xiaoming,ou=beijing,dc=imooc,dc=com
ou: beijing
uid: xiaoming
sn: 小明
cn: xiaoming
givenName: xiaoming
displayName: xiaoming
mail: [email protected]
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
userpassword: 123456

最终目录结构为

java客户端调用

根据 cn 从 beijing 这个组织下查询用户信息

使用jdk内置实现

import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.InitialLdapContext;
import java.util.Hashtable;

public class TestLdap {
    public static void main(String[] args) throws NamingException {
        DirContext dirContext = ldapContext();
        NamingEnumeration<SearchResult> enumeration = dirContext.search("ou=beijing,dc=imooc,dc=com", "cn=xiaoming", getDefaultSearchControls());
        while (enumeration.hasMoreElements()) {
            SearchResult searchResult = enumeration.next();
            System.out.println(searchResult);
        }
    }

    private static DirContext ldapContext() throws NamingException {
        Hashtable<String, String> env = new Hashtable<String, String>();
        env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
        env.put(Context.PROVIDER_URL, "ldap://ip:389");
        env.put(Context.SECURITY_AUTHENTICATION, "simple");
        env.put(Context.SECURITY_PRINCIPAL, "cn=admin,dc=imooc,dc=com");
        env.put(Context.SECURITY_CREDENTIALS, "test123456");
        return new InitialLdapContext(env, null);
    }

    private static SearchControls getDefaultSearchControls() {
        SearchControls controls = new SearchControls();
        controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
        return controls;
    }
}

使用unboundid这个ldapsdk

添加依赖

<dependency>
    <groupId>com.unboundid</groupId>
    <artifactId>unboundid-ldapsdk</artifactId>
    <version>6.0.5</version>
</dependency>
import com.unboundid.ldap.sdk.LDAPConnection;
import com.unboundid.ldap.sdk.LDAPException;
import com.unboundid.ldap.sdk.SearchRequest;
import com.unboundid.ldap.sdk.SearchResult;
import com.unboundid.ldap.sdk.SearchResultEntry;
import com.unboundid.ldap.sdk.SearchScope;

import java.util.List;

public class TestLdap2 {
    public static void main(String[] args) throws LDAPException {
        LDAPConnection ldapConnection = new LDAPConnection();
        ldapConnection.connect("ip", 389);
        ldapConnection.bind("cn=admin,dc=imooc,dc=com","test123456");
        SearchRequest searchRequest = new SearchRequest("ou=beijing,dc=imooc,dc=com", SearchScope.SUB,"cn=xiaoming");
        SearchResult searchResult = ldapConnection.search(searchRequest);
        List<SearchResultEntry> searchEntries = searchResult.getSearchEntries();
        System.out.println(searchEntries);
    }
}

使用spring封装

添加依赖

<dependency>
    <groupId>org.springframework.ldap</groupId>
    <artifactId>spring-ldap-core</artifactId>
    <version>2.4.0</version>
</dependency>
import org.springframework.ldap.core.AttributesMapper;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.core.support.LdapContextSource;
import org.springframework.ldap.filter.AndFilter;
import org.springframework.ldap.filter.EqualsFilter;

import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class TestSpringLdap {
    public static void main(String[] args) {
        LdapTemplate ldapTemplate = ldapTemplate();
        AndFilter filter = new AndFilter();
        filter.and(new EqualsFilter("cn", "xiaoming"));
        List<Map<String, Object>> searchResult = ldapTemplate.search("ou=beijing,dc=imooc,dc=com", filter.encode(), new LdapUserAttributeMapper());
        System.out.println(searchResult);
    }

    private static LdapTemplate ldapTemplate() {
        LdapContextSource ldapContextSource = new LdapContextSource();
        ldapContextSource.setUrl("ldap://ip:389");
        ldapContextSource.setUserDn("cn=admin,dc=imooc,dc=com");
        ldapContextSource.setPassword("test123456");
        ldapContextSource.afterPropertiesSet();
        return new LdapTemplate(ldapContextSource);
    }

    public static class LdapUserAttributeMapper implements AttributesMapper<Map<String, Object>> {

        @Override
        public Map<String, Object> mapFromAttributes(Attributes attributes) throws NamingException {
            Map<String, Object> map = new HashMap<>();
            NamingEnumeration<? extends Attribute> enumeration = attributes.getAll();
            while (enumeration.hasMoreElements()) {
                Attribute attribute = enumeration.next();
                map.put(attribute.getID(), attribute.get());
            }
            return map;
        }
    }
}

底层就是对 jdk 内置实现的封装。

参考

LDAP统一认证服务解决方案[通俗易懂]
LDAP概念和原理介绍
docker安装openldap
docker部署 OpenLDAP,实现账号的统一管理

标签:LDAP,dc,介绍,ldap,env,简单,import,com
From: https://www.cnblogs.com/strongmore/p/18113978

相关文章

  • .net事件(做一个简单的记录)
    描述(做一个简单的记录):    事件(event)的本质是一个委托;(声明一个事件:publiceventTestDelegateeventTest;)  委托(delegate)可以理解为一个符合某种签名的方法类型;比如:TestDelegate委托的返回数据类型为string,参数为int和EventPara,而TestI方法的参数和返回类型和TestDel......
  • Oracle日志记录模式 - LOGGING、FORCE LOGGING、NOLOGGING模式介绍
    一、日志记录模式(LOGGING、FORCELOGGING、NOLOGGING)内容转载自:https://www.cnblogs.com/tk-bolg/p/12867772.html1.三者的含义LOGGING:当创建一个数据库对象时将记录日志信息到联机重做日志文件。LOGGING实际上是对象的一个属性,用来表示在创建对象时是否记录REDO日志,包括......
  • 简单解决version 'GLIBC_2.34' not found,version 'GLIBC_2.25' not found
    简单解决version'GLIBC_2.34'notfound,version'GLIBC_2.25'notfound无需手动下载安装包编译前言很多博客都是要手动下载安装包进行编译升级,但这样很容易导致系统崩溃,本博文提供一个简单的方法,参考自博客1,博客2.检查版本strings/usr/lib64/libc.so.6|grepGLIBC_或者......
  • 【Qt之JSON文件】QJsonDocument、QJsonObject、QJsonArray等类介绍及使用
    简述Qt5中包含了处理JSON的类,均以QJson开头(例如:QJsonDocument、QJsonArray、QJsonObject),在QtCore模块中,不需要额外引入其它模块。简述常用的JSON库JSON常用类简单的JSON对象简单的JSON数组复杂的JSON更多参考 常用的JSON库json.org 中介绍了......
  • WPF多语言支持:简单灵活的动态切换,让你的程序支持多国语言
     概述:本示例演示了在WPF应用程序中实现多语言支持的详细步骤。通过资源字典和数据绑定,以及使用语言管理器类,应用程序能够在运行时动态切换语言。这种方法使得多语言支持更加灵活,便于维护,同时提供清晰的代码结构。在WPF中实现多语言的一种常见方法是使用资源字典和数据绑定。......
  • dbt docs generate 简单说明
    dbtdocsgenerate核心是获取dbt项目的元数据信息(包含了project的)以及相关table的(dbt模型相关的),然后通过提供的解析页面进行显示目前是基于静态处理的(先生成,然后基于纯web的解析渲染)对于展示方法很多,可以基于dbt的docsserve命令也可以基于自己的静态webserver(nginx或......
  • dbt 自定义schema 简单说明
    dbt的schema我们是可以灵活进行自定义的,可以实现一个比较有意思的事情使用场景模型级别的schema自定义seed数据schema自定义不同env或者vars的schema自定义不同targetschema的自定义schema自定义核心是generate_schema_name这个macro,我们可以自己定义参考自......
  • dbt Relation 扩展简单说明
    dbt的Relation实际上就是包含关系数据库表,数据库,schema一些信息的描述,dbt官方提供了api.Relation.create等操作进行Relation的维护,当然系统的builtins也提供了一些基本的操作能力,内部使用上会使用dbtBaseRelation中的各类实现比如pg就自己扩展了一个,同时在自己的m......
  • dbt 自定义AdapterPlugin 中dependencies 简单说明
    结合dbt-redshift的对于dependencies部分的定义以及使用简单说明下参考代码Plugin:AdapterPlugin=AdapterPlugin(adapter=RedshiftAdapter,#type:ignorecredentials=RedshiftCredentials,include_path=redshift.PACKAGE_PATH,dep......
  • TextMeshPro - 和UGUI Text的简单对比
    已经有uguiText了,为什么还要再来个TextMeshPro?1)TextMeshPro使用了更先进的渲染技术,渲染效果更好。同样的36号斜体字在Scene窗口中,我们放大后,Text可以明显的看到锯齿,而TextMeshPro字体的边缘还是圆润光滑。2)TextMeshPro默认支持多种渐变效果3) 性能更好的描边(TextMes......