[TOC]
0x00 前言简述 由于其公司内部都内部各种运维系统等,当每个新员工入职就需要一个挨一个的登录到每个系统的后台给新员工开通账号,设置密码,然后员工离职还得去到每个系统后台去关闭账号,想想多浪费时间那么能不能维护一套账号,对所有系统生效呢?当然有那就是LDAP
。
在深入学习LDAP协议之前我们需要了解什么是目录服务?
1.描述:目录服务是一个特殊的数据库,用来保存描述性的、基于属性的详细信息,支持过滤功能。如:人员组织管理,电话簿,地址簿
。 2.特点:是动态的,灵活的,易扩展的。 3.目录是一个为查询、浏览和搜索而优化的数据库,它成树状结构组织数据,类似文件目录一样。
什么是LDAP?
答:维基百科:它是一个轻型目录访问协议(英文:Lightweight Directory Access Protocol
,缩写:LDAP,/ˈɛldæp/)是一个开放的,中立的,工业标准的应用协议,通过IP协议提供访问控制和维护分布式信息的目录信息。LDAP目录服务是由目录数据库和一套访问协议组成的系统,它是基于X.500标准的轻量级目录访问协议有时被称为X.500-lite
。也是IETF下的一项标准,目前最新的RFC为 RFC4510 ;
比如 DNS 协议便是一种最被广泛使用的目录服务
。
LDAP有什么用?
答:构建一个统一的账号管理、身份验证平台,实现SSO单点登录机制,即用户可以在多个应用服务系统中使用同一个密码,通常用于公司内部网站的登录以及域内机器登陆管理;
特点:
使用轻量级目录访问协议(LDAP)构建集中的身份验证系统可以减少管理成本,增强安全性,避免数据复制的问题,并提高数据的一致性。
目录数据库和关系数据库不同,它有优异的读性能,但写性能差,并且没有事务处理、回滚等复杂功能,不适于存储修改频繁的数据
;
LDAP协议版本:
为什么要使用LDAP?
答:LDAP是开放的Internet标准,支持跨平台的Internet协议,在业界中得到广泛认可的,并且市场上或者开源社区上的大多产品都加入了对LDAP的支持,因此对于这类系统,不需单独定制,只需要通过LDAP做简单的配置就可以与服务器做认证交互;>简单粗暴,可以大大降低重复开发和对接的成本
LDAP目录与普通数据库有何异同?
1.主要不同之处在于数据的组织方式,它是一种有层次的、树形结构。所有条目的属性的定义是对象类object class 的组成部分,并组成在一起构成schema ;那些在组织内代表个人的schema被命名为white pages schema 。
2.数据库内的每个条目都与若干对象类联系,而这些对象类决定了一个属性是否为可选和它保存哪些类型的信息。属性的名字一般是一个易于记忆的字符串,例如用cn为通用名(common name)命名,而”mail”代表e-mail地址。 例如mail属性包含值“user@example.com ”。
主要产品 简单了解下基于 LDAP 协议的产品有一下:
厂商
产品
简介
Opensource
Opensource
OpenLDAP 开源的项目,速度很快,但是非主流应用,但是在社区的影响下逐渐成熟。
Microsoft
Microsoft Active Directory
基于win系统用户在域控中使用,对大数据量处理速度一般,但维护容易,生态圈大,管理相对简单。
IBM
IBM Directory Server
基于DB2 的的数据库,速度一般。
Novell
Novell Directory Server
基于文本数据库的存储,速度快, 不常用到。
Oracle
Oracle Internet Directory
简称OID是Oracle 用来集中存储和管理网络服务名称的解决方案,用于查询和修改任何类似目录的实体;
Apache
Apache Directory Server
广泛使用在Apache基金会下面所属软件中比如Apache http,进行目录的索引以及展示;如OpenLDAP Apache HTTP Server使用代理服务器(通过模块mod_proxy)支持LDAP。
基本模型 每一个系统、协议都会有属于自己的模型,当然LDAP也不例外;
在了解LDAP的基本模型之前我们需要先了解几个LDAP的目录树概念:
目录树:在一个目录服务系统中,整个目录信息集可以表示为一个目录信息树,树中的一个节点称之为条目(Entry),条目包含了该节点的属性及属性值。
条目:由属性(attribute)的一个聚集组成每个条目就是一条记录,并由一个唯一性的名字引用,即专有名称 (distinguished name,DN
),可描述一个层次结构,这个结构可以反映一个政治、地理或者组织的范畴。
对象类:与某个实体类型对应的一组属性,对象类是可以继承的,这样父类的必须属性也会被继承下来。
属性:描述条目的某个方面的信息,一个属性由一个属性类型和一个或多个属性值组成,属性有必须属性和非必须属性。补充:属性取值依赖于其类型,并且LDAPv3中一般非二进制值都遵从UTF-8 字符串语法。
关键字&术语说明:Entry (or object) 条目(或对象)
:LDAP中的每个单元都认为是条目。
术语
说明
Directory
目录,用于存放信息的单元
Entry
条目,实体LDAP的基本信息单元
LDIF
全称:LDAP Interchange Format , 在RFC2849中定义的标准,用于规范LDAP的配置和目录内容等详细信息的保存,后续的例子中将会较多地使用LDIF进行增删改查的操作。
关键字
全称
简述
DN
Distinguished Name
专有名称 , DN值:”uid=admin,ou=people,dc=weiyigeek,dc=top”, 一条记录的位置(全局唯一)
DC
Domain Component -
域名组件 , 域名的部分,其格式是将完整的域名分成几部分,如域名为example.com变成dc=example,dc=com(一条记录的所属位置)
CN
Common Name
公共名称 , 如“Admin(一条记录的名称)”或者人名或对象名称
OU
Organization Unit
组织单位,组织单位可以包含其他各种对象(包括其他组织单元),如“oa组”(一条记录的所属组织)
UID
User Id
用户ID username(一条记录的ID)
SN
Surname
姓,如“文”
RDN
Relative dn
相对辨别名,类似于文件系统中的相对路径,它是与目录树结构无关的部分,如“uid=admin”或“cn=ADMIN”
参照 YAPI 中的 LDAP 配置
1 2 3 4 5 6 7 8 9 10 11 { "ldapLogin" : { "enable" : true , "server" : "ldap://l-ldapt1.ops.dev.weiyigeek.top" , "baseDn" : "CN=Admin,CN=Users,DC=weiyigeek,DC=top" , "bindPassword" : "password123" , "searchDn" : "OU=UserContainer,DC=weiyigeek,DC=top" , "searchStandard" : "mail" } }
(1) 信息模型
描述:在LDAP中的信息以树状方式组织,在树状信息中的基本数据单元是条目,而且每个条目由属性构成,属性中存储由属性值;
1 2 3 4 5 条目 属性 ------------- -------------- | 条目1 | | 类型 | |条目2 条目3|--> | 值1 .... 值n| ------------- --------------
(2) 命名模型
描述:LDAP中的命名模型即LDAP中的条目定位方式,在LDAP中每个条目均有自己的DN 是该条目在整个树中的唯一名称标识;
LDAP树形结构的构成方式而一般有两种方式:体现到LDIF的详细信息
传统方式:聚焦于国别以及地理信息为上层构成,然后按照地理信息进行继续下行,最后精确到人的姓名以及住址;
互联网域名方式: 上层构成直接使用域名,能结合DNS相关的技术;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 c=CN | st=ChongQing | o = YongChuan (The Organisation) / \ ou=YoungChuanGroup1 ou=YoungChuanGroup2 (Oraganisation Unit) | cn=WeiyiGeek dc=top | dc=WeiyiGeek / \ ou=people ou=groups / uid=admin
(3) 功能模型
描述:在LDAP中共有四类10种操作:
查询类操作,如搜索、比较;
更新类操作,如添加条目,删除条目,修改条目以及修改条目名
认证类操作,如绑定,解绑
其它操作,如放弃和扩展操作(除了扩展操作,另外9种是LDAO的标准操作,扩展操作是LDAP中为了增加新的功能,而提供的一种标准扩展框架,当前已经成为LDAP标准的扩展操作,有修改密码和startTLS扩展,在新的RFC标准和草案中正在增加一些新的扩展操作,不同的LDAP厂商也均定义了自己的扩展操作)
(4) 安全模型
描述:LDAP中的安全模型主要通过身份认证、安全通道和访问控制来进行实现;
应用场景 描述:由于LDAP主要运用于统一身份认证
,而其主要是改变原有的认证策略,使需要认证的软件都通过LDAP进行认证,在统一身份认证之后,用户的所有信息都存储在AD Server中。终端用户在需要使用公司内部服务的时候,都需要通过AD服务器的认证。
weiyigeek.top-LDAP身份认证
那么程序中是如何访问的呢?
连接到LDAP服务器;
绑定到LDAP服务器;
在LDAP服务器上执行所需的任何操作;
释放LDAP服务器的连接;
我们以PHP脚本作为例子如下:
1 2 3 4 5 $ldapconn = ldap_connect("10.10.84.78") $ldapbind = ldap_bind($ldapconn, 'username', $ldappass); $searchRows= ldap_search($ldapconn, $basedn, "(cn=*)"); $searchResult = ldap_get_entries($ldapconn, $searchRows); ldap_close($ldapconn);
0x01 环境安装 描述:在上文中我们对LDAP产品进行列举,在厂商得持续开发迭代下提供LDAP服务的软件有很多商业上获得成功的,其中以MS的AD和Redhat的NDS(Netscape directory server)
使用最为广泛,而开源领域则是OpenLdap(全文实验也是基于此版本);
什么是OpenLDAP? OpenLDAP是轻型目录访问协议(Lightweight Directory Access Protocol,LDAP)的自由和开源的实现,在其OpenLDAP许可证下发行,并已经被包含在众多流行的Linux发行版中。 官网:http://www.openldap.org
它主要包括下述4个部分:
slapd - 独立LDAP守护服务
slurpd - 独立的LDAP更新复制守护服务
实现LDAP协议的库
工具软件和示例客户端
端口说明:
端口号
备注
389
未加SSL缺省端口(明文数据传输)
689
SSL加密端口
636
加密监听端口(加密数据传输)
基于 yum 安装 环境准备:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 setenforce 0 sed -i "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config ntpdate time.nist.gov mv /etc/yum.repos.d/CentOS-Base.repo{,.bak} wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo yum clean all yum makecache yum -y install openldap openldap-clients openldap-servers openldap-servers-sql openldap-devel migrationtools yum -y install compat-openldap rpm -qa |grep openldap slapd -VV cp /usr/share/openldap-servers/DB_CONFIG.example /var/lib/ldap/DB_CONFIG cp /usr/share/openldap-servers/slapd.conf.obsolete /etc/openldap/slapd.conf database bdb suffix "dc=weiyigeek,dc=com,dc=cn" checkpoint 1024 15 rootdn "cn=admin,dc=weiyigeek,dc=com,dc=cn" loglevel Stats cachesize 1000 slappasswd -s 123456
注意:其中cn=root中的root表示OpenLDAP管理员的用户名,而olcRootPW表示OpenLDAP管理员的密码。
weiyigeek.top-salpd.conf
修改配置文件完成后进行验证配置文件以及权限设置1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 slaptest -f /etc/openldap/slapd.conf chown -R ldap:ldap /var/lib/ldap/ /etc/init.d/slapd restart slaptest -f /etc/openldap/slapd.conf rm - rf /etc/openldap/slapd.d/* slaptest -f /etc/openldap/slapd.conf -F /etc/openldap/slapd.d/ /etc/init.d/slapd restart ldapsearch -LLL -W -x -H ldap://58jb.org -D "cn=admin,dc=weiyigeek,dc=com,dc=cn" -b "dc=weiyigeek,dc=com,dc=cn" "(uid=*)"
weiyigeek.top-
注意:每次修改了配置文件,所有得重新生成配置文件的信息
;
参考文档:
基于 Docker 安装 描述:由于openldap的osixia的镜像所内置的缺省的dc即LDAP结构采用互联网域名方式; Docker镜像:https://github.com/osixia/docker-openldap
建立数据持久化目录:1 mkdir -p /opt/OpenLDAP/{config,database}
docker-compose.yml (v1.3.0 ) 安装OpenLDAP版本:Jul 30 2019 16:24:19
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 version: '3.1' services: openldap-service: image: osixia/openldap container_name: openldap restart: always environment: LDAP_DOMAIN: weiyigeek.top LDAP_ORGANISATION: weiyigeek LDAP_ADMIN_PASSWORD: weiyigeek LDAP_TLS: 'false' volumes: - "/opt/OpenLDAP/database:/var/lib/ldap" - "/opt/OpenLDAP/config:/etc/ldap/slapd.d" ports: - 389 :389 - 689 :689 networks: - opt_default phpldapadmin-service: image: osixia/phpldapadmin container_name: phpldapadmin restart: always environment: PHPLDAPADMIN_LDAP_HOSTS: openldap-service PHPLDAPADMIN_HTTPS: 'false' ports: - 6443 :443 - 6080 :80 networks: - opt_default links: - openldap-service depends_on: - openldap-service networks: opt_default: external: true
环境变量说明:1 2 3 4 5 6 默认登录用户名:admin 配置LDAP组织者:--env LDAP_ORGANISATION="weiyigeek" 配置LDAP域:--env LDAP_DOMAIN="weiyigeek.top" 配置LDAP密码:--env LDAP_ADMIN_PASSWORD="weiyigeek" 配置管理LDAP主机地址: --env PHPLDAPADMIN_LDAP_HOSTS=172.17.0.6 配置不开启HTTPS:--env PHPLDAPADMIN_HTTPS=false (默认是true )
拉取并运行镜像:1 2 3 docker-compose config docker-compose up -d
容器内部查询:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 root@4a1a157c5e70:/$apt list | grep "slapd" slapd/now 2.4.48+dfsg-1~bpo10+1 amd64 [installed,local ] root@4a1a157c5e70:/$slapd -VV @($) $OpenLDAP : slapd (Jul 30 2019 16:24:19) $ Debian OpenLDAP Maintainers <pkg-openldap-devel@lists.alioth.debian.org> root@4a1a157c5e70:/$ldapsearch -VV ldapsearch: @( Debian OpenLDAP Maintainers <pkg-openldap-devel@lists.alioth.debian.org> (LDAP library: OpenLDAP 20448) root@4a1a157c5e70:/$slapcat -v dn: dc=WeiyiGeek,dc=com,dc=cn objectClass: top objectClass: dcObject objectClass: organization o: WeiyiGeek dc: WeiyiGeek structuralObjectClass: organization entryUUID: bbbb1564-0d95-103a-95a6-a917d679da5b creatorsName: cn=admin,dc=WeiyiGeek,dc=com,dc=cn createTimestamp: 20200408033527Z entryCSN: 20200408033527.510607Z modifiersName: cn=admin,dc=WeiyiGeek,dc=com,dc=cn modifyTimestamp: 20200408033527Z
0x02 LDAP配置&命令 描述:Yum安装ldap后的配置文件说明:1 2 3 4 5 6 7 /etc/openldap/slapd.conf /etc/openldap/slapd.d/* /etc/openldap/schema/* /var/lib/ldap/* /usr/share/openldap-servers/slapd.conf.obsolete /usr/share/openldap-servers/DB_CONFIG.example
openLDAP的打开日志信息:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 $vim /etc/openldap/slapd.conf loglevel -2 slaptest -f /etc/openldap/slapd.conf -F /etc/openldap/slapd.d/ chown -R ldap.ldap /etc/openldap/slapd.d/ mkdir /var/log /slapd chmod 755 /var/log /slapd/ chown ldap.ldap /var/log /slapd/ local4.* /var/log /slapd/slapd.log /etc/init.d/slapd restart /etc/init.d/rsyslog restart tailf /var/log /slapd/slapd.log
注意事项:
从OpenLDAP2.4.23版本开始所有配置数据都保存在 /etc/openldap/slapd.d/
中,建议不再使用slapd.conf作为配置文件。
线上ACL控制配置解析希望能达到的效果是:1.管理员能够有全部权限,包含新建用户,修改用户属性及用户密码等|2.普通用户只能修改自己的密码,别的权限都没有
;1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 access to attrs=userPassword,shadowLastChange by dn="cn=admin,dc=weiyigeek,dc=top" write by dn.children="ou=Admin,dc=weiyigeek,dc=top" write by anonymous auth by self write by * none access to * by dn="cn=admin,dc=weiyigeek,dc=top" write by dn.children="ou=Admin,dc=weiyigeek,dc=top" write by * read
slapd 命令 基础示例:1 2 3 4 5 6 7 8 9 10 $slapd -VV$slaptest $slapcat -v$slapcat -n 0
ldapsearch 命令 描述:LDAP一般用于SSO的单点登录,所以其他机器能够连接进行验证是最基础的,客户端安装openldap-client包进行登录LDAP并进行查询使用;1 yum install openldap-clients
基础语法:1 2 3 4 5 6 7 8 9 10 11 12 13 14 -x: 采用简单认证 -H: ldap协议://主机:端口不能与-h和-p同时使用 -b: 指定的查询的DN条目对象的属性 -D: 指定的baseDN专有名称 -w: 简单认证方式的密码(credentials)绑定DN的密码,与-W二者选一 -h: LDAP服务器IP或者可解析的hostname,与-p可结合使用,不能与-H同时使用 -p: LDAP服务器端口 -W 不输入密码,会交互式的提示用户输入密码,与-w二者选一 -f 指定输入条件,在RFC 4515中有更详细的说明 -c 出错后忽略当前错误继续执行,缺省情况下遇到错误即终止 -n 模拟操作但并不实际执行,用于验证,常与-v一同使用进行问题定位 -v 显示详细信息 -d 显示debug信息,可设定级别 -s 指定搜索范围, 可选值:base|one|sub|children
filter 过滤条件符:
weiyigeek.top-
基础示例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 $ldapsearch -x -H ldap://localhost:389 -b "dc=WeiyiGeek,dc=com,dc=cn" -D "cn=admin,dc=WeiyiGeek,dc=com,dc=cn" -w WeiyiGeekdn: dc=WeiyiGeek,dc=com,dc=cn objectClass: top objectClass: dcObject objectClass: organization o: WeiyiGeek dc: WeiyiGeek dn: cn=WeiyiGeek,ou=Development,dc=WeiyiGeek,dc=com,dc=cn sn: WeiyiGeek cn:: IFdlaXlpR2Vlaw== uid: weiyigeek userPassword:: e01ENX00U****StWdUJYOGcrSVBnPT0= uidNumber: 1000 gidNumber: 500 homeDirectory: /home/users/weiyigeek loginShell: /bin/bash objectClass: inetOrgPerson objectClass: posixAccount objectClass: top mail: test @weiyigeek.top displayName:: 5ZSv5LiA5p6B5a6i $ldapsearch -x -H ldap://localhost:389 -b "ou=Development,dc=WeiyiGeek,dc=com,dc=cn" -D "cn=admin,dc=WeiyiGeek,dc=com,dc=cn" -w WeiyiGeek$ldapsearch -x -H ldap://localhost:389 -b "cn=Weiyi,ou=Development,dc=WeiyiGeek,dc=com,dc=cn" -D "cn=admin,dc=WeiyiGeek,dc=com,dc=cn" -w WeiyiGeekdn: cn=Weiyi,ou=Development,dc=WeiyiGeek,dc=com,dc=cn sn: Weiyi cn: weiyi uid: weiyi uidNumber: 1001 gidNumber: 500 homeDirectory: /home/users/weiyi loginShell: /bin/bash objectClass: inetOrgPerson objectClass: posixAccount objectClass: top mail: weiyi@weiyigeek.top displayName: WeiyiName search: 2 result: 0 Success $ldapsearch -x -H ldap://localhost:389 -b "dc=WeiyiGeek,dc=com,dc=cn" -D "cn=admin,dc=WeiyiGeek,dc=com,dc=cn" -w WeiyiGeek "cn=*" $ldapsearch -x -H ldap://localhost:389 -b "dc=WeiyiGeek,dc=com,dc=cn" -D "cn=admin,dc=WeiyiGeek,dc=com,dc=cn" -w WeiyiGeek "ou=*" dn: ou=Development,dc=WeiyiGeek,dc=com,dc=cn ou: Development objectClass: organizationalUnit objectClass: top dn: ou=People,dc=WeiyiGeek,dc=com,dc=cn objectClass: top objectClass: organizationalUnit ou: People search: 2 result: 0 Success $ldapsearch -x -H ldap://localhost:389 -b "dc=WeiyiGeek,dc=com,dc=cn" -D "cn=admin,dc=WeiyiGeek,dc=com,dc=cn" -w WeiyiGeek "cn=Weiyi" sn cn uid uidNumber maildn: cn=Weiyi,ou=Development,dc=WeiyiGeek,dc=com,dc=cn sn: Weiyi cn: weiyi uid: weiyi uidNumber: 1001 mail: weiyi@weiyigeek.top $ldapsearch -Q -LLL -Y EXTERNAL -H ldapi:/// -b cn=config dndn: cn=config dn: cn=module{0},cn=config dn: cn=schema,cn=config $ldapsearch -Q -LLL -Y EXTERNAL -H ldapi:/// -b "dc=WeiyiGeek,dc=com,dc=cn" "(ou=*)" $ldapsearch -LLL -x -H ldap://127.0.0.1:389/ -D "cn=admin,dc=WeiyiGeek,dc=com,dc=cn" -b "dc=WeiyiGeek,dc=com,dc=cn" "(ou=*)" -w WeiyiGeek dn: ou=Group,dc=WeiyiGeek,dc=com,dc=cn ou: Group objectClass: top objectClass: organizationalUnit dn: ou=People,dc=WeiyiGeek,dc=com,dc=cn ou: People objectClass: organizationalUnit objectClass: top
补充事项:
1.查询到的是经过Base64编码的字符串,通过解码得到SSHA加密后密匙1 2 12:20:25.644 atob("e1NTSEF9TE5GaU0rZVZXNGlR43FDdzQ5UzRMNjRlb2xjMjY5OU4=" ) 12:20:25.745 "{SSHA}LNFiM8eVW4iQGq2w49S4L74eolc2699N"
2.过滤条件实例
下列过滤器将搜索包含一个或多个 manager 属性值的条目称为存在搜索: manager=*
下列过滤器将搜索包含通用名 WeiyiGeek 的条目。这也称为等价搜索:cn=WeiyiGeek
下列过滤器返回所有不包含通用名 WeiyiGeek 的条目:(!(cn=WeiyiGeek))
下列过滤器返回的所有条目中都有包含子字符串 X.500 的说明属性:description=X.500
下列过滤器返回所有组织单元为 Marketing 且说明字段中不包含子字符串 X.500 的条目: (&(ou=Marketing)(!(description=X.500 )))
下列过滤器返回所有组织单元为 Marketing 且 manager 为 WeiyiGeek 或 Cindy Zwaska 的条目: (&(ou=Marketing)(|(manager=cn=WeiyiGeek,ou=Marketing,dc=siroe,dc=com)(manager=cn=Cindy Zwaska,ou=Marketing,dc=siroe,dc=com)))
下列过滤器返回所有不代表人员的条目: (!(objectClass=person))
下列过滤器返回所有不代表人员且通用名近似于 printer3b 的条目:(&(!(objectClass=person))(cn~=printer3b))
下列过滤器返回对象类为inetOrgPerson或者为groupOfUniqueNames的条目:(|(objectClass=inetOrgPerson)(objectClass=groupOfUniqueNames))
ldapadd 命令 ldapmodify 命令 描述:该命令用于进行数据添加,实际上ldapadd只是采用了一个软链接指向ldapmodify,所以此处我们统一进行说明;
命令参数:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Option 说明 -H ldapuri,格式为ldap://机器名或者IP:端口号,不能与-h和-p同时使用 -h LDAP服务器IP或者可解析的hostname,与-p可结合使用,不能与-H同时使用 -p LDAP服务器端口号,与-h可结合使用,不能与-H同时使用 -x 使用简单认证方式 -D 所绑定的服务器的DN -w 绑定DN的密码,与-W二者选一 -W 不输入密码,会交互式的提示用户输入密码,与-w二者选一 -f 指定ldif文件作为输入 -a 添加新的entry,ldapadd缺省使用,ldapmodify 可指定以达到同样作用 -c 出错后忽略当前错误继续执行,缺省情况下遇到错误即终止 -n 模拟操作但并不实际执行,用于验证,常与-v一同使用进行问题定位 -v 显示详细信息 -d 显示debug信息,可设定级别 -e 设置客户端证书 -E 设置客户端私钥
测试添加的LDIF文件内容:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 cat > weiyigeek.ldif <<END dn: ou=People,dc=WeiyiGeek,dc=com,dc=cn changetype: add objectclass: top objectclass: organizationalUnit ou: People dn: cn=Weiyi,ou=Development,dc=WeiyiGeek,dc=com,dc=cn changetype: add sn: Weiyi cn: weiyi uid: weiyi uidNumber: 1001 gidNumber: 500 homeDirectory: /home/users/weiyi loginShell: /bin/bash objectClass: inetOrgPerson objectClass: posixAccount objectClass: top mail: weiyi@weiyigeek.top displayName: WeiyiName END changetype: add changetype: modify cat > Demo1.ldif<<END dn: cn=Weiyi,ou=Development,dc=WeiyiGeek,dc=com,dc=cn changetype: modify replace: mail mail: WeiyiGeek@weiyi.top dn: cn=Weiyi,ou=Development,dc=WeiyiGeek,dc=com,dc=cn changetype: modify add: description description: Test User dn: cn=Weiyi,ou=Development,dc=WeiyiGeek,dc=com,dc=cn changetype: modify delete: description dn: cn=Weiyi,ou=Development,dc=WeiyiGeek,dc=com,dc=cn changetype: modrdn newrdn: uid=WeiyiTest deleteoldrdn: 0 newsuperior: ou=People,dc=WeiyiGeek,dc=com,dc=cn dn: uid=WeiyiTest,ou=People,dc=WeiyiGeek,dc=com,dc=cn changetype: delete END cat > changePasswd.ldif<<END dn: uid=WeiyiTest,ou=People,dc=WeiyiGeek,dc=com,dc=cn changetype: modify add: userPassword userPassword: 123456 dn: uid=WeiyiTest,ou=People,dc=WeiyiGeek,dc=com,dc=cn changetype: modify replace: userPassword userPassword: 123456 END
基础实例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 $ldapadd -H ldap://127.0.0.1:389 -D "cn=admin,dc=WeiyiGeek,dc=com,dc=cn" -w WeiyiGeek -f weiyigeek.ldifadding new entry "cn=Weiyi,ou=Development,dc=WeiyiGeek,dc=com,dc=cn" $ldapmodify -a -x -H ldap://127.0.0.1:389 -D "cn=admin,dc=WeiyiGeek,dc=com,dc=cn" -w WeiyiGeek -f weiyigeek.ldifadding new entry "cn=Weiyi,ou=Development,dc=WeiyiGeek,dc=com,dc=cn" $ldapmodify -x -H ldap://127.0.0.1:389 -D "cn=admin,dc=WeiyiGeek,dc=com,dc=cn" -w WeiyiGeek -f weiyigeek.ldifadding new entry "ou=People,dc=WeiyiGeek,dc=com,dc=cn" adding new entry "cn=Weiyi,ou=Development,dc=WeiyiGeek,dc=com,dc=cn" $ldapmodify -a -x -H ldap://127.0.0.1:389 -D "cn=admin,dc=WeiyiGeek,dc=com,dc=cn" -w WeiyiGeek -f Demo1.ldifmodifying entry "cn=Weiyi,ou=Development,dc=WeiyiGeek,dc=com,dc=cn" modifying entry "cn=Weiyi,ou=Development,dc=WeiyiGeek,dc=com,dc=cn" modifying entry "cn=Weiyi,ou=Development,dc=WeiyiGeek,dc=com,dc=cn" modifying rdn of entry "cn=Weiyi,ou=Development,dc=WeiyiGeek,dc=com,dc=cn" deleting entry "cn=WeiyiTest,ou=People,dc=WeiyiGeek,dc=com,dc=cn"
Question:中的ldapadd替换称ldapmodify是否能够完全一致的动作? Ask:不行,其报错信息:ldapmodify: modify operation type is missing at line 2, entry "cn=Weiyi,ou=Development,dc=WeiyiGeek,dc=com,dc=cn"
,需要加上-a参数即可;
注意事项:
当部门和人员的信息还未进行关联,当然最简单的方式是先创建部门,然后在人员信息中添加相关内容即可
添加部门关键信息则为organisationalUnit,添加用户时候关键的objectclass是inetOrgPerson
ldapdelete 命令 基础实例:1 $ldapdelete -x -h 127.0.0.1 -p 389 -D "cn=admin,dc=WeiyiGeek,dc=com,dc=cn" -w WeiyiGeek "cn=Weiyi,ou=Development,dc=WeiyiGeek,dc=com,dc=cn"
slappasswd 命令 ldappasswd 命令 描述:LDAP有三种方式可以进行修改密码即
slappasswd命令: 管理员密码修改
ldappasswd命令: 用户密码修改
ldapmodify命令结合ldif文件
ldappasswd 参数:1 2 3 4 5 6 7 8 9 10 11 12 -H ldapuri,格式为ldap://机器名或者IP:端口号,不能与-h和-p同时使用 -h LDAP服务器IP或者可解析的hostname,与-p可结合使用,不能与-H同时使用 -p LDAP服务器端口号,与-h可结合使用,不能与-H同时使用 -x 使用简单认证方式 -D 所绑定的服务器的DN -w 绑定DN的密码,与-W二者选一 -W 不输入密码,会交互式的提示用户输入密码,与-w二者选一 -n 模拟操作但并不实际执行,用于验证,常与-v一同使用进行问题定位 -v 显示详细信息 -d 显示debug信息,可设定级别 -S 交互式进行密码的提示和输入以及Re-enter,与-s二者选一 -s 将指定内容设为密码,与-S二者选一
基础实例:1 2 3 4 5 6 $ldappasswd -x -h 127.0.0.1 -p 389 -D "cn=admin,dc=WeiyiGeek,dc=com,dc=cn" -w WeiyiGeek "uid=WeiyiTest,ou=People,dc=WeiyiGeek,dc=com,dc=cn" New password: XJbHKyRF $ldappasswd -x -h 127.0.0.1 -p 389 -D "uid=WeiyiTest,ou=People,dc=WeiyiGeek,dc=com,dc=cn" -w XJbHKyRF -s newpass123456
0x03 LDAP客户端 LDAPAccountManager 采用 docker 容器部署LDAPAccountManager:1 2 3 4 5 6 7 8 9 10 11 12 13 docker run -d --restart=always --name ldap-account-manager -p 8081:80 \ --link openldap:ldap-host \ --env PHPLDAPADMIN_LDAP_HOSTS=ldap-host \ --env PHPLDAPADMIN_HTTPS=false \ --network=opt_default \ --detach ldapaccountmanager/lam --link这里连接到openldap容器并起了一个别名ldap-host --env PHPLDAPADMIN_LDAP_HOSTS这里直接通过别名指向openldap容器,这样不需要写死IP地址 --env PHPLDAPADMIN_HTTPS 不使用443协议 --restart=always加入此参数是防止系统重启了容器未启动 --network=已存在的网络 [`docker network ls`可以进行查看,实际与LDAP同一个网络即可]
简单置流程:
(1) 我们访问http://192.168.107.245:8081/
进行LAM基础配置,首次登录点击configuration LAM configuration
,然后选择Edit server profiles
;
(2) 默认账号密码lam/lam
进行认证后才能进行配置Server settings Server settings
,Security settings
以及Account Types
选项卡中的Users与Groups
进行 配置
weiyigeek.top-
(3) 返回首页采用安全认证中的配置的DN进行登录LDAP然后进行创建默认的组(Unit),实际你会发现与 PHPLDAPAdmin
操作实际相差不大;
weiyigeek.top-
(4) 至此,已经完成docker版的openldap和LDAP Account Manager的安装配置。
PHPLdapAdmin 描述:phpLDAPadmin(也称为PLA)是一个基于Web的LDAP客户端。它为LDAP服务器提供简单,随处可访问的多语言管理。phpLDAPadmin是LDAP专业人员和新手的完美LDAP浏览器。其分层树查看器和高级搜索功能使您可以直观地浏览和管理LDAP目录。由于它是一个Web应用程序,因此该LDAP浏览器可在许多平台上运行,使您可以从任何位置轻松管理LDAP服务器。
官网:http://phpldapadmin.sourceforge.net/wiki/index.php/Main_Page
比如采用Docker进行安装:`如果开启HTTPS,需要配置443端口映射:-p 8443:443,并采用https访问1 docker run -d --privileged -p 10004:80 --name phpldapadmin --env PHPLDAPADMIN_HTTPS=false --env PHPLDAPADMIN_LDAP_HOSTS=172.17.0.6 --detach osixia/phpldapadmin
基础配置 Step1. 访问phpldapAdmin打开浏览器访问:http://192.168.172.245:6080
1 2 账号:cn=admin,dc=weiyigeek,dc=top 密码:weiyigeek
weiyigeek.top-
Step2.登录phpLdapAdmin添加组以及ldap账号流程步骤如下:
点击新建实体Create new entry here
Templates选择:Generic: Organisational Unit
建立组织单元,输入组织名称然后提交
回到首页,再次创建条目Templates选择:Generic: Posix Group
创建组 ,输入组名称然后提交
回到首页,点击创建的OU:Development组织,然后点击 Create a child entry
创建创建一个子条目
Templates选择:Generic: User Account
- 根据需求进行输入后进行创建Object,然后点击创建的CN进行查看显示内部属性Show internal attributes
提交完成后,点击新增的用户,点击右侧【增加新的属性Add new attribute
】,选择属性【Email】添好Email地址点击【Update Object】
Step3.采用创建的账号进行登陆LDAP;1 2 DN:cn=WeiyiGeek,ou=Development,dc=weiyigeek,dc=com,dc=cn 密码:123456
weiyigeek.top-
LDAPAdmin 描述:Ldap Admin是一个用于LDAP目录管理的免费Windows LDAP客户端和管理工具。此应用程序允许您在LDAP服务器上浏览,搜索,修改,创建和删除对象。它还支持更复杂的操作,例如目录复制和在远程服务器之间移动,并扩展常用编辑功能以支持特定对象类型(例如组和帐户), 支持多类型系统:Winndows&Linux 官网:http://www.ldapadmin.org/
下载安装LDAP Admin客户端,新增连接如下:
weiyigeek.top-
Apache Directory Studio 描述: 设计用来和各种LDAP服务器进行交互操作,提供了一个使用方便的客户端操作平台。除了Apache DS之外,诸如OpenLdap也可以很好地进行交互,对于不习惯不喜欢命令行方式的用户,Apache Directory Studio也是选择之一。
官方网址:http://directory.apache.org/studio/ 支持OS:跨平台,支持MacOS/Windows/Linux 下载地址:http://directory.apache.org/studio/downloads.html
weiyigeek.top-
导入与导出
File->右键 DN
选择 Export 进行导出格式为LDIF
File->右键 DN
选择 Import 进行导入格式为LDIF的备份文件,还能通过直接修改ldif文件进行创建entry或者移动条目
;
weiyigeek.top-
入坑解决: (1)import的失败请按照如下顺序进行原因确认:
ldif文件的多个entry的格式,包括全角字符等
ldif文件内容是否有缺失,拼写是否有错误
ldif文件的内容依赖的部分,这个只能你自己根据系统的情况自行确认,本身ldap就是一个类似目录层级的方式,比如上层目录没有试图添加下层,自然会出错
ldap的权限设定与配置 一般来说都是既存的数据和ldif文件中的某个entry写错了导致的问题,请首先排除这个方面的问题
描述:采用migrationtools工具包,实现导入系统账号的相关信息;1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 yum -y install migrationtools vim /usr/share/migrationtools/migrate_common.ph 70 71 $DEFAULT_MAIL_DOMAIN = "weiyigeek.top" ; 72 73 74 $DEFAULT_BASE = "dc=WeiyiGeek,dc=com,dc=cn" ; /usr/share/migrationtools/migrate_base.pl > base.ldif $more base.ldif$ldapadd -x -c -H ldap://127.0.0.1 -D "cn=admin,dc=WeiyiGeek,dc=com,dc=cn" -w WeiyiGeek -f /root/base.ldif
weiyigeek.top-导入系统账号的相关信息
创建两个测试用户及用户组,并修改密码
1 2 3 4 5 6 groupadd ldaptest1 groupadd ldaptest2 useradd -g ldaptest1 ldaptest1 useradd -g ldaptest2 ldaptest2 echo 123456 | passwd --stdin ldaptest1echo password | passwd --stdin ldaptest2
将刚创建的两个用户导入至openldap数据文件
1 2 3 4 5 6 7 8 grep ldaptest /etc/passwd > users grep ldaptest /etc/group > groups $cat users groupsldaptest1:x:1001:1001::/home/ldaptest1:/bin/bash ldaptest2:x:1002:1002::/home/ldaptest2:/bin/bash ldaptest1:x:1001: ldaptest2:x:1002:
使用migrationtools将两个临时用户生成ldif文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 /usr/share/migrationtools/migrate_passwd.pl users > users.ldif cat users.ldif /usr/share/migrationtools/migrate_group.pl groups > groups.ldif cat groups.ldif
4.把用户导入至openLDAP的数据文件并查询导入的数据1 2 3 4 5 6 7 ldapadd -x -H ldap://127.0.0.1 -D "cn=admin,dc=WeiyiGeek,dc=com,dc=cn" -w WeiyiGeek -f users.ldif ldapadd -x -H ldap://127.0.0.1 -D "cn=admin,dc=WeiyiGeek,dc=com,dc=cn" -w WeiyiGeek -f groups.ldif
weiyigeek.top-
JNDI方式 描述:我们可以使用Java中使用javax.naming可以对Ldap用户信息进行验证,使用这点可以完成SSO之类功能的集成;
简单的基础示例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 package top.weiyigeek.other;import java.util.Enumeration;import java.util.Hashtable;import javax.naming.Binding;import javax.naming.Context;import javax.naming.NameClassPair;import javax.naming.NamingEnumeration;import javax.naming.directory.Attribute;import javax.naming.directory.Attributes;import javax.naming.directory.DirContext;import javax.naming.directory.InitialDirContext;public class LDAPDemo { public static void main (String[] args) { String IP = "10.10.107.245" ; String PORT = "389" ; String BASEDN = "dc=WeiyiGeek,dc=com,dc=cn" ; String MANAGER = "cn=admin" ; String PASS = "WeiyiGeek" ; String USERNAME = "cn=WeiyiGeek,ou=Development" ; String LDAP_URL = "ldap://" +IP+":" +PORT+"/" +BASEDN; String[] attrIDs = {"mail" ,"displayName" ,"uidNumber" ,"sn" }; Hashtable<String, String> tbl = new Hashtable<String, String>(); tbl.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory" ); tbl.put(Context.PROVIDER_URL, LDAP_URL); tbl.put(Context.SECURITY_AUTHENTICATION, "simple" ); tbl.put(Context.SECURITY_PRINCIPAL, MANAGER+"," +BASEDN); tbl.put(Context.SECURITY_CREDENTIALS, PASS); System.out.println("--------------Show Env Setting --------------" ); Enumeration<String> keys = tbl.keys(); while (keys.hasMoreElements()) { System.out.println(tbl.get(keys.nextElement())); } System.out.println("" ); System.out.println("--------------Login Verification LDAP ---------- " ); DirContext context = null ; try { context = new InitialDirContext(tbl); System.out.println("Login Successful! 登录成功" ); System.out.println("Login Verification LDAP \n" ); System.out.println("-------------- 枚举 查询对象 ---------- " ); NamingEnumeration<?> bindings = context.listBindings("" ); while (bindings.hasMore()) { Binding bd = (Binding)bindings.next(); System.out.println(bd.getName() + ": " + bd.getNameInNamespace() + ": " + bd.getObject() ); } bindings.close(); try { Attributes answer = context.getAttributes(USERNAME); System.out.println("\n-----------------获取 " + USERNAME + " 对象属性-----------------" ); for (NamingEnumeration ae = answer.getAll(); ae.hasMore();) { Attribute attr = (Attribute)ae.next(); System.out.print(attr.getID()); for (NamingEnumeration e = attr.getAll(); e.hasMore(); System.out.println(" : " + e.next())); } } catch (Exception e) { System.out.println("Read Fail : " + USERNAME + " Object 对象不存在!" ); } try { Attributes answer = context.getAttributes(USERNAME, attrIDs); System.out.println("\n----------------- 获取对象指定属性 -----------------" ); for (NamingEnumeration ae = answer.getAll(); ae.hasMore();) { Attribute attr = (Attribute)ae.next(); System.out.print(attr.getID()); for (NamingEnumeration e = attr.getAll(); e.hasMore(); System.out.println(" : " + e.next())); } } catch (Exception e) { System.out.println("Read Fail : " + USERNAME + " Object 对象不存在!" ); } } catch (Exception e) { System.out.println("Login failed : " + e.getMessage()); } finally { try { if (context != null ) { context.close(); context = null ; } tbl.clear(); } catch (Exception e) { System.out.println("Exception happened." + e.getMessage()); } } } }
执行结果:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 --------------Show Env Setting -------------- ldap://10.10.107.245:389/dc=WeiyiGeek,dc=com,dc=cn com.sun.jndi.ldap.LdapCtxFactory cn=admin,dc=WeiyiGeek,dc=com,dc=cn simple WeiyiGeek --------------Login Verification LDAP ---------- Login Successful! 登录成功 Login Verification LDAP -------------- 枚举 查询对象 ---------- cn=User: cn=User,dc=WeiyiGeek,dc=com,dc=cn: com.sun.jndi.ldap.LdapCtx@5e9f23b4 cn=admin: cn=admin,dc=WeiyiGeek,dc=com,dc=cn: com.sun.jndi.ldap.LdapCtx@4783da3f ou=Development: ou=Development,dc=WeiyiGeek,dc=com,dc=cn: com.sun.jndi.ldap.LdapCtx@378fd1ac -----------------获取 cn=WeiyiGeek,ou=Development 对象属性----------------- sn : WeiyiGeek userPassword : [B@49097b5d loginShell : /bin/bash uidNumber : 1000 gidNumber : 500 displayName : 唯一极客 mail : test @weiyigeek.top objectClass : inetOrgPerson : posixAccount : top uid : weiyigeek cn : WeiyiGeek homeDirectory : /home/users/weiyigeek ----------------- 获取对象指定属性 ----------------- mail : test @weiyigeek.top displayName : 唯一极客 uidNumber : 1000 sn : WeiyiGeek
其它博主的代码:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 package com.example.ldap; import java.util.Hashtable;import java.util.Random; import javax.naming.AuthenticationException; import javax.naming.Context; import javax.naming.NamingEnumeration; import javax.naming.NamingException; import javax.naming.directory.BasicAttribute; import javax.naming.directory.BasicAttributes; import javax.naming.directory.SearchControls; import javax.naming.directory.SearchResult; import javax.naming.ldap.Control; import javax.naming.ldap.InitialLdapContext; import javax.naming.ldap.LdapContext; public class LDAPAuthentication { private final String URL = "ldap://10.0.43.206:389/" ; private final String BASEDN = "ou=people,dc=youedata,dc=com" ; private final String FACTORY = "com.sun.jndi.ldap.LdapCtxFactory" ; private LdapContext ctx = null ; private final Control[] connCtls = null ; private void LDAP_connect () { Hashtable<String, String> env = new Hashtable<String, String>(); env.put(Context.INITIAL_CONTEXT_FACTORY, FACTORY); env.put(Context.PROVIDER_URL, URL + BASEDN); env.put(Context.SECURITY_AUTHENTICATION, "simple" ); String root = "cn=admin,dc=youedata,dc=com" ; env.put(Context.SECURITY_PRINCIPAL, root); env.put(Context.SECURITY_CREDENTIALS, "youedata520" ); try { ctx = new InitialLdapContext(env, connCtls); System.out.println( "LDAP_connect连接成功" ); } catch (javax.naming.AuthenticationException e) { System.out.println("连接失败:" ); e.printStackTrace(); } catch (Exception e) { System.out.println("连接出错:" ); e.printStackTrace(); } } private void closeContext () { if (ctx != null ) { try { ctx.close(); } catch (NamingException e) { e.printStackTrace(); } } } private String getUserDN (String uid) { String userDN = "" ; LDAP_connect(); try { SearchControls constraints = new SearchControls(); constraints.setSearchScope(SearchControls.SUBTREE_SCOPE); NamingEnumeration<SearchResult> en = ctx.search("" , "uid=" + uid, constraints); if (en == null || !en.hasMoreElements()) { System.out.println("未找到该用户" ); } while (en != null && en.hasMoreElements()) { Object obj = en.nextElement(); if (obj instanceof SearchResult) { SearchResult si = (SearchResult) obj; userDN += si.getName(); userDN += "," + BASEDN; } else { System.out.println(obj); } } } catch (Exception e) { System.out.println("查找用户时产生异常。" ); e.printStackTrace(); } return userDN; } public boolean authenricate (String UID, String password) { boolean valide = false ; String userDN = getUserDN(UID); try { ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, userDN); ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, password); ctx.reconnect(connCtls); System.out.println(userDN + " 验证通过" ); valide = true ; } catch (AuthenticationException e) { System.out.println(userDN + " 验证失败" ); System.out.println(e.toString()); valide = false ; } catch (NamingException e) { System.out.println(userDN + " 验证失败" ); valide = false ; } closeContext(); return valide; } private boolean addUser (String usr, String pwd) { try { LDAP_connect(); BasicAttributes attrsbu = new BasicAttributes(); BasicAttribute objclassSet = new BasicAttribute("objectclass" ); String str = new Random().nextInt(10000 ) + "" ; objclassSet.add("inetOrgPerson" ); objclassSet.add("top" ); objclassSet.add("posixAccount" ); attrsbu.put(objclassSet); attrsbu.put("sn" , usr); attrsbu.put("cn" , usr); attrsbu.put("uid" , usr); attrsbu.put("mail" , "450416064@qq.com" ); attrsbu.put("gidNumber" , str); attrsbu.put("uidNumber" , str); attrsbu.put("homeDirectory" , "/home/account" ); attrsbu.put("userPassword" , pwd); ctx.createSubcontext("uid=" + usr , attrsbu); System.out.println("======================>" + usr + "添加成功" ); return true ; } catch (NamingException ex) { ex.printStackTrace(); } closeContext(); return false ; } public static void main (String[] args) { LDAPAuthentication ldap = new LDAPAuthentication(); ldap.LDAP_connect(); ldap.addUser("qq1111" ,"123456" ); if (ldap.authenricate("qq1111" , "123456" ) == true ){ System.out.println( "该用户认证成功" ); } } }
Java连接LDAP-JNDI参考: