前沿

领导:Hi 小王,以前有没有接触过Ldap??

小王:啥?Ldap是啥?没接触过。

领导:那有没有使用过微软的AD?

小王;啥是AD?没有

领导:好吧,我简单说下,我们目前使用AD保存用户的信息,但是AD不是开源的,无法二次开发,使用起来不太方便,所以我们如果能找到一个同样支持Ldap协议的开源软件,那么就能通过对该开源软件进行二次开发,来满足我们的需要。具体让龙哥和你详细聊聊。

龙哥:巴拉巴拉

小王:太多新名词,没太明白,我先自己查查资料,了解下这些新的名词。

龙哥:好,有问题随时沟通。

正文

为了找到一个基于Ldap开源软件,而且还是熟悉的开发语言,进行二次开发,大体思考了下调研思路,先按照以下几个步骤:

1、Ldap协议是啥?

2、目前行业支持Ldap协议的产品有哪些?

3、这些软件是否有满足我们要求的?选择一个合适的软件。

4、下载开源项目及浏览其目录结构,了解子项目的大体功能。

5、找到启动类进行启动。

6、使用客户端登陆认证,根据用户名登陆是否能找到登陆入口?

7、阅读入口源码,并且以此为入口,找到增删改查的相关接口?

8、将登陆实现替换成目前使用的AD验证,也就是说,将内部的登陆验证,透传到正在使用的AD上,我们的开源项目只做入口、参数透传,不做正真验证。

9、部署到测试环境上。

10、暴露IP + 端口,进行验证。

思路明确后,我们只需要按照这个步骤进行调研,在该过程中,如果出现问题,随时做调整

Ldap协议介绍

它是基于X.500标准扽轻量级目录访问协议,是开发的Internet标准,支持跨平台的internet协议。

目录是一个为查询、浏览、搜索而优化的数据库,它成树状结构组织数据,类似文件目录一样。

目录数据库和关系型数据库不同,它有优异的读性能,但写性能差,并且没有事务处理,不适合存储修改频繁的数据。所以目录天生是用来查询的。

上述这段定义是摘抄自别的博客,很好的阐述了Ldap协议的特点,Ldap只是定义了协议,没有具体的实现,所有对其实现的产品都是支持Ldap协议的。

其他产品对其支持:

YAPI对其进行支持,通过配置Ldap的服务,能够通过Ldap进行登陆;

metabase对其进行支持,通过管理员配置Ldap参数,也能够通过Ldap进行登陆;

还有好多产品,我们这里就不一一列举了。

目前Ldap主要产品

SUNONE Directory Server、IBM Directory Server 、Novell Directory Server、Microsoft Active Directory上述3种产品都是不开源的,我们不能用,下面几个产品是开源的:Open Ldap:速度很快,但非主流应用、ApacheDs、OpenDJ、红帽目录服务器。

Ldap一些特征例如目录树概念、DC、OU、CN、SN、信息模型、命名模型、功能模型、安全模型等,大家上网搜搜,有很多文章在讲述,这里就不再阐述了。

选择一个开源软件:

选择的是ApacheDs,但是ApacheDs后端似乎存在损坏数据的问题,但是我们不会有这个问题,因为我们不用ApacheDs存储数据,只是作为一个入口及参数透传而已。

浏览开源项目目录结构,了解子项目的大体功能

下载源码包:

GitHub - apache/directory-server: Apache Directory Server

打开后发现一堆的子项目,看着头晕,但是我们只要弄明白2件事,入口类以及启动类,下面是打开后的目录结构:

从截图上可以看到,他的子项目还是比较多的

找到启动类进行启动

我们在标号为35的子项目中找到一个类:org.apache.directory.server.UberjarMain#main

从代码里看,貌似这个就是启动类,而且从pom文件里也能看出来应该是这个类

<mainClass>org.apache.directory.server.UberjarMain</mainClass>

那就试试呗,启动后发现报以下异常

Instance directory argument is missing

异常,看代码73行发现,他会获取一个目录,将该目录作为Ldap运行的时候存放一些文件的根目录,例如日志的输出、conf、partitions等,找到问题所在后,我们再启动的时候,在VM options配置instance.base.dir路径即可,配置完再次重启,发现正常启动,打印如下日志:

是否说明绑定的端口就是10389呢,我们通过ApacheDirectoryStudio客户端链接工具来验证,Hostname肯定是本地IP呗,验证成功,说明没问题,但是从截图中看到还有一个端口号10636,这个端口是干嘛的?

