美文网首页实践人生
goalng 如何获取 ldap 服务器的数据?

goalng 如何获取 ldap 服务器的数据?

作者: 阿兵云原生 | 来源:发表于2023-04-05 21:42 被阅读0次
    ldap3.jpg

    我们工作在和其他组织配合时,我们可能不是作为服务器搭建的一方,而是属于客户端的一方,需要去获取服务器的组织结构,按照某些条件去获取服务器的数据,也可以是同步组织结构

    虽然说 golang 的数据结构没有 c++ 那么丰富,不过对于这个 ldap 还是有相应的库来进行处理的

    官方文档地址:https://pkg.go.dev/gopkg.in/ldap.v3

    我们也可以下载 github 上面的这个库

    go get github.com/go-ldap/ldap/v3
    

    golang 对于 ldap 库最新的版本是 Version: v3.1.0

    开始编码

    我们来写一个 demo ,获取我们上次搭建的 ldap 服务器上的组织结构

    [图片上传失败...(image-c11ca6-1680788393740)]

    这是我们简单搭建的 ldap 服务器,可以使用 LDAP Admin 可视化管理工具来查看具体的页面效果

    我们把这个库下载下来后,我们的编码思路如下:

    • 填写 ldap 服务器地址以及填写相应的管理员信息,与 ldap 服务器建立连接
    • 编写查询请求,并开始向 ldap 服务器进行查询
    • 将查询结构,按照 ldap v3 库提供的方式 打印出效果来

    连接 服务器

    我们可以使用 func DialURL(addr string, opts ...DialOpt) (*Conn, error) 函数来与 ldap 服务器建立连接

    ml, err := ldap.DialURL("ldap://xxxx")
        if err != nil {
            log.Fatal(err)
        }
        defer ml.Close()
    

    我们填入的地址中,可以不用输入端口号,库函数已经有给我们做好处理,我们可以来看看源码

    [图片上传失败...(image-36c098-1680788393740)]

    DialURL 函数用于连接 ldap 服务器,连接成功会给我们返回一个新的连接

    我们可以继续看一下这个函数调用 c, err := dc.dial(u)

    [图片上传失败...(image-e3d734-1680788393740)]

    golang 的库会根据我们填写的地址是 ldap 还是 ldaps 来判断是做加密传输还是不加密传输,与之对应的就是访问不加密的用 389 端口加密的就使用 636 端口

    添加管理员绑定信息

    我们添加的 ldap 域信息为:dc=xiaomotong,dc=com

    我的管理员是:cn=admin,dc=xiaomotong,dc=com

    _, err = ml.SimpleBind(&ldap.SimpleBindRequest{
            Username: "cn=admin,dc=xiaomotong,dc=com",
            Password: "123123",
        })
        if err != nil {
            log.Fatalf("Failed to bind: %s\n", err)
        }
    
        fmt.Println("connect successfully !!")
    

    来看看实际的 SimpleBindRequest数据结构

    // SimpleBindRequest represents a username/password bind operation
    type SimpleBindRequest struct {
        // Username is the name of the Directory object that the client wishes to bind as
        Username string
        // Password is the credentials to bind with
        Password string
        // Controls are optional controls to send with the bind request
        Controls []Control
        // AllowEmptyPassword sets whether the client allows binding with an empty password
        // (normally used for unauthenticated bind).
        AllowEmptyPassword bool
    }
    
    • Username
    • Password

    客户端需要绑定的域用户和密码

    • Controls

    需要绑定请求的控件

    • AllowEmptyPassword

    是否允许空密码,若是空密码,一般是绑定一个未授权的用户

    编写查询请求,并开始查询 ldap 服务器

    searchRequest := ldap.NewSearchRequest(
            "dc=xiaomotong,dc=com",
            ldap.ScopeWholeSubtree,
            ldap.NeverDerefAliases,
            0,
            0,
            false,
            "(ou=People)",
            []string{},
            nil,
        )
        searchResult, err := ml.Search(searchRequest)
        if err != nil {
            log.Println("can't search ", err.Error())
        }
        log.Printf("%d", len(searchResult.Entries))
    

    编写查询请求,也就是简单的给我们的结构体进行一个负值操作,填写好对相应的参数,即可开始查询,一起来看看这个结构体NewSearchRequest

    [图片上传失败...(image-8c69ba-1680788393740)]

    基本上就是填写相应的域信息

    • BaseDN , 一个域唯一的标识
    • scope 范围的选择,我们默认选择ScopeWholeSubtree ,查询所有的子树
    • DerefAliases , SizeLimit,TimeLimit,TypesOnly 填写默认值即可
    • Filter , 查询需要的过滤条件,可以按照我们的实际情况写条件,就像写查询数据库的条件一样,这里不能为空,否则会程序崩溃
    F:\codegitee\golang_study\later_learning\ldap_test>go run main.go
    connect successfully !!
    2021/11/06 21:07:59 can't search  LDAP Result Code 201 "Filter Compile Error": ldap: error parsing filter
    panic: runtime error: invalid memory address or nil pointer dereference
    [signal 0xc0000005 code=0x0 addr=0x4 pc=0xa33cef]
    
    goroutine 1 [running]:
    main.main()
            F:/codegitee/golang_study/later_learning/ldap_test/main.go:40 +0x24f
    exit status 2
    
    • Attributes , 需要返回的属性有哪些,是一个切片,如果我们默认填空,则会返回所有属性

    查看对应的 Search 函数源码

    [图片上传失败...(image-5bd0da-1680788393740)]

    代码的大致逻辑是,doRequest 将数据组包向 ldap 服务器发送请求,请求成功之后,将响应的数据按照 tag 不同的内容进行解析

    [图片上传失败...(image-68c90b-1680788393740)]

    最终返回一个 *SearchResult 查询结果的指针

    输入查询信息

    for _, item := range searchResult.Entries {
       item.Print()
       fmt.Printf("\n\n")
    }
    

    [图片上传失败...(image-69baea-1680788393740)]

    上图源码我们可以看到输出查询信息就是遍历一下 searchResult.Entries ,我们可以来看看对应的数据结构

    [图片上传失败...(image-34bc44-1680788393740)]

    我们可以看到结果里面,有一个 Entries []*Entry 是一个切片,里面放了多个 *Entry , 在 ldap 服务器中, 1 个 Entry 就代表一条唯一的记录

    Entry 结构体就是对应的 DN,一条记录唯一的辨别名 , 和他涉及的属性

    [图片上传失败...(image-be275b-1680788393740)]

    EntryAttribute 属性结构体中,我们可以看到 有 Name ,有 Values ,这里就是对应我们之前说到的 RDN,也就是一个键值对,多个键值对组成一个 DN

    [图片上传失败...(image-e4a3bc-1680788393740)]

    最终我们来查看一下效果

    >go run main.go
    connect successfully !!
    2021/11/06 21:20:58 1
    DN: ou=People,dc=xiaomotong,dc=com
    objectClass: [organizationalUnit]
    ou: [People]
    

    结果是输出了 1 条信息,没错,因为我们的 ou=people 只有 1条记录,如果我们需要查询整个 ldap服务器的所有数据,则我们可以将上述代码的 Filter 位置,修改成 objectClass=*

    解释上述结果:

    • DN 表示唯一的记录,是辨别名的意思
    • objectClass 是一个类,这里对应的是 organizationalUnit ,表示组织单元OU,可以理解为 组
    • ou: [People] 指的是这个 ou 对应的名字是 People

    欢迎点赞,关注,收藏

    朋友们,你的支持和鼓励,是我坚持分享,提高质量的动力

    [图片上传失败...(image-4ab698-1680788393740)]

    好了,本次就到这里

    技术是开放的,我们的心态,更应是开放的。拥抱变化,向阳而生,努力向前行。

    我是阿兵云原生,欢迎点赞关注收藏,下次见~

    相关文章

      网友评论

        本文标题:goalng 如何获取 ldap 服务器的数据?

        本文链接:https://www.haomeiwen.com/subject/qujyddtx.html