咱们工作在和其余组织配合时,咱们可能不是作为服务器搭建的一方,而是属于客户端的一方,须要去获取服务器的组织构造,依照某些条件去获取服务器的数据,也能够是同步组织构造
尽管说 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 服务器上的组织构造
这是咱们简略搭建的 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()
咱们填入的地址中,能够不必输出端口号,库函数曾经有给咱们做好解决,咱们能够来看看源码
DialURL
函数用于连贯 ldap 服务器,连贯胜利会给咱们返回一个新的连贯
咱们能够持续看一下这个函数调用 c, err := dc.dial(u)
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 operationtype 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
基本上就是填写相应的域信息
- BaseDN , 一个域惟一的标识
- scope 范畴的抉择,咱们默认抉择
ScopeWholeSubtree
,查问所有的子树 - DerefAliases , SizeLimit,TimeLimit,TypesOnly 填写默认值即可
- Filter , 查问须要的过滤条件,能够依照咱们的理论状况写条件,就像写查询数据库的条件一样,这里不能为空,否则会程序解体
F:\codegitee\golang_study\later_learning\ldap_test>go run main.goconnect successfully !!2021/11/06 21:07:59 can't search LDAP Result Code 201 "Filter Compile Error": ldap: error parsing filterpanic: 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 +0x24fexit status 2
- Attributes , 须要返回的属性有哪些,是一个切片,如果咱们默认填空,则会返回所有属性
查看对应的 Search
函数源码
代码的大抵逻辑是,doRequest
将数据组包向 ldap 服务器发送申请,申请胜利之后,将响应的数据依照 tag 不同的内容进行解析
最终返回一个 *SearchResult
查问后果的指针
输出查问信息
for _, item := range searchResult.Entries { item.Print() fmt.Printf("\n\n")}
上图源码咱们能够看到输入查问信息就是遍历一下 searchResult.Entries
,咱们能够来看看对应的数据结构
咱们能够看到后果外面,有一个 Entries []*Entry
是一个切片,外面放了多个 *Entry
, 在 ldap 服务器中, 1 个 Entry 就代表一条惟一的记录
Entry 构造体就是对应的 DN,一条记录惟一的分别名 , 和他波及的属性
EntryAttribute 属性构造体中,咱们能够看到 有 Name ,有 Values ,这里就是对应咱们之前说到的 RDN,也就是一个键值对,多个键值对组成一个 DN
最终咱们来查看一下成果
>go run main.goconnect successfully !!2021/11/06 21:20:58 1DN: ou=People,dc=xiaomotong,dc=comobjectClass: [organizationalUnit]ou: [People]
后果是输入了 1 条信息,没错,因为咱们的 ou=people 只有 1条记录,如果咱们须要查问整个 ldap服务器的所有数据,则咱们能够将上述代码的 Filter 地位,批改成 objectClass=*
解释上述后果:
- DN 示意惟一的记录,是分别名的意思
- objectClass 是一个类,这里对应的是 organizationalUnit ,示意组织单元OU,能够了解为 组
- ou: [People] 指的是这个 ou 对应的名字是 People
欢送点赞,关注,珍藏
敌人们,你的反对和激励,是我保持分享,提高质量的能源
好了,本次就到这里
技术是凋谢的,咱们的心态,更应是凋谢的。拥抱变动,背阴而生,致力向前行。
我是阿兵云原生,欢送点赞关注珍藏,下次见~