什么是LDAP
LDAP(Light Directory Access Portocol),它是基于X.500标准的轻量级目录访问协议。该协议可以提供目录服务。LDAP可以类比成为一个树形的数据库。其试用于更新少,读取多的场景,在软件系统中通常用来做一个统一的用户、组织管理。
基本概念
- DN (distinguished name),可以理解成为LDAP中各个资源定位的ID,类似于文件路径,这个路径通常包含DC (Domain Component)、OU (Organizational Unit)、CN (Common Name)
- DC (Domain Component),域名元素,通常是树形的根位置
- OU (Organizational Unit),组织单元,
- CM(common name),对象属性的通用名
- o (Organization Name),
- uid(userid),
LDAP的结构
image.png在这里,我们举一个公司的例子,如上所示。
- DN(Distinguished Name),数据的唯一标识,树形结构每个节点都有自己的唯一标识,如上图:
- XXX集团 DN:
dc=xxx集团,dc=com
,这是该树的根节点 - 集团总部DN:
dc=集团总部,dc=xxx集团,dc=com
, 该节点的DN包含【 XXX集团 DN】的DN,所以可以看出这是【 XXX集团 DN】的子节点 - 牛A公司DN:
dc=牛A公司,dc=xxx集团,dc=com
- 牛A公司研发部 DN:
ou=研发部,ou=牛A公司,dc=xxx集团,dc=com
- 牛A公司研发部 李四DN:
cn=李四,cn=研发部,ou=牛A公司,dc=xxx集团,dc=com
- XXX集团 DN:
容器openladp使用
- 启动 openldap
# 挂载目录运行
docker run -itd -p 389:389 --name openldap \
-v /opt/data/ldap/database:/var/lib/ldap \
-v /opt/data/ldap/config:/etc/openldap/slapd.d \
--env LDAP_ORGANISATION="xyz" \
--env LDAP_DOMAIN="xyz.com" \
--env LDAP_ADMIN_PASSWORD="qiu11211" \
--detach osixia/openldap:1.5.0
# 测试,不挂载目录
docker run -itd -p 389:389 --name openldap \
--env LDAP_ORGANISATION="xyz" \
--env LDAP_DOMAIN="xyz.com" \
--env LDAP_ADMIN_PASSWORD="qiu11211" \
--detach osixia/openldap:1.5.0
配置LDAP组织者:LDAP_ORGANISATION
配置LDAP域:LDAP_DOMAIN
配置LDAP密码:LDAP_ADMIN_PASSWORD
默认登录用户名:admin
- 启动phpldapadmin,其中
10.54.16.23
为openldap的启动IP
docker run -p 6443:443 \
--env PHPLDAPADMIN_LDAP_HOSTS=192.168.3.156 \
--detach osixia/phpldapadmin:0.9.0
login DN :cn=admin,dc=xyz,dc=com
Password: qiu11211
- 可以自页面上创建操作节点
导入
在PHPLDAPadmin上可以导入组织架构,如下是一个例子:
image.png
dn: dc=gdy, dc=com
dc: gdy
objectClass: top
objectClass: domain
dn: ou=people, dc=gdy, dc=com
ou: people
objectClass: top
objectClass: organizationalUnit
dn: ou=group, dc=gdy, dc=com
ou: group
objectClass: top
objectClass: organizationalUnit
列子代码
- 登录验证LDAP
package main
import (
"fmt"
"github.com/go-ldap/ldap/v3"
)
func main() {
con, err := LoginBind("admin","qiu11211")
fmt.Println(con.IsClosing())
if err != nil {
fmt.Println("V")
fmt.Println(err)
}
fmt.Println("Exit")
}
// LoginBind connection ldap server and binding ldap server
func LoginBind(ldapUser, ldapPassword string) (*ldap.Conn, error) {
l, err := ldap.DialURL(fmt.Sprintf("ldap://%s:%d", "127.0.0.1", 389))
if err != nil {
fmt.Errorf("conect error",err)
return nil, err
}
_, err = l.SimpleBind(&ldap.SimpleBindRequest{
Username: fmt.Sprintf("cn=%s,dc=demo,dc=com", ldapUser),
Password: ldapPassword,
})
if err != nil {
fmt.Println("ldap password is error: ", ldap.LDAPResultInvalidCredentials)
return nil, err
}
fmt.Println(ldapUser,"登录成功")
return l, nil
}
- 添加用户例子
package main
import (
"fmt"
"github.com/go-ldap/ldap/v3"
)
type User struct {
username string
password string
telephone string
emailSuffix string
snUsername string
uid string
gid string
}
func main() {
fmt.Println("hello 1")
con, err := LoginBind("admin","qiu11211")
fmt.Println(con.IsClosing())
if err != nil {
fmt.Println("V")
fmt.Println(err)
}
//1. add user
var user User
user.username="nick"
user.password="admin123"
user.snUsername="nick"
user.uid="1000"
user.gid="1000"
user.emailSuffix="@qq.com"
if err=user.addUser(con);err!=nil{
fmt.Println(err)
}
fmt.Println("exit")
//1. add user
//var user1 User
//user1.username="邱家洪"
//user1.password="admin123"
//user1.snUsername="邱家洪"
//user1.uid="1000"
//user1.gid="1000"
//user1.emailSuffix="@qq.com"
//if err=user1.addUser(con);err!=nil{
// fmt.Println(err)
//}
}
// LoginBind connection ldap server and binding ldap server
func LoginBind(ldapUser, ldapPassword string) (*ldap.Conn, error) {
l, err := ldap.DialURL(fmt.Sprintf("ldap://%s:%d", "127.0.0.1", 389))
//l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", "127.0.0.1", 389))
if err != nil {
fmt.Errorf("conect error",err)
return nil, err
}
_, err = l.SimpleBind(&ldap.SimpleBindRequest{
Username: fmt.Sprintf("cn=%s,dc=demo,dc=com", ldapUser),
Password: ldapPassword,
})
if err != nil {
fmt.Println("ldap password is error: ", ldap.LDAPResultInvalidCredentials)
return nil, err
}
fmt.Println(ldapUser,"登录成功")
return l, nil
}
func (user *User) addUser(conn *ldap.Conn) error {
ldaprow := ldap.NewAddRequest(fmt.Sprintf("cn=%s,dc=demo,dc=com", user.username), nil)
ldaprow.Attribute("userPassword", []string{user.password})
ldaprow.Attribute("homeDirectory", []string{fmt.Sprintf("/home/%s", user.username)})
ldaprow.Attribute("cn", []string{user.username})
ldaprow.Attribute("uid", []string{user.username})
ldaprow.Attribute("objectClass", []string{"shadowAccount", "posixAccount", "account"})
ldaprow.Attribute("uidNumber", []string{"2201"})
ldaprow.Attribute("gidNumber", []string{"2201"})
ldaprow.Attribute("loginShell", []string{"/bin/bash"})
if err := conn.Add(ldaprow); err != nil {
return err
}
return nil
}
- 删除用户
package main
import (
"fmt"
"github.com/go-ldap/ldap/v3"
)
type User struct {
username string
password string
telephone string
emailSuffix string
snUsername string
uid string
gid string
}
func main() {
fmt.Println("hello 1")
con, err := LoginBind("admin","qiu11211")
fmt.Println(con.IsClosing())
if err != nil {
fmt.Println("V")
fmt.Println(err)
}
var user User
user.username="marionxue"
if err:=user.delUser(con);err!=nil{
fmt.Println("用户删除失败")
}
fmt.Println(user.username,"用户删除成功!")
}
// LoginBind connection ldap server and binding ldap server
func LoginBind(ldapUser, ldapPassword string) (*ldap.Conn, error) {
l, err := ldap.DialURL(fmt.Sprintf("ldap://%s:%d", "127.0.0.1", 389))
//l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", "127.0.0.1", 389))
if err != nil {
fmt.Errorf("conect error",err)
return nil, err
}
_, err = l.SimpleBind(&ldap.SimpleBindRequest{
Username: fmt.Sprintf("cn=%s,dc=demo,dc=com", ldapUser),
Password: ldapPassword,
})
if err != nil {
fmt.Println("ldap password is error: ", ldap.LDAPResultInvalidCredentials)
return nil, err
}
fmt.Println(ldapUser,"登录成功")
return l, nil
}
func (user *User) delUser(conn *ldap.Conn) error{
ldaprow := ldap.NewDelRequest(fmt.Sprintf("cn=%s,dc=demo,dc=com",user.username),nil)
if err:= conn.Del(ldaprow);err!=nil{
return err
}
return nil
}
- 遍历所有用户
package main
import (
"fmt"
"github.com/go-ldap/ldap/v3"
"strings"
)
type User struct {
username string
password string
telephone string
emailSuffix string
snUsername string
uid string
gid string
}
func main() {
fmt.Println("hello 1")
con, err := LoginBind("admin","qiu11211")
fmt.Println(con.IsClosing())
if err != nil {
fmt.Println("V")
fmt.Println(err)
}
//2. 遍历用户
employees, err := GetEmployees(con)
if err != nil {
fmt.Println(err)
}
for _, employe := range employees {
fmt.Println(employe)
}
}
// LoginBind connection ldap server and binding ldap server
func LoginBind(ldapUser, ldapPassword string) (*ldap.Conn, error) {
l, err := ldap.DialURL(fmt.Sprintf("ldap://%s:%d", "127.0.0.1", 389))
//l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", "127.0.0.1", 389))
if err != nil {
fmt.Errorf("conect error",err)
return nil, err
}
_, err = l.SimpleBind(&ldap.SimpleBindRequest{
Username: fmt.Sprintf("cn=%s,dc=demo,dc=com", ldapUser),
Password: ldapPassword,
})
if err != nil {
fmt.Println("ldap password is error: ", ldap.LDAPResultInvalidCredentials)
return nil, err
}
fmt.Println(ldapUser,"登录成功")
return l, nil
}
func GetEmployees(con *ldap.Conn) ([]string, error) {
var employees []string
sql := ldap.NewSearchRequest("dc=demo,dc=com",
ldap.ScopeWholeSubtree,
ldap.NeverDerefAliases,
0,
0,
false,
"(objectClass=*)",
[]string{"dn", "cn", "objectClass"},
nil)
cur, err := con.Search(sql)
if err != nil {
return nil, err
}
if len(cur.Entries) > 0 {
for _, item := range cur.Entries {
cn := item.GetAttributeValues("cn")
for _, iCn := range cn {
employees = append(employees, strings.Split(iCn, "[")[0])
}
}
return employees, nil
}
return nil, nil
}
- 添加组
package main
import (
"fmt"
"github.com/go-ldap/ldap/v3"
)
type Group struct {
username string
}
func main() {
fmt.Println("hello 1")
con, err := LoginBind("admin","qiu11211")
fmt.Println(con.IsClosing())
if err != nil {
fmt.Println("V")
fmt.Println(err)
}
//1. add user
var g Group
g.username="crqu"
if err=g.addGroup(con);err!=nil{
fmt.Println(err)
}
fmt.Println("exit")
}
// LoginBind connection ldap server and binding ldap server
func LoginBind(ldapUser, ldapPassword string) (*ldap.Conn, error) {
l, err := ldap.DialURL(fmt.Sprintf("ldap://%s:%d", "127.0.0.1", 389))
if err != nil {
fmt.Errorf("conect error",err)
return nil, err
}
_, err = l.SimpleBind(&ldap.SimpleBindRequest{
Username: fmt.Sprintf("cn=%s,dc=demo,dc=com", ldapUser),
Password: ldapPassword,
})
if err != nil {
fmt.Println("ldap password is error: ", ldap.LDAPResultInvalidCredentials)
return nil, err
}
fmt.Println(ldapUser,"登录成功")
return l, nil
}
//dn: ou=crqu,dc=demo,dc=com
//objectclass: organizationalUnit
//ou: crqu
func (group *Group) addGroup(conn *ldap.Conn) error {
ldaprow := ldap.NewAddRequest(fmt.Sprintf("ou=%s,dc=demo,dc=com", group.username), nil)
ldaprow.Attribute("objectClass", []string{"organizationalUnit"})
ldaprow.Attribute("ou", []string{group.username})
if err := conn.Add(ldaprow); err != nil {
return err
}
return nil
}
- 在新的组上面添加用户,含密码
package main
import (
"fmt"
"github.com/go-ldap/ldap/v3"
)
type User struct {
username string
}
func main() {
fmt.Println("hello 1")
con, err := LoginBind("admin","qiu11211")
fmt.Println(con.IsClosing())
if err != nil {
fmt.Println("V")
fmt.Println(err)
}
//1. add user
var g User
g.username="ming"
if err=g.addUser(con);err!=nil{
fmt.Println(err)
}
fmt.Println("exit")
}
// LoginBind connection ldap server and binding ldap server
func LoginBind(ldapUser, ldapPassword string) (*ldap.Conn, error) {
l, err := ldap.DialURL(fmt.Sprintf("ldap://%s:%d", "127.0.0.1", 389))
if err != nil {
fmt.Errorf("conect error",err)
return nil, err
}
_, err = l.SimpleBind(&ldap.SimpleBindRequest{
Username: fmt.Sprintf("cn=%s,dc=demo,dc=com", ldapUser),
Password: ldapPassword,
})
if err != nil {
fmt.Println("ldap password is error: ", ldap.LDAPResultInvalidCredentials)
return nil, err
}
fmt.Println(ldapUser,"登录成功")
return l, nil
}
//dn: cn=nick,ou=crqu,dc=demo,dc=com
//cn: nick
//givenname: nick
//objectclass: inetOrgPerson
//objectclass: top
//sn: nick
func (group *User) addUser(conn *ldap.Conn) error {
ldaprow := ldap.NewAddRequest(fmt.Sprintf("cn=%s,ou=crqu,dc=demo,dc=com", group.username), nil)
ldaprow.Attribute("objectClass", []string{"inetOrgPerson","top"})
ldaprow.Attribute("cn", []string{group.username})
ldaprow.Attribute("givenname", []string{group.username})
ldaprow.Attribute("sn", []string{group.username})
// hua
ldaprow.Attribute("userpassword", []string{"{MD5}pP2/vmpo8KAIjC2YxkRzEQ=="})
if err := conn.Add(ldaprow); err != nil {
return err
}
return nil
}
网友评论