ldap(light directory access portocol)是輕量目錄訪問協議,基于x.500標準,支持tcp/ip。
ldap目錄以樹狀的層次結構來存儲數據。每個目錄記錄都有標識名(distinguished name,簡稱dn),用來讀取單個記錄,
一般是這樣的:
1
|
cn = username,ou = people,dc = test,dc = com |
幾個關鍵字的含義如下:
- base dn:ldap目錄樹的最頂部,也就是樹的根,是上面的dc=test,dc=com部分,一般使用公司的域名,也可以寫做o=test.com,前者更靈活一些。
- dc::domain component,域名部分。
- ou:organization unit,組織單位,用于將數據區分開。
- cn:common name,一般使用用戶名。
- uid:用戶id,與cn的作用類似。
- sn:surname, 姓。
- rdn:relative dn,dn中與目錄樹的結構無關的部分,通常存在cn或者uid這個屬性里。
所以上面的dn代表一條記錄,代表一位在test.com公司people部門的用戶username。
python-ldap
python一般使用python-ldap庫操作ldap,文檔:https://www.python-ldap.org/en/latest/index.html。
下載:
1
|
pip install python - ldap |
還要安裝一些環境,ubuntu:
1
2
3
|
apt - get install build - essential python3 - dev python2. 7 - dev \ libldap2 - dev libsasl2 - dev slapd ldap - utils python - tox \ lcov valgrind |
centos:
1
2
|
yum groupinstall "development tools" yum install openldap - devel python - devel |
獲取ldap地址后即可與ldap建立連接:
1
2
|
import ldap ldapconn = ldap.initialize( 'ldap://192.168.1.111:389' ) |
綁定用戶,可用于用戶驗證,用戶名必須是dn:
1
|
ldapconn.simple_bind_s( 'cn=username,ou=people,dc=test,dc=com' , pwd) |
成功認證時會返回一個tuple:
1
|
( 97 , [], 1 , []) |
驗證失敗會報異常ldap.invalid_credentials:
1
|
{ 'desc' : u 'invalid credentials' } |
注意驗證時傳空值驗證也是可以通過的,注意要對dn和pwd進行檢查。
查詢ldap用戶信息時,需要登錄管理員rootdn帳號:
1
2
3
4
5
|
ldapconn.simple_bind_s( 'cn=admin,dc=test,dc=com' , 'adminpwd' ) searchscope = ldap.scope_subtree searchfilter = 'cn=username' base_dn = 'ou=people,dc=test,dc=com' print ldapconn.search_s(base_dn, searchscope, searchfilter, none) |
添加用戶add_s(dn, modlist),dn為要添加的條目dn,modlist為存儲信息:
1
2
3
4
5
6
7
8
|
dn = 'cn=test,ou=people,dc=test,dc=com' modlist = [ ( 'objectclass' , [ 'person' , 'organizationalperson' ], ( 'cn' , [ 'test' ]), ( 'uid' , [''testuid]), ( 'userpassword' , [ 'pwd' ]), ] result = ldapconn.add_s(dn, modlist) |
添加成功會返回元組:
1
|
( 105 , [], 2 , []) |
失敗會報ldap.ldaperror異常
django使用ldap驗證
一個很簡單的ldap驗證backend:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
import ldap class ldapbackend( object ): """ authenticates with ldap. """ _connection = none _connection_bound = false def authenticate( self , username = none, passwd = none, * * kwargs): if not username or not passwd: return none if self ._authenticate_user_dn(username, passwd): user = self ._get_or_create_user(username, passwd) return user else : return none @property def connection( self ): if not self ._connection_bound: self ._bind() return self ._get_connection() def _bind( self ): self ._bind_as( ldap_config[ 'username' ], ldap_config[ 'password' ], true ) def _bind_as( self , bind_dn, bind_password, sticky = false): self ._get_connection().simple_bind_s( bind_dn, bind_password ) self ._connection_bound = sticky def _get_connection( self ): if not self ._connection: self ._connection = ldap.initialize(ldap_config[ 'host' ]) return self ._connection def _authenticate_user_dn( self , username, passwd): bind_dn = 'cn=%s,%s' % (username, ldap_config[ 'base_dn' ]) try : self ._bind_as(bind_dn, passwd, false) return true except ldap.invalid_credentials: return false def _get_or_create_user( self , username, passwd): # 獲取或者新建user return user |
不想自己寫的話,django與flask都有現成的庫:
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:https://www.cnblogs.com/linxiyue/p/10250243.html