验证同样没问题,这2个端口有啥区别吗,既然这2个端口都生效,我们先猜猜,认证方式不可能是相同的,开源框架不会做这么无聊的事,是不是一个需要sasl认证,一个普通认证了,秉着一切问题都出至源码的理念,终于从server.xml中找到这2个ip的配置:

<ldapService id="ldapsService"enabled="true"enableLdaps="true"><tcpTransport><tcpTransport port="10636"/></tcpTransport><directoryService>#directoryService</directoryService>
</ldapService><ldapService id="ldapService"allowAnonymousAccess="false"saslHost="ldap.example.com"saslPrincipal="ldap/ldap.example.com@EXAMPLE.COM"searchBaseDn="ou=users,ou=system"maxTimeLimit="15000"maxSizeLimit="1000"><tcpTransport><tcpTransport port="10389" nbThreads="8" backLog="50"/></tcpTransport>

果然与我们开始猜想的一样。

使用客户端进行登陆,根据用户名登陆是否找到登陆入口

输入错误的用户名和秘密,查看日志,根据调用链是否能够找到入口?

从上图标注的序号可以看出,入口是标记为1的序号,通过一路跟踪代码发现,org.apache.directory.server.ldap.handlers.LdapRequestHandler#handle存在这个抽象方法,该抽象方法有10个实现类,包括绑定(登陆验证)、解绑、添加、修改、搜索、比较、删除、扩展等,我们从标号4也能看出来,登陆的时候调用的是BindRequestHandler,从而验证了我们的猜想。

阅读入口源码,并且以此我入口,找到增删改查的相关接口

这里就比较简单了,通过debug模式,可以查看到入参和调用轨迹

登陆校验接口

入参:

MessageType : BIND_REQUESTMessage ID : 1BindRequestVersion : '3'Name : 'uid=admin,ou=system'Simple authentication : '(omitted-for-safety)'

调用轨迹:

org.apache.directory.server.ldap.LdapProtocolHandler.messageReceived -》org.apache.mina.handler.demux.DemuxingIoHandler.messageReceived -》
org.apache.directory.server.ldap.handlers.LdapRequestHandler.handleMessage
org.apache.directory.server.ldap.handlers.request.BindRequestHandler.handle -》
org.apache.directory.server.ldap.handlers.request.BindRequestHandler#handleSimpleAuth

搜索:

入参:

MessageType : SEARCH_REQUEST
Message ID : 22SearchRequestbaseDn : 'ou=schema'filter : '(objectClass=*)'scope : single leveltypesOnly : falseSize Limit : 1000Time Limit : no limitDeref Aliases : deref Alwaysattributes : 'hasSubordinates', 'objectClass'

调用轨迹:

org.apache.directory.server.ldap.LdapProtocolHandler.messageReceived-》org.apache.mina.handler.demux.DemuxingIoHandler.messageReceived -》org.apache.directory.server.ldap.handlers.LdapRequestHandler.handleMessageorg.apache.directory.server.ldap.handlers.request.AddRequestHandler#handle

添加用户:

入参:

MessageType : ADD_REQUEST
Message ID : 39Add Request :
Entrydn: cn=李四+uid=si.li+description=李四+sn=李+givenName=四+displayName=李四+mail=lisi@163.com+userPassword=123123,ou=laoniantuan,dc=example,dc=comobjectClass: inetOrgPersonobjectClass: organizationalPersonobjectClass: personobjectClass: topuid: si.limail: lisi@163.comgivenName: 四displayName: 李四description: 李四cn: 李四sn: 李
userPassword: 0x31 0x32 0x33 0x31 0x32 0x33

调用轨迹:

org.apache.directory.server.ldap.LdapProtocolHandler.messageReceived-》org.apache.mina.handler.demux.DemuxingIoHandler.messageReceived -》org.apache.directory.server.ldap.handlers.LdapRequestHandler.handleMessageorg.apache.directory.server.ldap.handlers.request.AddRequestHandler#handle

删除节点:

入参:

MessageType : DEL_REQUEST
Message ID : 54Del requestEntry : 'ou=laoniantuan,dc=example,dc=com'

调用轨迹:

org.apache.directory.server.ldap.LdapProtocolHandler.messageReceived-》org.apache.mina.handler.demux.DemuxingIoHandler.messageReceived -》org.apache.directory.server.ldap.handlers.LdapRequestHandler.handleMessageorg.apache.directory.server.ldap.handlers.request.DeleteRequestHandler#handle

