检测是否在Python中使用LDAP锁定了Active Directory用户帐户

时间:2012-08-03 11:57:54

标签: python active-directory python-ldap

我正在使用python的ldap模块验证用户登录。 登录失败时,我会收到ldap.INVALID_CREDENTIALS登录信息,但这可能是因为密码错误或帐户被锁定。在第3次尝试后帐户被锁定。

我想检测到该帐户已被锁定并向受挫的用户报告,而不是相同的“无效登录”消息。

寻找我找到的解决方案:

  • AD不使用userAccountControl LOCKED标志;
  • 应改为使用lockoutTime属性

我应该用来查找锁定用户的LDAP查询是:

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

或针对特定用户:

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

但这不起作用,查询每次都不返回任何结果。

7 个答案:

答案 0 :(得分:9)

lockoutTime中的值为零意味着它没有被锁定。所以,你应该试试这个。

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

实际上,上述查询仍然不是100%正确。如果您从MSDN上阅读了细则,Microsoft建议您将Lockout-Time属性添加到Lockout-Duration属性,然后将其与当前时间进行比较。那是因为存在一种称为锁定持续时间的事情。锁定持续时间过后,用户将自动解锁。 Lockout-Duration中的零表示帐户被永久锁定,直到管理员将其解锁。

请参阅此MSDN article

  

此属性值仅在帐户登录时重置   成功。这意味着这个值可能不为零,但是   帐户未被锁定。要准确确定帐户是否正确   锁定,您必须将锁定持续时间添加到此时间并进行比较   结果到当前时间,占当地时区和   夏令时。

答案 1 :(得分:4)

lockoutTime<not set>属性,因此最简单的方法是使用:

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

表示非空条目。

<强>更新

但是,当密码过期,密码需要更改等时,也会设置此值。

因此需要通过以下方式进行过滤:

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

获取用户被锁定的情况,因为他们违反了密码政策,例如错误地输入密码5次。

答案 2 :(得分:3)

此外,我发现AD中的所有用户都不能保证lockoutTime(至少在我们的配置中),但是会在达到失败的锁定尝试次数时创建。因此,在检查锁定帐户时,还需要检查“无”或等效帐户。

答案 3 :(得分:2)

我还找到了这个属性标记列表: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

您必须使用userAccountControl创建属性0x002的二进制AND。为了获得所有锁定(即禁用)帐户,您可以使用

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

对于运营商1.2.840.113556.1.4.803,请参阅LDAP Matching Rules

答案 4 :(得分:2)

这样做:

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

答案 5 :(得分:1)

使用此查询获得最佳效果

Get-ADUser -LDAPFilter“(&amp;(objectCategory = Person)(objectClass = User)(lockoutTime&gt; = 1))” - 属性LockedOut

答案 6 :(得分:0)

(及(objectClass的=用户)(&安培;!(lockoutTime = *)((lockoutTime = 0))))

将返回作为用户且具有名为lockoutTime的当前属性的对象,该属性不等于0.