我从0开始开发了一个LDAP服务。

当然不能从0开始,,,我当初酝酿这个需求的时候,LDAP的rfc都看了一周。

 

需求是需要一个LDAP服务来支持三方系统的登录,比如神策、confluence、jira。

都不用想,三方开源闭源的方案都有很多。但是我寻觅了一圈,没找到一个可以直接在LDAP后端对接一个接口到账号体系的,都是需要账号导入,纳尼?

哈哈哈,也或许是造轮子的情绪太重,没有认真的找。但是不管怎么样,轮子造出来了。

 

我是怎么造的轮子?

 

当然是先读书了,rfc是要读个大概的。

https://www.cnblogs.com/mrtiny/p/ldap-Technical-Specification-Road-Map.html

 

协议指令比较多,我们并不关心用不到的,我们只需要支持两个主要的指令,查询(searchrequest)、认证(bindrequest)

就可以实现需求了。

 

LDAP的服务端实现有很多,我选了一个叫OpenLDAP的,因为名字看着顺眼。

源码是C++的,我开始是用它的数据库结构,并参考代码,用C#实现了对应的账号管理功能,当时的方案是认证时候同步账号到ldap数据库。

 

协议解析,也就是将请求数据解析成程序员能看明白的实体对象,也是有开源方案的。

比如Zetetic的,http://wiki.github.com/skradel/Zetetic.Ldap。

实际使用时候,发现有很多不完善,解析出错。因此我基于rfc和它的一些类的定义实现了自己的方案。

主要就是将请求解析成Asn1,然后从Asn1解析出实体对象。

 

然后实现会话管理,也就是bindrequest+unbindrequest。

 

然后实现ip白名单功能。

 

然后设计可以对接外部账号体系的接口。

 

上线后完美支撑业务需求。

 

我知道它有一些瑕疵,

比如openldap的表设计在字段中存了sql字句,而我用的EF无法发挥优势。

比如searchrequest指令处理里面没有实现成员组的支持。

比如bindrequest指令处理,同步账号又存储到ldap数据库的操作没有多少意义。

 

于是在今年底,我又花了大概一周时间,重构了一次:

干掉之前的ldap数据库临时存储账号的功能,替换为直接对接账号体系接口。

searchrequest指令处理时的查询缓存优化。

新增支持账号组。

 

开发调试协议是个繁琐的工作,因此我请来了apache目录服务客户端

 

 

 

 

对外的接口很简单,实现对应的接口定义就OK,其他的交给框架。

    interface ILdapPersonStore
    {
        List<ILdapExternalObject> GetPersons();
    }

    public interface ILdapExternalObject
    {
        Dictionary<string, string> Attributes { get; }

        /// <summary>
        /// 记录位置,唯一
        /// </summary>
        /// <returns></returns>
        string GetDN();
        /// <summary>
        /// 所属域
        /// </summary>
        /// <returns></returns>
        string GetDC();


        /// <summary>
        /// 通用名称
        /// </summary>
        /// <returns></returns>
        string GetCN();

        /// <summary>
        /// 类别
        /// </summary>
        /// <returns></returns>
        string GetObjectClass();
    }
    public interface ILdapPerson : ILdapExternalObject
    {
        /// <summary>
        /// 所属组织单元
        /// </summary>
        /// <returns></returns>
        string GetOU();

        /// <summary>
        /// 用户ID
        /// </summary>
        /// <returns></returns>
        string GetUID();
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        string GetMemberOf();
        /// <summary>
        /// UUID格式的唯一标识
        /// </summary>
        /// <returns></returns>
        string GetEntryUUID();
        /// <summary>
        /// 姓名
        /// </summary>
        /// <returns></returns>
        string GetName();
        /// <summary>
        /// 是否有下级
        /// </summary>
        /// <returns></returns>
        bool GetHasSubordinates();

        ILdapExternalObject groupOfUniqueNames { get; }
    }

轮子造好就等卖钱了

posted @ 2020-11-03 16:12  道木先生  阅读(455)  评论(0编辑  收藏  举报