修改节点:

入参:

MessageType : MODIFYDN_REQUEST
Message ID : 13ModifyDN ResponseEntry : 'ou=laoniantuan,dc=example,dc=com'New Rdn : 'ou=laorentuan'Delete old Rdn : trueNew superior : 'dc=example,dc=com'

调用轨迹:

org.apache.directory.server.ldap.LdapProtocolHandler.messageReceived
-》org.apache.mina.handler.demux.DemuxingIoHandler.messageReceived -》
org.apache.directory.server.ldap.handlers.LdapRequestHandler.handleMessage
org.apache.directory.server.ldap.handlers.request.ModifyRequestHandler#handle

移动节点:

入参:

MessageType : MODIFYDN_REQUEST
Message ID : 24ModifyDN ResponseEntry : 'cn=李四+description=李四+displayName=李四+givenName=四+mail=lisi@163.com+sn=李+uid=si.li,ou=qingniantuan,dc=example,dc=com'New Rdn : 'cn=李四+description=李四+displayName=李四+givenName=四+mail=lisi@163.com+sn=李+uid=si.li'Delete old Rdn : trueNew superior : 'ou=laoniantuan,dc=example,dc=com'

调用轨迹:

org.apache.directory.server.ldap.LdapProtocolHandler.messageReceived
-》org.apache.mina.handler.demux.DemuxingIoHandler.messageReceived -》
org.apache.directory.server.ldap.handlers.LdapRequestHandler.handleMessage
org.apache.directory.server.ldap.handlers.request.ModifyDnRequestHandler#handle

将ApacheDs校验登陆的部分透传到AD服务器,根据代码调用轨迹,只需要在org.apache.directory.server.ldap.handlers.request.BindRequestHandler#handleSimpleAuth类中调用AD服务器的链接验证即可,核心代码如下:

