繁体   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