快盘下载:好资源、好软件、快快下载吧!
快盘排行|快盘最新
[TOC]
由于其公司内部都内部各种运维系统等,当每个新员工入职就需要一个挨一个的登录到每个系统的后台给新员工开通账号,设置密码,然后员工离职还得去到每个系统后台去关闭账号,想想多浪费时间那么能不能维护一套账号,对所有系统生效呢? 当然有那就是LDAP。
在深入学习LDAP协议之前我们需要了解什么是目录服务?
1.描述:目录服务是一个特殊的数据库,用来保存描述性的、基于属性的详细信息,支持过滤功能。如:人员组织管理,电话簿,地址簿。 2.特点:是动态的,灵活的,易扩展的。 3.目录是一个为查询、浏览和搜索而优化的数据库,它成树状结构组织数据,类似文件目录一样。
答:维基百科:它是一个轻型目录访问协议(英文:Lightweight Directory Access Protocol,缩写:LDAP,/ˈɛldæp/)是一个开放的,中立的,工业标准的应用协议,通过IP协议提供访问控制和维护分布式信息的目录信息。LDAP目录服务是由目录数据库和一套访问协议组成的系统,它是基于X.500标准的轻量级目录访问协议有时被称为X.500-lite。也是IETF下的一项标准,目前最新的RFC为 RFC4510 ;
比如 DNS 协议便是一种最被广泛使用的目录服务。
答:构建一个统一的账号管理、身份验证平台,实现SSO单点登录机制,即用户可以在多个应用服务系统中使用同一个密码,通常用于公司内部网站的登录以及域内机器登陆管理;
答:LDAP是开放的Internet标准,支持跨平台的Internet协议,在业界中得到广泛认可的,并且市场上或者开源社区上的大多产品都加入了对LDAP的支持,因此对于这类系统,不需单独定制,只需要通过LDAP做简单的配置就可以与服务器做认证交互;>简单粗暴,可以大大降低重复开发和对接的成本
1.主要不同之处在于数据的组织方式,它是一种有层次的、树形结构。所有条目的属性的定义是对象类object class的组成部分,并组成在一起构成schema;那些在组织内代表个人的schema被命名为white pages schema。 2.数据库内的每个条目都与若干对象类联系,而这些对象类决定了一个属性是否为可选和它保存哪些类型的信息。属性的名字一般是一个易于记忆的字符串,例如用cn为通用名(common name)命名,而”mail”代表e-mail地址。 例如mail属性包含值“user@example.com”。
简单了解下基于 LDAP 协议的产品有一下:
厂商
产品
简介
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 (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 配置
{ "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|--> | 值1 .... 值n| ------------- --------------
(2) 命名模型
描述:LDAP中的命名模型即LDAP中的条目定位方式,在LDAP中每个条目均有自己的DN 是该条目在整个树中的唯一名称标识;
LDAP树形结构的构成方式而一般有两种方式:体现到LDIF的详细信息
#传统方式 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种操作:
(4) 安全模型
描述:LDAP中的安全模型主要通过身份认证、安全通道和访问控制来进行实现;
描述:由于LDAP主要运用于统一身份认证,而其主要是改变原有的认证策略,使需要认证的软件都通过LDAP进行认证,在统一身份认证之后,用户的所有信息都存储在AD Server中。终端用户在需要使用公司内部服务的时候,都需要通过AD服务器的认证。
WeiyiGeek.LDAP身份认证
那么程序中是如何访问的呢?
我们以PHP脚本作为例子如下:
$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);
描述:在上文中我们对LDAP产品进行列举,在厂商得持续开发迭代下提供LDAP服务的软件有很多商业上获得成功的,其中以MS的AD和Redhat的NDS(Netscape directory server)使用最为广泛,而开源领域则是OpenLdap(全文实验也是基于此版本);
OpenLDAP是轻型目录访问协议(Lightweight Directory Access Protocol,LDAP)的自由和开源的实现,在其OpenLDAP许可证下发行,并已经被包含在众多流行的Linux发行版中。 官网:http://www.openldap.org
它主要包括下述4个部分:
端口说明:
端口号
备注
389
未加SSL缺省端口(明文数据传输)
689
SSL加密端口
636
加密监听端口(加密数据传输)
环境准备:
#SeLinux设为disabled setenforce 0 sed -i "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config #同步系统时间 ntpdate time.nist.gov #Firewalld防火墙设置 #镜像源设置 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 #创建缓存 #安装OpenLDAP的相关(compat-openldap包与主从有很大的关系) yum -y install openldap openldap-clients openldap-servers openldap-servers-sql openldap-devel migrationtools yum -y install compat-openldap #通过查看安装了哪些包 rpm -qa |grep openldap #查看OpenLDAP版本 slapd -VV #初始化OpenLDAP的配置 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 # 创建slapd.conf #salpd.conf 配置修改:[修改或添加-如下图所示] #把配置文件中:dc=my-domain,dc=com 修改成自己的域名; dc=58jb,dc=org ;cn=Manager就是管理员账号; database bdb suffix "dc=weiyigeek,dc=com,dc=cn" #基础DN checkpoint 1024 15 rootdn "cn=admin,dc=weiyigeek,dc=com,dc=cn" #管理员admin DN loglevel Stats #增加一个日志记录 cachesize 1000 #缓存大小 #设置OpenLDAP管理员密码,拷贝这个到/etc/openldap/slapd.conf里,指定rootpw属性必须顶格写,而且与后面的密码文件用Tab键隔开,并修改对应序列。 slappasswd -s 123456 # {SSHA}JTudNsYrtbsksTdjxe4bFSwbrt1cF+LD
注意:其中cn=root中的root表示OpenLDAP管理员的用户名,而olcRootPW表示OpenLDAP管理员的密码。
WeiyiGeek.salpd.conf
修改配置文件完成后进行验证配置文件以及权限设置
#先检测/etc/openldap/slapd.conf是否有错误 slaptest -f /etc/openldap/slapd.conf #授权数据文件,更改文件的所属 chown -R ldap:ldap /var/lib/ldap/ #重启slapd生成配置文件,接着回到检测/etc/openldap/slapd.conf是否有错误 /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/openldap/slapd.d/cn=config/olcDatabase={1}mdb.ldif #重启到这里为止,OpenLDAP服务端基本上完成了 /etc/init.d/slapd restart #检查ldap的连接测试,输入密码后返回信息:No such object (32) 表示成功! 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.
注意:每次修改了配置文件,所有得重新生成配置文件的信息;
参考文档:
描述:由于openldap的osixia的镜像所内置的缺省的dc即LDAP结构采用互联网域名方式; Docker镜像:https://github.com/osixia/docker-openldap
建立数据持久化目录:
mkdir -p /opt/OpenLDAP/{config,database}
docker-compose.yml (v1.3.0) 安装OpenLDAP版本:Jul 30 2019 16:24:19
#OpenLDAP 环境部署 #mkdir -p /opt/OpenLDAP/{config,database} 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
环境变量说明:
默认登录用户名: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)
拉取并运行镜像:
docker-compose config #验证yaml文件 docker-compose up -d #拉取和后台运行容器 #如容器间不能正常通信请查看防火墙是否allow;
容器内部查询:
#Docker安装版本查询,如果您是基于CentOS系列构建得请采用rpm -qa 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: @(#) $OpenLDAP: ldapsearch (Jul 30 2019 16:24:19) $ Debian OpenLDAP Maintainers <pkg-openldap-devel@lists.alioth.debian.org> (LDAP library: OpenLDAP 20448) #使用slapcat来查看相关的用户信息,缺省方式下已经有cn=admin的用户信息(貌似不需要认证直接显示用户密码) root@4a1a157c5e70:/$slapcat -v # id=00000001 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#000000#000#000000 modifiersName: cn=admin,dc=WeiyiGeek,dc=com,dc=cn modifyTimestamp: 20200408033527Z
描述:Yum安装ldap后的配置文件说明:
#OpenLDAP相关配置文件(主配置文件,管理员dn,密码,日志配置,权限等设置) /etc/openldap/slapd.conf /etc/openldap/slapd.d/* # 这下面是slapd.conf配置信息生成的文件,每修改一次配置信息,这里的东西就要重新生成 /etc/openldap/schema/* # OpenLDAP的schema存放的地方 /var/lib/ldap/* # OpenLDAP的数据文件 /usr/share/openldap-servers/slapd.conf.obsolete # 模板配置文件 /usr/share/openldap-servers/DB_CONFIG.example # 模板数据库配置文件
openLDAP的打开日志信息:
#设置LDAP日志级别为-2记录Info信息 $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/ #在/etc/rsyslog.conf文件中加入 local4.* /var/log/slapd/slapd.log #重启slapd以及rsyslog服务 /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.普通用户只能修改自己的密码,别的权限都没有;
# access to attrs=userPassword通过属性找到访问范围密码, # 超级管理员也就是我们ldap配置文件里写的rootdn:"cn=admin,dc=weiyigeek,dc=top"有写(write)权限; # 由于管理员可能不止一个,我创建了个管理员组"ou=Admin,dc=weiyigeek,dc=top"把管理员统一都放到这个组下,管理员组下的所有用户(dn.children)有写权限; # 匿名用户(anonymous)要通过验证(auth); # 自己(self)有对自己密码的写(write)权限,其他人(*)都没有权限(none). 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 * 所有其他属性, # 超级管理员rootdn:"cn=admin,dc=weiyigeek,dc=top"有写(write)权限; # 管理员"ou=Admin,dc=weiyigeek,dc=top"成员有写(write)权限; # 其他人(*)只有读(read)权限 access to * by dn="cn=admin,dc=weiyigeek,dc=top" write by dn.children="ou=Admin,dc=weiyigeek,dc=top" write by * read
基础示例:
#ldap版本信息 $slapd -VV #确认配置文件信息是否正确 $slaptest # config file testing succeeded #查看相关的用户信息(缺省方式 cn=admin) $slapcat -v $slapcat -n 0 #查看不同的数据库id数据{0,1}
描述:LDAP一般用于SSO的单点登录,所以其他机器能够连接进行验证是最基础的,客户端安装openldap-client包进行登录LDAP并进行查询使用;
yum install openldap-clients
基础语法:
-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 过滤条件符:
#(1)查询得到的实际上是LDIF文件格式中的内容; $ldapsearch -x -H ldap://localhost:389 -b "dc=WeiyiGeek,dc=com,dc=cn" -D "cn=admin,dc=WeiyiGeek,dc=com,dc=cn" -w WeiyiGeek # extended LDIF # LDAPv3 # base <dc=WeiyiGeek,dc=com,dc=cn> with scope subtree # filter: (objectclass=*) # requesting: ALL # weiyigeek.top dn: dc=WeiyiGeek,dc=com,dc=cn objectClass: top objectClass: dcObject objectClass: organization o: WeiyiGeek dc: WeiyiGeek # WeiyiGeek, Development, weiyigeek.top 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 #(2)指定DN进行查询(指定过滤条件) -b SearchDN $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 WeiyiGeek # extended LDIF # LDAPv3 # base <cn=Weiyi,ou=Development,dc=WeiyiGeek,dc=com,dc=cn> with scope subtree # filter: (objectclass=*) # requesting: AL # Weiyi, Development, weiyigeek.top dn: 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 result search: 2 result: 0 Success # numResponses: 2 # numEntries: 1 #(3)模糊匹配条目可以采用通配符进行查找,同时可以结合>和<以及~匹配查找等方式实现更加快速和便捷地定位。 #常用的方式还可以使用cn=*或者cn=admin这样进行指定信息进行过滤 $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=*" # Development, weiyigeek.top dn: ou=Development,dc=WeiyiGeek,dc=com,dc=cn ou: Development objectClass: organizationalUnit objectClass: top # People, weiyigeek.top dn: ou=People,dc=WeiyiGeek,dc=com,dc=cn objectClass: top objectClass: organizationalUnit ou: People # search result search: 2 result: 0 Success # numResponses: 3 # numEntries: 2 #(4) 指定返回信息(类似与在SQL中写Select并且可以采用指定规则排序) #我们只返回创建的uid的 mail/uid/title/cn/sn $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 mail # Weiyi, Development, weiyigeek.top dn: cn=Weiyi,ou=Development,dc=WeiyiGeek,dc=com,dc=cn sn: Weiyi cn: weiyi uid: weiyi uidNumber: 1001 mail: weiyi@weiyigeek.top #(5) 服务端下查看openldap服务下的dn配置 $ldapsearch -Q -LLL -Y EXTERNAL -H ldapi:/// -b cn=config dn dn: cn=config dn: cn=module{0},cn=config dn: cn=schema,cn=config #(6) 指定过滤条件查询 $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 #Client 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加密后密匙
12:20:25.644 atob("e1NTSEF9TE5GaU0rZVZXNGlR43FDdzQ5UzRMNjRlb2xjMjY5OU4=") 12:20:25.745 "{SSHA}LNFiM8eVW4iQGq2w49S4L74eolc2699N"
2.过滤条件实例
描述:该命令用于进行数据添加,实际上ldapadd只是采用了一个软链接指向ldapmodify,所以此处我们统一进行说明;
命令参数:
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文件内容:
cat > weiyigeek.ldif <<END #添加Organisation Unit 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 #ldapmodify ldif文件添加、修改(添加W字段) 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 #移动条目&修改UID 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
基础实例:
#指定ldif文件进行添加用户(ldapadd) $ldapadd -H ldap://127.0.0.1:389 -D "cn=admin,dc=WeiyiGeek,dc=com,dc=cn" -w WeiyiGeek -f weiyigeek.ldif adding new entry "cn=Weiyi,ou=Development,dc=WeiyiGeek,dc=com,dc=cn" #指定ldif文件进行添加用户 (ldapmodify:方式1,采用-a参数) $ldapmodify -a -x -H ldap://127.0.0.1:389 -D "cn=admin,dc=WeiyiGeek,dc=com,dc=cn" -w WeiyiGeek -f weiyigeek.ldif adding new entry "cn=Weiyi,ou=Development,dc=WeiyiGeek,dc=com,dc=cn" #指定ldif文件进行添加用户、修改 (ldapmodify:方式2需要在ldif文件中加入 changetype: add ) $ldapmodify -x -H ldap://127.0.0.1:389 -D "cn=admin,dc=WeiyiGeek,dc=com,dc=cn" -w WeiyiGeek -f weiyigeek.ldif adding new entry "ou=People,dc=WeiyiGeek,dc=com,dc=cn" adding new entry "cn=Weiyi,ou=Development,dc=WeiyiGeek,dc=com,dc=cn" #指定ldif文件进行修改、增加字段、删除字段、移动条目、删除条目 $ldapmodify -a -x -H ldap://127.0.0.1:389 -D "cn=admin,dc=WeiyiGeek,dc=com,dc=cn" -w WeiyiGeek -f Demo1.ldif 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 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"
Ask:不行,其报错信息:ldapmodify: modify operation type is missing at line 2, entry "cn=Weiyi,ou=Development,dc=WeiyiGeek,dc=com,dc=cn",需要加上-a参数即可;
$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"
描述:LDAP有三种方式可以进行修改密码即
ldappasswd 参数:
-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)ldappasswd不指定密码的情况下它会自动生成一个密码(实际上是采用admin用户重置其它用户的密码),并添加到userPassword字段之中,之后可以采用前面ldapsearch进行输入此密码进行验证; $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 #(2) ldappasswd使用-s指定修改密码,在已知用户密码前提下进行修改现有密码 $ldappasswd -x -h 127.0.0.1 -p 389 -D "uid=WeiyiTest,ou=People,dc=WeiyiGeek,dc=com,dc=cn" -w XJbHKyRF -s newpass123456
采用 docker 容器部署LDAPAccountManager:
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同一个网络即可]
简单置流程:
描述: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访问
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
账号:cn=admin,dc=weiyigeek,dc=top 密码:weiyigeek
Step2.登录phpLdapAdmin添加组以及ldap账号流程步骤如下:
Step3.采用创建的账号进行登陆LDAP;
DN:cn=WeiyiGeek,ou=Development,dc=weiyigeek,dc=com,dc=cn 密码:123456
描述:Ldap Admin是一个用于LDAP目录管理的免费Windows LDAP客户端和管理工具。此应用程序允许您在LDAP服务器上浏览,搜索,修改,创建和删除对象。它还支持更复杂的操作,例如目录复制和在远程服务器之间移动,并扩展常用编辑功能以支持特定对象类型(例如组和帐户), 支持多类型系统:Winndows&Linux 官网:http://www.ldapadmin.org/
下载安装LDAP Admin客户端,新增连接如下:
描述: 设计用来和各种LDAP服务器进行交互操作,提供了一个使用方便的客户端操作平台。除了Apache DS之外,诸如OpenLdap也可以很好地进行交互,对于不习惯不喜欢命令行方式的用户,Apache Directory Studio也是选择之一。
官方网址:http://directory.apache.org/studio/ 支持OS:跨平台,支持MacOS/Windows/Linux 下载地址:http://directory.apache.org/studio/downloads.html
导入与导出
入坑解决:
描述:采用migrationtools工具包,实现导入系统账号的相关信息;
#下载工具包 yum -y install migrationtools #修改migrationtools的配置文件 vim /usr/share/migrationtools/migrate_common.ph 70 # Default DNS domain 71 $DEFAULT_MAIL_DOMAIN = "weiyigeek.top"; 72 73 # Default base 74 $DEFAULT_BASE = "dc=WeiyiGeek,dc=com,dc=cn"; #生成基础的数据文件(可以根据需求把不需要的去掉) /usr/share/migrationtools/migrate_base.pl > base.ldif $more base.ldif # dn: dc=WeiyiGeek,dc=com,dc=cn # dc: WeiyiGeek # objectClass: top # objectClass: domain # dn: ou=Hosts,dc=WeiyiGeek,dc=com,dc=cn # ou: Hosts # objectClass: top # objectClass: organizationalUnit #把base.ldif导入OpenLDAP的数据文件(-c 强制导入) $ldapadd -x -c -H ldap://127.0.0.1 -D "cn=admin,dc=WeiyiGeek,dc=com,dc=cn" -w WeiyiGeek -f /root/base.ldif # adding new entry "dc=WeiyiGeek,dc=com,dc=cn" # adding new entry "ou=Hosts,dc=WeiyiGeek,dc=com,dc=cn" # adding new entry "ou=Rpc,dc=WeiyiGeek,dc=com,dc=cn" # adding new entry "ou=Services,dc=WeiyiGeek,dc=com,dc=cn" # adding new entry "nisMapName=netgroup.byuser,dc=WeiyiGeek,dc=com,dc=cn" # adding new entry "ou=Mounts,dc=WeiyiGeek,dc=com,dc=cn" # adding new entry "ou=Networks,dc=WeiyiGeek,dc=com,dc=cn" # adding new entry "ou=People,dc=WeiyiGeek,dc=com,dc=cn" # adding new entry "ou=Group,dc=WeiyiGeek,dc=com,dc=cn" # adding new entry "ou=Netgroup,dc=WeiyiGeek,dc=com,dc=cn" # adding new entry "ou=Protocols,dc=WeiyiGeek,dc=com,dc=cn" # adding new entry "ou=Aliases,dc=WeiyiGeek,dc=com,dc=cn" # adding new entry "nisMapName=netgroup.byhost,dc=WeiyiGeek,dc=com,dc=cn"
WeiyiGeek.导入系统账号的相关信息
创建两个测试用户及用户组,并修改密码
groupadd ldaptest1 groupadd ldaptest2 useradd -g ldaptest1 ldaptest1 useradd -g ldaptest2 ldaptest2 echo 123456 | passwd --stdin ldaptest1 echo password | passwd --stdin ldaptest2
将刚创建的两个用户导入至openldap数据文件
grep ldaptest /etc/passwd > users grep ldaptest /etc/group > groups $cat users groups ldaptest1:x:1001:1001::/home/ldaptest1:/bin/bash ldaptest2:x:1002:1002::/home/ldaptest2:/bin/bash ldaptest1:x:1001: ldaptest2:x:1002:
使用migrationtools将两个临时用户生成ldif文件
/usr/share/migrationtools/migrate_passwd.pl users > users.ldif cat users.ldif # dn: uid=ldaptest1,ou=People,dc=WeiyiGeek,dc=com,dc=cn # uid: ldaptest1 # cn: ldaptest1 # objectClass: account # objectClass: posixAccount # objectClass: top # objectClass: shadowAccount # userPassword: {crypt}$6$Rr.3Z1X8$fmyCvoFFaTw74GVO.G3okx765i3K2CUaEK/Uu0cyNc8/Xn2HHM1DelVM3nmgDNsQWEZGpLCNUtp.faXvspiff1 # shadowLastChange: 18363 # shadowMin: 0 # shadowMax: 99999 # shadowWarning: 7 # loginShell: /bin/bash # uidNumber: 1001 # gidNumber: 1001 # homeDirectory: /home/ldaptest1 /usr/share/migrationtools/migrate_group.pl groups > groups.ldif cat groups.ldif # dn: cn=ldaptest1,ou=Group,dc=WeiyiGeek,dc=com,dc=cn # objectClass: posixGroup # objectClass: top # cn: ldaptest1 # userPassword: {crypt}x # gidNumber: 1001
4.把用户导入至openLDAP的数据文件并查询导入的数据
ldapadd -x -H ldap://127.0.0.1 -D "cn=admin,dc=WeiyiGeek,dc=com,dc=cn" -w WeiyiGeek -f users.ldif # adding new entry "uid=ldaptest1,ou=People,dc=WeiyiGeek,dc=com,dc=cn" # adding new entry "uid=ldaptest2,ou=People,dc=WeiyiGeek,dc=com,dc=cn" ldapadd -x -H ldap://127.0.0.1 -D "cn=admin,dc=WeiyiGeek,dc=com,dc=cn" -w WeiyiGeek -f groups.ldif # adding new entry "cn=ldaptest1,ou=Group,dc=WeiyiGeek,dc=com,dc=cn" # adding new entry "cn=ldaptest2,ou=Group,dc=WeiyiGeek,dc=com,dc=cn"
描述:我们可以使用Java中使用javax.naming可以对Ldap用户信息进行验证,使用这点可以完成SSO之类功能的集成;
简单的基础示例:
//登陆与验证LDAP 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; /** * @Descr 使用Javax.naming验证LDAP登录 * @author WeiyiGeek * javac ldaptest.java * java ldaptest */ 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>(); //JNDI //为初始化上下文选择服务提供者 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 "); //举上下文有两个方法 System.out.println("-------------- 枚举 查询对象 ---------- "); //方式1: // NamingEnumeration list = context.list("ou=Development"); //指定对象 // while (list.hasMore()) { // NameClassPair nc = (NameClassPair)list.next(); // System.out.println(nc); // } //方式2: 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(" -----------------获取 "+ 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(" ----------------- 获取对象指定属性 -----------------"); 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 { //销毁context上下文对象 try { if (context != null) { context.close(); context = null; } tbl.clear(); } catch (Exception e) { System.out.println("Exception happened." + e.getMessage()); } } } }
执行结果:
--------------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
其它博主的代码:
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; /** * @author monkey * @date 2019-06-28 * @desc ldap demo */ 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("未找到该用户"); } // maybe more than one element 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"); //可以和数据库关联,做一个自增,比如mysql存起来 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参考:
Linux配置HTTP服务
用.NET做DDNS动态域名解析和SSL证书申请
使用Sublime开发微信小程序实现wxml, wxss代码高亮和语法提示
海康威视iVMS-4200校时、手动校时、定位校时、NTP校时四种方法任你选
网络水晶头标准制作线序和直通线、交叉线的检测方法
单模光纤和多模光纤都有哪些形状的接头
常说的E太网中的网线都哪些规格,怎么区别?
virtual box虚拟机安装Centos7教程
virtual box安装Centos7教程和常见问题说明
小马PE统维护工具制作与使用教程
JMAG-Designer 18安装破解教程
curl访问非安全的ssl证书问题
关于我们| 广告联络| 联系我们| 网站帮助| 免责声明| 软件发布
Copyright 2019-2029 【快快下载吧】 版权所有 快快下载吧 | 豫ICP备10006759号公安备案:41010502004165
声明: 快快下载吧上的所有软件和资料来源于互联网,仅供学习和研究使用,请测试后自行销毁,如有侵犯你版权的,请来信指出,本站将立即改正。