public static int checkUser(String username, String password) {if (StringUtils.isAnyEmpty(username, password)) {return Constants.CHECK_STATUS_PARAM_EMPTY;}String property = System.getProperty("ldap.server.url");Properties properties = System.getProperties();System.out.println(properties);Hashtable<String, String> env = new Hashtable<>();DirContext ctx = null;env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");env.put(Context.PROVIDER_URL, CON_URL);env.put(Context.SECURITY_AUTHENTICATION, SECURITY_AUTHENTICATION_SIMPLE);env.put(TIMEOUT, TIMEOUT_VALUE);// 连接超时设置为2秒//env.put(Context.SECURITY_PRINCIPAL, EMAIL_SUBFIX + username);env.put(Context.SECURITY_PRINCIPAL, username);env.put(Context.SECURITY_CREDENTIALS, password);try {// 链接ldaplong start = System.currentTimeMillis();ctx = new InitialDirContext(env);LOG.info("认证成功 用户:{},cost:{}", username, System.currentTimeMillis() - start);return Constants.CHECK_STATUS_PASS;} catch (CommunicationException var) {}

再模拟ApacheDs返回的格式,返回给上游即可。

这里需要注意的是,后端接收到的密码格式类似于[115, 101, 99, 114, 101, 116]形式,开始很闷,这是啥东西,难道是将密码加密了,但是查看源码,没有找到解密的地方,最后灵光一现可能是密码的ascii码,我们通过简单的转译就能得到密码的明文,猜想也是对的,遇到这个问题没有立马想出来,原因是计算机基础不踏实,大脑里没有明文与ascii码的对照关系。

部署到测试环境:

因为apacheDs是maven项目,执行maven install命令,将打包后的jar包部署到测试环境,记得要在VM options中添加instance.base.dir路径,执行 java -jar xxxx.jar 命令

暴露IP + 端口 进行验证:

验证过程可以通过客户端,也可以将其提供给其他支持Ldap协议认证的软件,我是通过将测试环境IP + 端口提供给Jira服务来验证,结果肯定是没问题啦。

参考:

https://github.com/apache/directory-server

Ldap探索之路之directory-server(ApacheDs二次开发)相关推荐

  1. RedHat Directory Server 8.2 Installation Guide

    RHDS是一套基于openldap的目录服务,当前可在官方下载的最新版本是8.2,不过下载下来的都是源代码rpm软件包,需要编译成二进制rpm软件包.我这里已经编译好了,总共12个软件包,已经包含了依 ...

  2. 启动weblogic的错误:Could not obtain an exclusive lock to the embedded LDAP data files directory...

    http://hi.baidu.com/kaisep/item/0e4bf6ee5da001d1ea34c986 源地址 启动weblogic的错误:Could not obtain an exclu ...

  3. 服务器3个w目录文件夹,第 4 章 目录服务器条目 (Sun Java System Directory Server Enterprise Edition 6.2 管理指南)...

    第 4 章 目录服务器条目 本章讨论如何管理目录中的数据条目.此外,还介绍如何设置引用以及如何加密属性值. 除非定义了相应的访问控制指令 (Access Control Instruction, AC ...

  4. 服务器禁止修改目录,目录服务器限制 (Sun Java System Directory Server Enterprise Edition 6.2 发行说明)...

    不要手动更改文件权限. 在某些情况下,对已安装的 Directory Server Enterprise Edition 产品文件的权限进行更改可能会导致软件无法正常运行.只能按照产品文档中的说明或 ...

  5. centos directory server

    centos directory server http://www.aliyun.com/zixun/content/3_12_517262.html CentOS系统安装Directory Ser ...

  6. LDAP(Lightweight Directory Access Protocol)介绍

    LDAP(Lightweight Directory Access Protocol)介绍 LDAP是个啥? LDAP基本结构及术语 基本结构 条目(Entry) 识别名(DN) 相对识别名(RDN) ...

  7. ibm tivoli_IBM Tivoli Directory Server 6.0的SSL配置

    介绍 安全套接字层(SSL)是一种行业标准协议,它使用对称密钥和公用密钥加密机制在Internet上提供安全通信. SSL协议在TCP / IP之上和应用协议(例如轻型目录访问协议(LDAP)和超文本 ...

  8. ibm tivoli_解决Tivoli Directory Server同步问题的方法

    ibm tivoli IBM®Tivoli®Directory Server(TDS)是功能强大且权威的企业目录基础结构,是企业安全性的关键推动因素. 它在为诸如身份管理,门户和Web服务之类的应用程 ...

  9. TDS (Tivoli Directory Server)学习指南

    1.概念 IBM的Tivoli Directory Server是IBM对 Lightweight Directory Access Protocol (LDAP)的实现,它可以跨平台的进行安装配置. ...

最新文章

  1. 2021-2027年中国透明导电膜玻璃行业市场研究及前瞻分析报告
  2. ubuntu18.04.4 获取当前文件路径
  3. 【Network Security!】服务器远程管理
  4. boost::function_types::is_member_object_pointer的用法测试程序
  5. 腾讯绝悟AI完全体限时开放体验,研究登上国际顶会与顶刊
  6. 聊聊JVM(八)说说GC标记阶段的一些事
  7. Seaborn初学指南
  8. Nodejs 文件上传
  9. Win11蓝屏100%不重启解决方法
  10. Spring 实践 -拾遗
  11. 这位程序员就这样被征服了......
  12. [Python+MATLAB] 在Python中使用MATLAB (持续更新中)
  13. STM32f407---oled屏幕配套取字模软件使用
  14. C#调用C语言生成的DLL“未找到入口”
  15. mysql存大日志_MySQL三大日志
  16. Android开发项目计划书
  17. rtk定位权限_无人机中的GPS定位、DGPS差分定位、RTK差分定位
  18. 内网神器-Bettercap
  19. 程序员的圣诞节是怎么样的?
  20. magisk卸载内置软件_手机刷入面具magisk授权后,ROOT权限经常丢失解决方法

热门文章

  1. 【网络基础】DNS是什么
  2. 英语知识点整理day23-谚语学习(N字母开头)
  3. 用playbook安装Apache,修改端口,配置ServerName,修改主页,设置开机自启
  4. 世界时转化为北京时!!!
  5. DXF00-00 时间:2021.11.30-2021.11.30 关键词1:Autodesk CAD 关键词2:脱机帮助文档 关键词3:下载及使用
  6. xml.parsers.expat.ExpatError: mismatched tag: line 63, column 4
  7. java invalidate_Swing GUI中validate(),revalidate()和invalidate()
  8. 平面设计和ui设计的区别:ui设计前景怎样
  9. 信心安全快讯丨公安部发布公安机关互联网安全监督检查规定;俄罗斯遭“围攻”被指发起网络攻击;第2季度全球7.65亿用户受到网络攻击
  10. NDIS LWF网络过滤驱动开发(一):LWF简介及数据结构说明