金瓯无缺江河一统|Win10系统基于Docker和Python3搭建并维护统一认证系统OpenLdap
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_180
OpenLdap(Lightweight Directory Access Protocol)是什么?它其实是一个开源的、具备工业标准特性的应用协议,可以使用TCP协议提供访问控制和维护分布式信息的目录信息。这是一个传统意义上的书面解释,是的,毫无疑问,你会一脸懵逼。好吧,让我们变得感性一点,假如我每天早上使用Twitter想听听懂王又吹了什么牛,登录Twitter账号密码,紧接着又想上Instagram看看女神又post了什么新靓照,好的,登录Instagram账号密码,摸了一上午的鱼之后,突然想起来要登录公司的邮箱,看看有没有新需求,是的,又需要那该死的账号和密码,甚至于查询社保、公积金提取、交罚款都需要各自系统的账号和密码。想象一下,如果有一套系统可以统一管理和维护所有下游应用的账号和权限,我们不需要花时间重复的注册新应用的账号,而只需要关注应用本身,从而实现账号集中认证管理,此时作为账号管理员的我们只须维护OpenLDAP 服务器条目即可,金瓯无缺江山一统,这就是openladp能够带给我们的好处。
LDAP是非常典型的层级结构,信息模型是建立在属性条目(entries)的基础上。一个属性条目是一些属性的集合,并且具有一个全局唯一的"可区分名称"DN,一个条目可以通过DN来引用。每一个条目的属性具有一个类型和一个或者多个值。类型通常是容易记忆的名称,比如"cn"是通用名称(common name) ,或者"mail"是电子邮件地址。条目的值的语法取决于属性类型。比如,cn属性可能具有一个值"jack joe" 。一个mail属性可能包含"admin@v3u.cn" 。一个pngphoto属性可能包含一幅PNG(二进制)格式的图片。
这里简单介绍一下openldap常用的层级关键字的解释:
dc:Domain Component 域名的范围,其格式是将完整的域名分成几部分,如域名为v3u.cn则写成dc=v3u,dc=cn。
uid:User Id 用户ID,比如自增长“1”。
ou:Organization Unit 组织单位,类似于文件系统中的子目录,它是一个容器对象,组织单位可以包含其他各种对象(包括其他组织单元),如“newgroup”。
cn:Common Name 公共名称,如“jack joe”。
sn: Surname 姓,如“joe”。
dn :Distinguished Name 惟一辨别名,类似于文件系统中的绝对路径,每个对象都有一个惟一的名称,类似于mysql的全局唯一索引,如“uid= tom,ou=market,dc=example,dc=com”,记住在一个目录树中DN总是惟一的。
理解了概念,让我们来实操一把,因为实践永远是检验真理的唯一标准,首先安装Docker,参照:win10系统下把玩折腾DockerToolBox以及更换国内镜像源(各种神坑)。
随后拉取openldap镜像:
docker pull osixia/openldap:1.3.0
这里我们使用1.3稳定版,拉取成功后查看本地镜像
docker images
可以看到只有200mb左右,非常小巧:
liuyue:~ liuyue$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
osixia/openldap 1.3.0 faac9bb59f83 6 months ago 260MB
启动容器:
docker run -p 389:389 --name myopenldap --network bridge --hostname openldap-host --env LDAP_ORGANISATION="v3u" --env LDAP_DOMAIN="v3u.cn" --env LDAP_ADMIN_PASSWORD="admin" --detach osixia/openldap:1.3.0
这里我们通过端口映射将389端口作为链接桥梁,同时配置LDAP组织者:–env LDAP_ORGANISATION=“v3u”,配置LDAP域:–env LDAP_DOMAIN=“v3u.cn”,配置LDAP密码:–env LDAP_ADMIN_PASSWORD=“admin”,默认登录用户名:admin,并且开启后台守护进程。
查看容器运行状态:
docker ps
可以看到已经在后台启动了:
liuyue:~ liuyue$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b62d1f66c2b8 osixia/openldap:1.3.0 "/container/tool/run" 2 days ago Up 2 days 0.0.0.0:389->389/tcp, 636/tcp myopenldap
liuyue:~ liuyue$
服务确认没问题之后,我们通过python来进行逻辑的编写,首先安装依赖
pip3 install ldap3
随后编写测试脚本 test_ldap.py ,首先测试一下链接ldap服务器:
from ldap3 import Server, Connection, ALL,MODIFY_REPLACE
s = Server('localhost', get_info=ALL)
c = Connection(s, user='cn=admin,dc=v3u,dc=cn', password='admin')
c.bind()
print(c.extend.standard.who_am_i())
这里的localhost是docker容器的ip,同时使用账号admin登录,注意账号(cn)以及域(dc)不要写错,不出意外的话,系统会返回当前验证的用户信息:
liuyue:mytornado liuyue$ python3 "/Users/liuyue/wodfan/work/mytornado/test_ldap.py"
dn:cn=admin,dc=v3u,dc=cn
liuyue:mytornado liuyue$
初始状态下,LDAP是一个空目录,即没有任何数据。可通过程序代码向目录数据库中添加数据,也可使用ldap3库的ldapadd命令来完成添加数据的操作,该命令可将一个LDIF文件中的条目添加到目录:
这里我们来添加一个OU,也就是组织(OrganizationalUnit)。
#添加组织
res = c.add('OU=v3u_users,dc=v3u,dc=cn', object_class='OrganizationalUnit')
print(res)
print(c.result)
可以看到添加成功:
liuyue:mytornado liuyue$ python3 "/Users/liuyue/wodfan/work/mytornado/test_ldap.py"
True
{'result': 0, 'description': 'success', 'dn': '', 'message': '', 'referrals': None, 'type': 'addResponse'}
随后可以为该组织添加一个群组(group):
# 添加群组
ldap_attr = {}
ldap_attr['objectClass'] = ['top', 'posixGroup']
ldap_attr['gidNumber'] = '1'
c.add('cn=mygroup,dc=v3u,dc=cn',attributes=ldap_attr)
print(c.result)
返回:
liuyue:mytornado liuyue$ python3 "/Users/liuyue/wodfan/work/mytornado/test_ldap.py"
{'result': 0, 'description': 'success', 'dn': '', 'message': '', 'referrals': None, 'type': 'addResponse'}
liuyue:mytornado liuyue$
紧接着就是添加人员了:
#添加用户
ldap_attr = {}
ldap_attr['cn'] = "test user1"
ldap_attr['sn'] = "测试"
ldap_attr['userPassword'] = "1234"
user_dn = "cn=testuser1,cn=mygroup,dc=v3u,dc=cn"
c.add(dn=user_dn,object_class='inetOrgPerson',attributes=ldap_attr)
print(c.result)
这里的cn可以理解为用户名,sn为姓,userPassword顾名思义就是该用户的密码,dn则是该用户在系统中的唯一标识,注意指定刚刚建立的群组mygroup,返回:
liuyue:mytornado liuyue$ python3 "/Users/liuyue/wodfan/work/mytornado/test_ldap.py"
{'result': 0, 'description': 'success', 'dn': '', 'message': '', 'referrals': None, 'type': 'addResponse'}
liuyue:mytornado liuyue$
此时,我们可以查询一下刚刚建立好的用户:
print(c.search("dc=v3u,dc=cn", '(&(cn=testuser1))', attributes=['*']))
print(c.entries)
就可以看到用户的具体信息:
liuyue:mytornado liuyue$ python3 "/Users/liuyue/wodfan/work/mytornado/test_ldap.py"
True
[DN: cn=testuser1,cn=mygroup,dc=v3u,dc=cn - STATUS: Read - READ TIME: 2020-11-23T17:58:08.569044
cn: test user1
testuser1
objectClass: inetOrgPerson
sn: 测试
userPassword: b'1234'
]
liuyue:mytornado liuyue$
如果我们要修改用户信息,可以使用modify方法:
#修改用户
c.modify('cn=testuser1,cn=mygroup,dc=v3u,dc=cn',{'uid':[(MODIFY_REPLACE, ['1'])]})
print(c.result)
这里修改用户的uid属性,返回:
liuyue:mytornado liuyue$ python3 "/Users/liuyue/wodfan/work/mytornado/test_ldap.py"
{'result': 0, 'description': 'success', 'dn': '', 'message': '', 'referrals': None, 'type': 'modifyResponse'}
liuyue:mytornado liuyue$
再次搜索该用户:
print(c.search("dc=v3u,dc=cn", '(&(cn=testuser1))', attributes=['*']))
print(c.entries)
可以看到uid已经被添加好了:
liuyue:mytornado liuyue$ python3 "/Users/liuyue/wodfan/work/mytornado/test_ldap.py"
True
[DN: cn=testuser1,cn=mygroup,dc=v3u,dc=cn - STATUS: Read - READ TIME: 2020-11-23T18:02:47.080555
cn: test user1
testuser1
objectClass: inetOrgPerson
sn: 测试
uid: 1
userPassword: b'1234'
]
最后,如果员工离职的话,公司内所有账号和权限应该被回收,所以进行删除操作:
#删除用户
c.delete(dn='cn=testuser1,cn=mygroup,dc=v3u,dc=cn')
print(c.result)
返回:
{'result': 0, 'description': 'success', 'dn': '', 'message': '', 'referrals': None, 'type': 'delResponse'}
再次查询已经获取不到记录:
print(c.search("dc=v3u,dc=cn", '(&(cn=testuser1))', attributes=['*']))
print(c.entries)
liuyue:mytornado liuyue$ python3 "/Users/liuyue/wodfan/work/mytornado/test_ldap.py"
False
[]
至此,我们就基于openldap的树形结构将组织以及用户信息分别进行存储和CURD(增删改查)操作,在树的root(根)一般定义总域(c=v3u)或者域名后缀(dc=cn),其次往往定义一个或多个组织(organization,o)或组织单元(organization unit,ou)。一个组织单元可以包含人员、设备信息(服务器、电脑等)相关信息。例如uid=testuser1,ou=v3u_users,dc=v3u,dc=cn,如图所示:

除此以外,OpenLDAP 还是一种典型的分布式结构,提供复制同步,可将主服务器上的数据通过推或拉的机制实现在从服务器上更新,完成数据的同步,从而避免OpenLDAP 服务器出现单点故障,实现了高可用架构。
OpenLdap目录层级结构是一个专门为搜索和浏览而设计的数据库,虽然也支持简单的插入、删除、修改功能。但是我们可以理解为它是为浏览和搜索而生的,它的查询速度很快,相反插入速度较慢,和关系型数据库相比,它并不支持事务和回滚以及复杂的插入、更新等连贯操作功能,这一点和Elasticsearch有几分相似,但是,古人云:“射不主皮,力不同科”,如果您的系统扩容频繁,下游应用层出不穷,那么您就可以考虑用它来做统一用户管理,为您的应用保驾护航。
原文转载自「刘悦的技术博客」 https://v3u.cn/a_id_180
金瓯无缺江河一统|Win10系统基于Docker和Python3搭建并维护统一认证系统OpenLdap的更多相关文章
- #研发解决方案介绍#IdCenter(内部统一认证系统)
郑昀 基于朱传志的设计文档 最后更新于2014/11/13 关键词:LDAP.认证.权限分配.IdCenter. 本文档适用人员:研发 曾经一个IT内部系统配一套帐号体系和授权 线上生产环境里 ...
- 云方案,依托H3C彩虹云存储架构,结合UIA统一认证系统,实现了用户数据的集中存储和管理
客户的声音 资料云项目在迷你云基础上二次开发,通过使用云存储技术及文件秒传技术,对文件进行统一存储与管理,以达到节约文件管理成本.存储成本目的:通过有效的文件版本控制机制,以达到风险管控的目的:通过多 ...
- 基于Docker的服务器搭建
-----------基于Docker的多种服务器搭建----------- 开发环境 本机上的虚拟机 Centos7.4 Docker1.13.1 Openssl1.1.1 1 Nginx 1.1 ...
- 基于docker+reveal.js搭建一个属于自己的在线ppt网站
前言 最近热衷于Docker,由于这段时间使用Docker来折腾自己的服务器,越来越感觉这是一种及其被应该推广的技术,因此想在公司内部也做一次技术分享.当然,如果只是做的PPT,我就不写这文章了.既然 ...
- 基于Docker+Jenkins+Gitlab搭建持续集成环境
随着DevOps理念和敏捷理念的发展,我们希望通过自动化技术,加快项目的迭代.尤其是当使用微服务方案后,面临在大量的项目构建和部署工作,借助于jenkins的持续集成,可以快速把应用打包成docker ...
- 基于docker环境,搭建 jetty环境, 部署java项目
前提: 1.Ubuntu 系统. 2.docker环境已经安装好. 实现步骤: 1.上docker hub 下载jetty docker 镜像. 执行命令:$ sudo docker pull jet ...
- 基于Docker的GitLab搭建
今天写一些Docker搭建GitLab,好久没有写博客园了,今天又回来了,为了学习技术? 建议使用Linux内核系统,或者虚拟机,首先安装docker环境(菜鸟教程) 一.下载镜像文件 如果慢的话,可 ...
- 基于Docker和Golang搭建Web服务器
1 场景描述 基于centos7的docker镜像搭建golang开发环境 在docker容器内,使用golang实现一个Web服务器 启动docker容器,并在容器内启动Web服务器 我购买了一个最 ...
- 【分布式】-- 基于Nacos、OpenFeign搭建的微服务抽奖系统后台小案例
1.项目介绍 最近入项目之前要求熟悉一下SpringCloud Nacos微服务基于Feign接口调用并整合Swagger2进行接口文档展示给前端,所以自己按照要求来编写并整合了一套基于SpringC ...
随机推荐
- spring aop 记录 service 方法调用时长 - 环绕通知
添加依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>sp ...
- 选择器补充与CSS属性
目录 伪元素选择器 选择器优先级 CSS属性 宽和高 字体样式 文字属性 背景属性 边框属性 display属性 盒子模型 浮动(float) 清除浮动 伪元素选择器 伪元素选择器可以通过CSS操作文 ...
- 【产品】如何写好APP描述
你有没有想过越是需要花钱购买的 App,用户会更认真阅读你的 App描述?本文列举了15个 app 描述,看看哪些是我们以前忽略了的,哪些是我们也犯过的错误.图中有红色背景的文字是需要强调的地方,这些 ...
- 树形dp基础
今天来给大家讲一下数形dp基础 树形dp常与树上问题(lca.直径.重心)结合起来 而这里只讲最最基础的树上dp 1.选课 题目描述 在大学里每个学生,为了达到一定的学分,必须从很多课程里选择一些课程 ...
- 【JSOI2016】最佳团体
思路:二分答案+动态规划(结合dfs序) 类型:选/不选:最大比值 代码: #include<stdio.h> #include<bits/stdc++.h> using na ...
- [第18届 科大讯飞杯 J] 能到达吗
能到达吗 题目链接:牛客5278 J 能到达吗 Description 给定一个 \(n\times m\) 的地图,地图的左上角为 \((1, 1)\) ,右下角为 \((n,m)\). 地图上有 ...
- docker服务部署、迁移与备份、dockerfile、私有仓库
今日内容概要 服务部署 迁移与备份 dockerfile 私有仓库 内容详细 1.服务部署 # 装 mysql redis --->源码编译安装-->启 动 # 有了docker后,容器操 ...
- Dubbo3 源码系列 Dubbo“纠葛”(入门篇)
日期 更新说明 2022年5月28日 spring xml部分解读 2022年6月3日 spring annotation部分解读 人生不相见, 动如参与商. 今夕复何夕, 共此灯烛光. 少壮能几时, ...
- 深入C++05:运算符重载
运算符重载 1.复数类 运算符重载目的:使对象运算表现得和编译器内置类型一样: 复数类例子 #include<iostream> using namespace std; class CC ...
- Python数据分析--Numpy常用函数介绍(6)--Numpy中矩阵和通用函数
在NumPy中,矩阵是 ndarray 的子类,与数学概念中的矩阵一样,NumPy中的矩阵也是二维的,可以使用 mat . matrix 以及 bmat 函数来创建矩阵. 一.创建矩阵 mat 函数创 ...