簡體   English   中英

在 Python 中使用 LDAP 檢測 Active Directory 用戶帳戶是否被鎖定

[英]Detect if an Active Directory user account is locked using LDAP in Python

我正在使用 python 的 ldap 模塊驗證用戶登錄。 當登錄失敗時,我得到一個 ldap.INVALID_CREDENTIALS 登錄,但這可能是因為密碼錯誤或帳戶被鎖定。 帳戶在第 3 次嘗試后被鎖定。

我想檢測到該帳戶已被鎖定並將其報告給沮喪的用戶,而不是相同的“無效登錄”消息。

搜索我找到的解決方案:

  • AD 不使用 userAccountControl LOCKED 標志;
  • 應該改用 lockoutTime 屬性

我應該用來查找鎖定用戶的 LDAP 查詢是:

(&(objectClass=user)(lockoutTime>=1))

或者對於特定用戶:

(&(objectClass=user)(sAMAccountName=jabberwocky)(lockoutTime>=1))

但這不起作用,查詢每次都沒有返回結果。

lockoutTime中的零值意味着它沒有被鎖定。 所以,你應該試試這個。

(&(objectClass=user)(!lockoutTime=0)) 

實際上,上述查詢仍然不是 100% 正確的。 如果您從 MSDN 閱讀細則,Microsoft 建議您將Lockout-Time屬性添加到Lockout-Duration屬性,然后將其與當前時間進行比較。 那是因為有一個叫做鎖定時間的東西。 一旦鎖定時間結束,用戶將自動解鎖。 Lockout-Duration中的零表示帳戶將永遠鎖定,直到管理員將其解鎖。

請參閱這篇MSDN 文章

此屬性值僅在帳戶登錄成功時重置。 這意味着該值可能不為零,但帳戶未被鎖定。 准確判斷賬戶是否被鎖定,必須在該時間上加上Lockout-Duration,與當前時間進行比較,考慮當地時區和夏令時。

lockoutTime是一個<not set>屬性,所以最簡單的方法是使用:

(&(objectClass=user)(lockoutDuration=*))) 

對於非空條目。

更新:

但是,當密碼過期、需要更改密碼等時,也會設置此值。

所以需要過濾:

UserPrincipal userPrincipal = new UserPrincipal(context);
bool isLocked = userPrincipal.IsAccountLockedOut();

獲取用戶因違反密碼策略而被鎖定的情況,例如錯誤輸入密碼 5 次。

我還找到了這個屬性標志列表: How to use the UserAccountControl flags

SCRIPT  0x0001  1
ACCOUNTDISABLE  0x0002  2
HOMEDIR_REQUIRED    0x0008  8
LOCKOUT 0x0010  16
PASSWD_NOTREQD  0x0020  32
PASSWD_CANT_CHANGE 0x0040   64
ENCRYPTED_TEXT_PWD_ALLOWED  0x0080  128
TEMP_DUPLICATE_ACCOUNT  0x0100  256
NORMAL_ACCOUNT  0x0200  512
INTERDOMAIN_TRUST_ACCOUNT   0x0800  2048
WORKSTATION_TRUST_ACCOUNT   0x1000  4096
SERVER_TRUST_ACCOUNT    0x2000  8192
DONT_EXPIRE_PASSWORD    0x10000 65536
MNS_LOGON_ACCOUNT   0x20000 131072
SMARTCARD_REQUIRED  0x40000 262144
TRUSTED_FOR_DELEGATION  0x80000 524288
NOT_DELEGATED   0x100000    1048576
USE_DES_KEY_ONLY    0x200000    2097152
DONT_REQ_PREAUTH    0x400000    4194304
PASSWORD_EXPIRED    0x800000    8388608
TRUSTED_TO_AUTH_FOR_DELEGATION  0x1000000   16777216
PARTIAL_SECRETS_ACCOUNT 0x04000000      67108864

您必須使用0x002對屬性userAccountControl進行二進制與運算。 為了獲得所有鎖定(即禁用)的帳戶,您可以使用

(&(objectClass=user)(userAccountControl:1.2.840.113556.1.4.803:=2))

對於操作員1.2.840.113556.1.4.803請參閱LDAP 匹配規則

此外,我發現 lockoutTime 並不能保證 AD 中的所有用戶(至少在我們的配置中),但會在達到鎖定嘗試失敗次數時創建。 因此,在檢查鎖定帳戶時,還需要檢查 None 或等效項。

使用此查詢以獲得最佳結果,

Get-ADUser -LDAPFilter "(&(objectCategory=Person)(objectClass=User)(lockoutTime>=1))" -Properties LockedOut

(&(objectClass=user)(&(lockoutTime=*)(!(lockoutTime=0))))

將返回作為用戶的對象,並且具有名為 lockoutTime 的 present 屬性,該屬性不等於 0。

像這樣做:

def islocked(self, user, basedn, conn):

    search_filter = "(&(objectCategory=Person)(objectClass=User)(lockoutTime>=1))"
    search_attribute = ["sAMAccountName"]

    try:
        conn.search(basedn,
                        search_filter,
                        attributes=search_attribute)
        results = conn.entries
    except ldap3.core.exceptions.LDAPException as e:
        print(e)
    lockedaccounts = [x['sAMAccountName'] for x in results]
    lockedaccounts = [str(x) for x in lockedaccounts]
    lockedaccounts = [x for x in lockedaccounts]
    if user in lockedaccounts:
        return True
    else:
        return False

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM