可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm validating user logins using python's ldap module.
When the login fails, I get a ldap.INVALID_CREDENTIALS login, but this can be either because of a wrong password or because the account is locked. The account get's locked after the 3rd try.
I would like to detect that the account is locked and report that to the frustrated user, instead of the same "invalid login" message.
Searching for a solution I found:
- The userAccountControl LOCKED flag is not used by AD;
- The lockoutTime attribute should be used instead
The LDAP query I should be using to find locked users is:
(&(objectClass=user)(lockoutTime>=1))
Or for a specific user:
(&(objectClass=user)(sAMAccountName=jabberwocky)(lockoutTime>=1))
But this is not working, the query returns no results every time.
回答1:
A value of zero in lockoutTime
means it's not locked out. So, you should try this.
(&(objectClass=user)(!lockoutTime=0))
Actually, the above query is still not 100% correct. If you read the fine print from MSDN, Microsoft is suggesting you to add the Lockout-Time
attribute to the Lockout-Duration
attribute and then compare it with the current time. That's because there is such a thing called lockout duration. Once the lockout duration passes, the user is unlocked automatically. Zero in Lockout-Duration
means the account is locked forever until the administrator unlock it.
See this MSDN article
This attribute value is only reset when the account is logged onto
successfully. This means that this value may be non zero, yet the
account is not locked out. To accurately determine if the account is
locked out, you must add the Lockout-Duration to this time and compare
the result to the current time, accounting for local time zones and
daylight savings time.
回答2:
lockoutTime
is a <not set>
attribute so the easiest way is to use:
(&(objectClass=user)(lockoutDuration=*)))
for the non-empty entries.
Update:
However, this value is also set when the password expires, password needs to change etc.
So it needs to be filtered by:
UserPrincipal userPrincipal = new UserPrincipal(context);
bool isLocked = userPrincipal.IsAccountLockedOut();
to get the cases where the user is locked out because they violated the password policy e.g incorrectly entered the password 5 times.
回答3:
In addition, I found that lockoutTime is not guaranteed for all users in AD (at least in our configuration), but will be created upon reaching the number of failed lockout attempts. So in checking for locked accounts, checking for None or an equivalent will be required as well.
回答4:
use this query to get the best results,
Get-ADUser -LDAPFilter "(&(objectCategory=Person)(objectClass=User)(lockoutTime>=1))" -Properties LockedOut
回答5:
I found also this list of property flags: 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
You must make a binary-AND of property userAccountControl
with 0x002
. In order to get all locked (i.e. disabled) accounts you can use
(&(objectClass=user)(userAccountControl:1.2.840.113556.1.4.803:=2))
For operator 1.2.840.113556.1.4.803
see LDAP Matching Rules
回答6:
(&(objectClass=user)(&(lockoutTime=*)(!(lockoutTime=0))))
Will return objects which are users and have a present attribute named lockoutTime which isn't equal to 0.