在Visual Basic中是否有办法检查用户的密码是否设置为永不在Active Directory中过期?
我找到了一种方法来查找更改的最后日期,但我找不到其他可用选项。
Dim de As DirectoryServices.DirectoryEntry = GetUser(uDetails.username)
Dim objUser = GetObject(de.Path)
If objUser.PasswordLastChanged < DateTime.Now.AddMonths(-3) Then
...
在哪里可以找到所有可用objUser
属性的列表?
答案 0 :(得分:5)
如果您使用的是.NET 3.5及更高版本,则应查看System.DirectoryServices.AccountManagement
(S.DS.AM)命名空间。在这里阅读所有相关内容:
基本上,您可以定义域上下文并轻松在AD中查找用户和/或组:
// set up domain context
PrincipalContext ctx = new PrincipalContext(ContextType.Domain);
// find a user
UserPrincipal user = UserPrincipal.FindByIdentity(ctx, "SomeUserName");
if(user != null)
{
// one of the properties exposed is "PasswordNeverExpires" (bool)
if(user.PasswordNeverExpires)
{
// do something here....
...
}
}
新的S.DS.AM让您可以轻松地与AD中的用户和群组一起玩!
答案 1 :(得分:2)
对于.NET 2.0,您可以使用一些LDAP。神奇的部分是userAccountControl:1.2.840.113556.1.4.803:=65536
。第一部分是要搜索的属性,第二部分是“按位AND”,第三部分是要检查的按位标志,在本例中是第17位。您可以在 How to query Active Directory by using a bitwise filter 中的Active Directory中按位AND和OR查看更多内容。
在下面的代码中,使用domain controller(DC)和FQDN更新SearchRoot
变量。
Imports System.DirectoryServices
Public Class Form1
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
''//Bind to the root of our domain
''// YOU_DOMAIN_CONTROLLER should be one of your DCs
''// EXAMPLE and COM are the parts of your FQDN
Dim SearchRoot As DirectoryEntry = New DirectoryEntry("LDAP://YOUR_DOMAIN_CONTROLLER/dc=EXAMPLE,dc=COM")
''//Create a searcher bound to the root
Dim Searcher As DirectorySearcher = New DirectorySearcher(SearchRoot)
''//Set our filer. The last part is dumb but that is the way that LDAP was built.
''//It basically does a bitwise AND looking for the 17th bit to be set on that property "userAccountControl" which is the "password never expires" bit
''//See this if you care to learn more http://support.microsoft.com/kb/269181
Searcher.Filter = "(&(objectCategory=person)(objectClass=user)(userAccountControl:1.2.840.113556.1.4.803:=65536))"
''//Find all of the results
Dim Results = Searcher.FindAll()
Dim DE As DirectoryEntry
''//Loop through each result
For Each R As SearchResult In Results
''//Get the result as a DirectoryEntry object
DE = R.GetDirectoryEntry()
''//Output the object name
Console.WriteLine(DE.Name)
Next
End Sub
End Class
答案 2 :(得分:1)
您可以使用最初来自here的以下代码,我已根据您的问题翻译了C#并进行了一些修改(添加了一个getter):
Dim pwdNeverExpires = getPasswordNeverExpires("Tim")
setPasswordNeverExpires("Tim", True)
' See http://msdn.microsoft.com/en-us/library/aa772300(VS.85).aspx
<Flags()> _
Private Enum ADS_USER_FLAG_ENUM
ADS_UF_SCRIPT = 1
' 0x1
ADS_UF_ACCOUNTDISABLE = 2
' 0x2
ADS_UF_HOMEDIR_REQUIRED = 8
' 0x8
ADS_UF_LOCKOUT = 16
' 0x10
ADS_UF_PASSWD_NOTREQD = 32
' 0x20
ADS_UF_PASSWD_CANT_CHANGE = 64
' 0x40
ADS_UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED = 128
' 0x80
ADS_UF_TEMP_DUPLICATE_ACCOUNT = 256
' 0x100
ADS_UF_NORMAL_ACCOUNT = 512
' 0x200
ADS_UF_INTERDOMAIN_TRUST_ACCOUNT = 2048
' 0x800
ADS_UF_WORKSTATION_TRUST_ACCOUNT = 4096
' 0x1000
ADS_UF_SERVER_TRUST_ACCOUNT = 8192
' 0x2000
ADS_UF_DONT_EXPIRE_PASSWD = 65536
' 0x10000
ADS_UF_MNS_LOGON_ACCOUNT = 131072
' 0x20000
ADS_UF_SMARTCARD_REQUIRED = 262144
' 0x40000
ADS_UF_TRUSTED_FOR_DELEGATION = 524288
' 0x80000
ADS_UF_NOT_DELEGATED = 1048576
' 0x100000
ADS_UF_USE_DES_KEY_ONLY = 2097152
' 0x200000
ADS_UF_DONT_REQUIRE_PREAUTH = 4194304
' 0x400000
ADS_UF_PASSWORD_EXPIRED = 8388608
' 0x800000
ADS_UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION = 16777216
' 0x1000000
End Enum
Protected Overridable Function getPasswordNeverExpires(ByVal userName As String) As Boolean
Const userNameString As String = "userName"
Const userFlagsString As String = "userFlags"
Dim machineName As String = Environment.MachineName
Dim userInThisComputerDirectoryEntry As DirectoryEntry = getUserInThisComputerDirectoryEntry(machineName, userName)
If userInThisComputerDirectoryEntry Is Nothing Then
Throw New ArgumentException("not found in " & machineName, userNameString)
End If
Dim userFlagsProperties As PropertyValueCollection = userInThisComputerDirectoryEntry.Properties(userFlagsString)
Dim userFlags As ADS_USER_FLAG_ENUM = CType(userFlagsProperties.Value, ADS_USER_FLAG_ENUM)
Return userFlags = (userFlags Or ADS_USER_FLAG_ENUM.ADS_UF_DONT_EXPIRE_PASSWD)
End Function
Protected Overridable Sub setPasswordNeverExpires(ByVal userName As String, ByVal passwordNeverExpires As Boolean)
Const userNameString As String = "userName"
Const userFlagsString As String = "userFlags"
Dim machineName As String = Environment.MachineName
Dim userInThisComputerDirectoryEntry As DirectoryEntry = getUserInThisComputerDirectoryEntry(machineName, userName)
If userInThisComputerDirectoryEntry Is Nothing Then
Throw New ArgumentException("not found in " & machineName, userNameString)
End If
Dim userFlagsProperties As PropertyValueCollection = userInThisComputerDirectoryEntry.Properties(userFlagsString)
Dim userFlags As ADS_USER_FLAG_ENUM = CType(userFlagsProperties.Value, ADS_USER_FLAG_ENUM)
Dim newUserFlags As ADS_USER_FLAG_ENUM = userFlags
If passwordNeverExpires Then
newUserFlags = newUserFlags Or ADS_USER_FLAG_ENUM.ADS_UF_DONT_EXPIRE_PASSWD
Else
newUserFlags = newUserFlags And (Not ADS_USER_FLAG_ENUM.ADS_UF_DONT_EXPIRE_PASSWD)
End If
userFlagsProperties.Value = newUserFlags
userInThisComputerDirectoryEntry.CommitChanges()
End Sub
Protected Overridable Function getUserInThisComputerDirectoryEntry(ByVal machineName As String, ByVal userName As String) As DirectoryEntry
Dim computerDirectoryEntry As DirectoryEntry = getComputerDirectoryEntry(machineName)
Const userSchemaClassName As String = "user"
Return computerDirectoryEntry.Children.Find(userName, userSchemaClassName)
End Function
Protected Overridable Function getComputerDirectoryEntry(ByVal machineName As String) As DirectoryEntry
'Initiate DirectoryEntry Class To Connect Through WINNT Protocol
' see: http://msdn.microsoft.com/en-us/library/system.directoryservices.directoryentry.path.aspx
Const pathUsingWinNTComputerMask As String = "WinNT://{0},computer"
Dim path As String = String.Format(pathUsingWinNTComputerMask, machineName)
Dim thisComputerDirectoryEntry As New DirectoryEntry(path)
Return thisComputerDirectoryEntry
End Function
您必须添加对System.DirectoryServices
的引用。我已经在没有Active Directory的Windows Server 2008上使用.NET Framework 4(它也应该在2.0下工作)进行了测试。但是请自行检查并随意扩展它以获取/设置其他属性或连接到其他计算机(SomeDomain/OtherComputerName
而不是Environment.MachineName
)。
答案 3 :(得分:1)
public bool isPasswordExpired(String p_UserName, String p_DomainName)
{
bool m_Check=false;
int m_Val1 = (int)de1.Properties["userAccountControl"].Value;
int m_Val2 = (int) 0x10000;
if (Convert.ToBoolean(m_Val1 & m_Val2))
{
m_Check = true;
} //end
return m_Check
}