在 VB.NET 中使用 Active Directory






4.80/5 (38投票s)
本文介绍如何在 Windows 2000+ 网络中执行 Active Directory 中的任务。
引言
本文讨论使用 VB.NET 在 Active Directory (AD) 中进行操作,如何查询 AD、查询组、成员、添加用户、暂停用户以及更改用户密码。Active Directory 是 Windows 的目录服务,它提供了整个网络的统一视图。使用 Active Directory 就像操作数据库一样,您根据要检索的信息编写查询。
访问 Active Directory 有三种接口
- LDAP:轻量级目录访问协议 (LDAP) 是一个运行在 TCP/IP 层(或堆栈)之上的服务协议,它提供了一个用于访问、搜索和修改 Internet 目录的接口,并且基于客户端-服务器模型。
- ADSI:Active Directory 服务接口 (ADSI) 是一组 COM 组件(或接口),用于访问网络设置中不同网络提供商的目录服务;它旨在提供一个单一的、集中的接口来访问和管理网络资源。
- System.DirectoryServices:.NET Framework 内置的
System.DirectoryServices
命名空间旨在提供对 LDAP 目录(Active Directory)的编程访问,并基于 ADSI API 构建。
背景
最近,在工作中,我被分配了一项任务,为我目前编写的应用程序创建一个安全系统。我更进一步,希望确保即使应用程序被带到公司以外的地方,也无法运行;这时我便想到了基于公司网络 Active Directory 来构建我的安全系统。这将阻止个人将应用程序带出公司并尝试使用它,无论是出于恶意目的还是仅仅为了“玩弄”。这似乎也是最安全的方式,因为只有少数人拥有以任何方式更改 Active Directory 的权限。尽管 .NET Framework 中有大量用于操作 Active Directory 的内置功能,但我还是决定创建自己的对象,一个包装 .NET 中 System.DirectoryServices
命名空间的包装器。
使用此应用程序的员工都在同一个部门。他们,又在数据库中拥有自己的表,其中包含有关用户的特定信息,例如访问级别、队列等。应用程序首次启动时,安全性基于用户在数据库中的访问级别。这将决定用户可以访问的内容。当应用程序启动时,它会检查用户登录的名称。
Environment.UserName.ToString
然后,它会拆分用户名(在我的公司,您的用户名是 FirstName.LastName)以获取名字和姓氏,并查询上述表以根据前面检索到的名字和姓氏检索用户的访问级别。我希望保留访问级别安全,因为这确保了人们不会访问他们不应该访问的应用程序区域,因此我在用户表中添加了一个新列来存储他们的 AD 登录名(数据类型为 SysUser
)。从那里,我将使用 Environment.UserName.ToString
再次检索他们登录时使用的用户名。有了这个,我将从用户表中检索他们的 LoginName
,并查询 Active Directory 以确保这是一个有效的网络帐户,并且他们有权限使用此应用程序。
在处理此 AD 安全性时,我发现了 System.DirectoryServices
命名空间的真正强大之处;使用它可以:
- 向网络添加新用户
- 暂停用户的帐户
- 启用用户的帐户
- 重置用户密码
- 更新用户帐户
- 将用户添加到特定组
- 从组中删除用户
- 检索用户所属的所有组的列表
- 检索连接到网络的所有计算机
- 确定用户的帐户是否已禁用
- 检查用户帐户是否处于活动状态(执行基本登录)
等等。在本文中,我将带您逐步了解如何连接到 Active Directory、在 Active Directory 中搜索用户、禁用用户帐户、重置用户密码、为新用户设置邮箱、显示网络上的所有计算机以及将用户添加到 Active Directory 中的特定组。
使用代码
我先来介绍这个辅助程序,许多过程/函数都会调用这个辅助程序。这个辅助程序的任务很简单,就是设置用户 AD 帐户的属性。这可以节省属性需要设置或更改时的时间和代码。此辅助程序会搜索提供的属性,以查看它是否已存在于用户的帐户中;如果不存在,则添加并设置值;如果已存在,则更新该属性的值。
''' <summary>
''' Helper method that sets properties for AD users.
''' </summary>
''' <param name="de">DirectoryEntry to use</param>
''' <param name="pName">Property name to set</param>
''' <param name="pValue">Value of property to set</param>
Public Shared Sub SetADProperty(ByVal de As DirectoryEntry, _
ByVal pName As String, ByVal pValue As String)
'First make sure the property value isnt "nothing"
If Not pValue Is Nothing Then
'Check to see if the DirectoryEntry contains this property already
If de.Properties.Contains(pName) Then 'The DE contains this property
'Update the properties value
de.Properties(pName)(0) = pValue
Else 'Property doesnt exist
'Add the property and set it's value
de.Properties(pName).Add(pValue)
End If
End If
End Sub
使用 Active Directory 时要做的第一件事就是建立到 Active Directory 的连接。
''' <summary>
''' Method used to create an entry to the AD.
''' Replace the path, username, and password with the ones specific to you
'''and your network.
'''Hardcoding a username & password can be viewed as a security risk
''' so you may want to store this in an encrypted file.
''' </summary>
''' <returns> A DirectoryEntry </returns>
Public Shared Function GetDirectoryEntry() As DirectoryEntry
Dim dirEntry As DirectoryEntry = New DirectoryEntry()
dirEntry.Path = "LDAP://192.168.1.1/CN=Users;DC=Yourdomain"
dirEntry.Username = "yourdomain\sampleuser"
dirEntry.Password = "samplepassword"
Return dirEntry
End Function
如上所述,当我向用户表添加新列以存储其 AD 登录名(SQL2000/2005 内置的 SysUser
数据类型)时,此数据类型以 DOMAIN\USERNAME 的格式存储值。在 Active Directory 中搜索特定用户时,您需要剥离“DOMAIN\”,所以我创建了以下函数来为我完成此操作。
''' <summary>
''' Function to extract just the login from the provided string
''' (given in the format DOMAIN\USERNAME)
''' </summary>
''' <param name="path">Full AD login of the user</param>
''' <returns>The login with the "DOMAIN\" stripped</returns>
Public Function ExtractUserName(ByVal path As String) As String
Dim userPath As String() = path.Split(New Char() {"\"c})
Return userPath((userPath.Length - 1))
End Function
为了在 Active Directory 中搜索提供的用户,我创建了以下函数。
''' <summary>
''' Function to search the Active Directory and ensure the Login provided
''' in Agent Process is a valid one. The search is performed
''' to see if the login provided exists for the first and last name of
''' the user being queried
''' </summary>
''' <param name="loginName">Login of the associate to search for</param>
''' <param name="givenName">First name fo the associate being added</param>
''' <param name="surName">Last name of the associate being added</param>
''' <returns>True or False depending if the login provided is a valid one</returns>
Public Function IsValidADLogin(ByVal loginName As String, _
ByVal givenName As String, ByVal surName As String) As Boolean
Try
Dim search As New DirectorySearcher()
search.Filter = String.Format("(&(SAMAccountName={0}) & _
(givenName={1})(sn={2}))", _
ExtractUserName(loginName), givenName, surName)
search.PropertiesToLoad.Add("cn")
search.PropertiesToLoad.Add("SAMAccountName") 'Users login name
search.PropertiesToLoad.Add("givenName") 'Users first name
search.PropertiesToLoad.Add("sn") 'Users last name
'Use the .FindOne() Method to stop as soon as a match is found
Dim result As SearchResult = search.FindOne()
If result Is Nothing Then
Return False
Else
Return True
End If
Catch ex As Exception
MessageBox.Show(ex.Message, "Active Directory Error", & _
MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1)
End Try
End Function
通过此函数,如果找到所选用户,则返回 True
,否则返回 False
,让程序员知道这不是 Active Directory 中的有效用户。如前所述,访问 Active Directory 有很多事情可以做;我现在将向您介绍 System.DirectoryServices
命名空间的可能操作示例。
第一个示例是创建一个新的 AD 用户;要使用此功能,您必须拥有具有添加用户正确权限的帐户。(所有帐户都可以访问搜索 Active Directory,只有管理员组的成员才能执行许多功能,包括创建新的 AD 用户。)最简单的方法是将具有 DomainAdmin 权限的用户帐户的权限委派给正在运行程序的线程。以下代码将为您处理此事。
'' <summary>
''' Establish identity (principal) and culture for a thread.
''' </summary>
Public Shared Sub SetCultureAndIdentity()
AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal)
Dim principal As WindowsPrincipal = CType(Thread.CurrentPrincipal, WindowsPrincipal)
Dim identity As WindowsIdentity = CType(principal.Identity, WindowsIdentity)
System.Threading.Thread.CurrentThread.CurrentCulture = New CultureInfo("en-US")
End Sub
1. 创建新的 Active Directory 用户帐户
需要四个过程来执行此操作。第一个过程 CreateADAccount
是实际创建新用户的过程。它依赖于其他三个过程:SetPassword
用于设置新用户的密码,EnableAccount
用于启用新帐户,AddUserToGroup
用于将新用户添加到指定的 Active Directory 组。
首先,我们来看 CreateADAccount
过程。
''' <summary>
''' Procedure to create a new Active Directory account
''' </summary>
''' <param name="sUserName">Username for the new account</param>
''' <param name="sPassword">Password for the new account</param>
''' <param name="sFirstName">First name of the user</param>
''' <param name="sLastName">Last name of the user</param>
''' <param name="sGroupName">Group to add the user to</param>
''' <remarks></remarks>
Public Sub CreateAdAccount(ByVal sUserName As String, _
ByVal sPassword As String, _
ByVal sFirstName As String, ByVal sLastName As String, _
ByVal sGroupName As String)
Dim catalog As Catalog = New Catalog()
Dim dirEntry As New DirectoryEntry()
' 1. Create user account
Dim adUsers As DirectoryEntries = dirEntry.Children
Dim newUser As DirectoryEntry = adUsers.Add("CN=" & sUserName, "user")
' 2. Set properties
SetProperty(newUser, "givenname", sFirstName)
SetProperty(newUser, "sn", sLastName)
SetProperty(newUser, "SAMAccountName", sUserName)
SetProperty(newUser, "userPrincipalName", sUserName)
newUser.CommitChanges()
' 3. Set the password
SetPassword(newUser, sPassword)
' 5. Add the user to the specified group
AddUserToGroup(dirEntry, newUser, sGroupName)
' 6. Enable the account
EnableAccount(newUser)
' 7. Close & clean-up
newUser.Close()
dirEntry.Close()
End Sub
过程末尾的三行高亮代码引用了上面提到的三个附加过程,第一个是 SetPassword
。
'' <summary>
''' Method to set a user's password
''' <param name="dEntry">DirectoryEntry to use</param>
''' <param name="sPassword">Password for the new user</param>
Private Shared Sub SetPassword(ByVal dEntry As DirectoryEntry, _
ByVal sPassword As String)
Dim oPassword As Object() = New Object() {sPassword}
Dim ret As Object = dEntry.Invoke("SetPassword", oPassword)
dEntry.CommitChanges()
End Sub
第二个过程是 EnableAccount
,负责启用新帐户以便用户可以使用它。
''' <summary>
''' Method to enable a user account in the AD.
''' </summary>
''' <param name="de"></param>
Private Shared Sub EnableAccount(ByVal de As DirectoryEntry)
'UF_DONT_EXPIRE_PASSWD 0x10000
Dim exp As Integer = CInt(de.Properties("userAccountControl").Value)
de.Properties("userAccountControl").Value = exp Or &H1
de.CommitChanges()
'UF_ACCOUNTDISABLE 0x0002
Dim val As Integer = CInt(de.Properties("userAccountControl").Value)
de.Properties("userAccountControl").Value = val And Not &H2
de.CommitChanges()
End Sub
第三个也是最后一个过程是 AddUserToGroup
,它将新用户添加到指定的 Active Directory 组。
'' <summary>
''' Method to add a user to a group
''' </summary>
''' <param name="de">DirectoryEntry to use</param>
''' <param name="deUser">User DirectoryEntry to use</param>
''' <param name="GroupName">Group Name to add user to</param>
Public Shared Sub AddUserToGroup(ByVal de As DirectoryEntry, _
ByVal deUser As DirectoryEntry, ByVal GroupName As String)
Dim deSearch As DirectorySearcher = New DirectorySearcher()
deSearch.SearchRoot = de
deSearch.Filter = "(&(objectClass=group) (cn=" & GroupName & "))"
Dim results As SearchResultCollection = deSearch.FindAll()
Dim isGroupMember As Boolean = False
If results.Count > 0 Then
Dim group As New DirectoryEntry(results(0).Path)
Dim members As Object = group.Invoke("Members", Nothing)
For Each member As Object In CType(members, IEnumerable)
Dim x As DirectoryEntry = New DirectoryEntry(member)
Dim name As String = x.Name
If name <> deUser.Name Then
isGroupMember = False
Else
isGroupMember = True
Exit For
End If
Next member
If (Not isGroupMember) Then
group.Invoke("Add", New Object() {deUser.Path.ToString()})
End If
group.Close()
End If
Return
End Sub
2. 禁用用户帐户
通过 System.DirectoryServices
命名空间,您不仅可以创建新的 Active Directory 用户,还可以禁用用户的 Active Directory 帐户。要禁用用户的 Active Directory 帐户,请使用以下过程。
''' <summary>
''' Method that disables a user account in the AD
''' and hides user's email from Exchange address lists.
''' </summary>
''' <param name="sLogin">Login of the user to disable</param>
Public Sub DisableAccount(ByVal sLogin As String)
' 1. Search the Active Directory for the desired user
Dim dirEntry As DirectoryEntry = GetDirectoryEntry()
Dim dirSearcher As DirectorySearcher = New DirectorySearcher(dirEntry)
dirSearcher.Filter = "(&(objectCategory=Person)(objectClass=user) _
(SAMAccountName=" & sLogin & "))"
dirSearcher.SearchScope = SearchScope.Subtree
Dim results As SearchResult = dirSearcher.FindOne()
' 2. Check returned results
If Not results Is Nothing Then
' 2a. User was returned
Dim dirEntryResults As DirectoryEntry = _
GetDirectoryEntry(results.Path)
Dim iVal As Integer = _
CInt(dirEntryResults.Properties("userAccountControl").Value)
' 3. Disable the users account
dirEntryResults.Properties("userAccountControl").Value = iVal Or &H2
' 4. Hide users email from all Exchange Mailing Lists
dirEntryResults.Properties("msExchHideFromAddressLists").Value = "TRUE"
dirEntryResults.CommitChanges()
dirEntryResults.Close()
End If
dirEntry.Close()
End Sub
3. 更新/修改用户的 Active Directory 帐户信息
通过 System.DirectoryServices
命名空间,您不仅可以创建新的 Active Directory 用户和禁用用户的 Active Directory 帐户,还可以更新/修改用户的 Active Directory 帐户属性。此过程中的属性将与您的 Active Directory 中的属性不同,因此您需要访问权限才能查看可用属性;我列出的只是可能属性的一小部分。要更新/修改用户的 Active Directory 帐户,请使用以下过程。
''' <summary>
''' Method that updates user's properties
''' </summary>
''' <param name="userLogin">Login of the user to update</param>
''' <param name="userDepartment">New department of the specified user</param>
''' <param name="userTitle">New title of the specified user</param>
''' <param name="userPhoneExt">New phone extension of the specified user</param>
Public Sub UpdateUserADAccount(ByVal userLogin As String, _
ByVal userDepartment As String, _
ByVal userTitle As String, ByVal userPhoneExt As String)
Dim dirEntry As DirectoryEntry = GetDirectoryEntry()
Dim dirSearcher As DirectorySearcher = New DirectorySearcher(dirEntry)
' 1. Search the Active Directory for the speied user
dirSearcher.Filter = "(&(objectCategory=Person)(objectClass=user) _
(SAMAccountName=" & userLogin & "))"
dirSearcher.SearchScope = SearchScope.Subtree
Dim searchResults As SearchResult = dirSearcher.FindOne()
If Not searchResults Is Nothing Then
Dim dirEntryResults As New DirectoryEntry(results.Path)
'The properties listed here may be different then the
'properties in your Active Directory so they may need to be
'changed according to your network
' 2. Set the new property values for the specified user
SetProperty(dirEntryResults, "department", userDepartment)
SetProperty(dirEntryResults, "title", userTitle)
SetProperty(dirEntryResults, "phone", userPhoneExt)
' 3. Commit the changes
dirEntryResults.CommitChanges()
' 4. Close & Cleanup
dirEntryResults.Close()
End If
' 4a. Close & Cleanup
dirEntry.Close()
End Sub
4. 列出 Active Directory 中的所有计算机
使用 .NET Framework 中的 System.DirectoryServices
命名空间,您还可以创建 Active Directory 中所有计算机的列表。创建此函数时,我用每个计算机名填充了一个 Collection
,然后我可以枚举 Collection
并用从 Active Directory 查询返回的名称填充控件(如 ListBox
、DataGridView
等)。使用的函数是:
''' <summary>
''' Function to query the Active Directory and return all the computer names
'''on the network
''' </summary>
''' <returns>A collection populated with all the computer names</returns>
Public Shared Function ListAllADComputers() As Collection
Dim dirEntry As DirectoryEntry = GetDirectoryEntry()
Dim pcList As New Collection()
' 1. Search the Active Directory for all objects with type of computer
Dim dirSearcher As DirectorySearcher = New DirectorySearcher(dirEntry)
dirSearcher.Filter = ("(objectClass=computer)")
' 2. Check the search results
Dim dirSearchResults As SearchResult
' 3. Loop through all the computer names returned
For Each dirSearchResults In dirSearcher.FindAll()
' 4. Check to ensure the computer name isnt already listed in
'the collection
If Not pcList.Contains(dirSearchResults.GetDirectoryEntry().Name.ToString()) Then
' 5. Add the computer name to the collection (since
'it dont already exist)
pcList.Add(dirSearchResults.GetDirectoryEntry().Name.ToString())
End If
Next
' 6. Return the results
Return pcList
End Function
5. 列出用户所属的所有组
以下函数返回用户所属组的 Collection
。我选择了 Collection 而不是用组名连接的字符串,因为这样,我就可以用值填充控件。
''' <summary>
''' Function to return all the groups the user is a member od
''' </summary>
''' <param name="_path">Path to bind to the AD</param>
''' <param name="username">Username of the user</param>
''' <param name="password">password of the user</param>
Private Function GetGroups(ByVal _path As String, ByVal username As String, _
ByVal password As String) As Collection
Dim Groups As New Collection
Dim dirEntry As New _
System.DirectoryServices.DirectoryEntry(_path, username, password)
Dim dirSearcher As New DirectorySearcher(dirEntry)
dirSearcher.Filter = String.Format("(sAMAccountName={0}))", username)
dirSearcher.PropertiesToLoad.Add("memberOf")
Dim propCount As Integer
Try
Dim dirSearchResults As SearchResult = dirSearcher.FindOne()
propCount = dirSearchResults.Properties("memberOf").Count
Dim dn As String
Dim equalsIndex As String
Dim commaIndex As String
For i As Integer = 0 To propCount - 1
dn = dirSearchResults.Properties("memberOf")(i)
equalsIndex = dn.IndexOf("=", 1)
commaIndex = dn.IndexOf(",", 1)
If equalsIndex = -1 Then
Return Nothing
End If
If Not Groups.Contains(dn.Substring((equalsIndex + 1), _
(commaIndex - equalsIndex) - 1)) Then
Groups.Add(dn.Substring((equalsIndex + 1), & _
(commaIndex - equalsIndex) - 1))
End If
Next
Catch ex As Exception
If ex.GetType Is GetType(System.NullReferenceException) Then
MessageBox.Show("Selected user isn't a member of any groups " & _
"at this time.", "No groups listed", _
MessageBoxButtons.OK, MessageBoxIcon.Error)
'they are still a good user just does not
'have a "memberOf" attribute so it errors out.
'code to do something else here if you want
Else
MessageBox.Show(ex.Message.ToString, "Search Error", & _
MessageBoxButtons.OK, MessageBoxIcon.Error)
End If
End Try
Return Groups
End Function
End Class
6. 确定用户帐户是否已被禁用
以下函数可用于确定所选用户的帐户是否已被禁用。
''' <summary>
''' This will perfrom a logical operation on the userAccountControl values
''' to see if the user account is enabled or disabled.
''' The flag for determining if the
''' account is active is a bitwise value (decimal =2)
''' </summary>
''' <param name="userAccountControl"></param>
''' <returns></returns>
Public Shared Function IsAccountActive(ByVal userAccountControl As Integer) _
As Boolean
Dim accountDisabled As Integer = & _
Convert.ToInt32(ADAccountOptions.UF_ACCOUNTDISABLE)
Dim flagExists As Integer = userAccountControl And accountDisabled
'if a match is found, then the disabled
'flag exists within the control flags
If flagExists > 0 Then
Return False
Else
Return True
End If
End Function
7. 从特定组中删除用户
以下函数可用于从特定组中删除用户。
''' <summary>
''' This will perform the removal of a user from the specified group
''' </summary>
''' <param name="UserName">Username of the user to remove</param>
''' <param name="GroupName">Groupname to remove them from</param>
''' <remarks></remarks>
Public Shared Sub RemoveUserFromGroup(ByVal UserName As String, _
ByVal GroupName As String)
Dim Domain As New String("")
'get reference to group
Domain = "/CN=" + GroupName + ",CN=Users," + GetLDAPDomain()
Dim oGroup As DirectoryEntry = GetDirectoryObject(Domain)
'get reference to user
Domain = "/CN=" + UserName + ",CN=Users," + GetLDAPDomain()
Dim oUser As DirectoryEntry = GetDirectoryObject(Domain)
'Add the user to the group via the invoke method
oGroup.Invoke("Remove", New Object() {oUser.Path.ToString()})
oGroup.Close()
oUser.Close()
End Sub
8. 检查用户帐户以查看其是否处于活动状态
以下过程执行模拟登录到用户帐户,以查看其是否为有效帐户以及是否处于活动状态。此方法调用其他函数才能正常工作:GetUser
和重载的 GetUser
、IsUserValid
和 IsAccountActive
;所有这些都将在下面列出。
''' <summary>
''' This method will not actually log a user in, but will perform tests to ensure
''' that the user account exists (matched by both the username and password), and also
''' checks if the account is active.
''' </summary>
''' <param name="UserName"></param>
''' <param name="Password"></param>
Public Shared Function Login(ByVal UserName As String, ByVal Password As String) _
As ADWrapper.LoginResult
'first, check if the logon exists based on the username and password
If IsUserValid(UserName, Password) Then
Dim dirEntry As DirectoryEntry = GetUser(UserName)
If Not dirEntry Is Nothing Then
'convert the accountControl value so that a logical
'operation can be performed
'to check of the Disabled option exists.
Dim accountControl As Integer = & _
Convert.ToInt32(dirEntry.Properties("userAccountControl")(0))
dirEntry.Close()
'if the disabled item does not exist then the account is active
If Not IsAccountActive(accountControl) Then
Return LoginResult.LOGIN_USER_ACCOUNT_INACTIVE
Else
Return LoginResult.LOGIN_OK
End If
Else
Return LoginResult.LOGIN_USER_DOESNT_EXIST
End If
Else
Return LoginResult.LOGIN_USER_DOESNT_EXIST
End If
End Function
GetUser(+重载版本)
''' <summary>
''' This will return a DirectoryEntry object if the user does exist
''' </summary>
''' <param name="UserName"></param>
''' <returns></returns>
Public Shared Function GetUser(ByVal UserName As String) As DirectoryEntry
'create an instance of the DirectoryEntry
Dim dirEntry As DirectoryEntry = GetDirectoryObject("/" + GetLDAPDomain())
'create instance fo the direcory searcher
Dim dirSearch As New DirectorySearcher(dirEntry)
dirSearch.SearchRoot = dirEntry
'set the search filter
dirSearch.Filter = "(&(objectCategory=user)(cn=" + UserName + "))"
'deSearch.SearchScope = SearchScope.Subtree;
'find the first instance
Dim searchResults As SearchResult = dirSearch.FindOne()
'if found then return, otherwise return Null
If Not searchResults Is Nothing Then
'de= new DirectoryEntry(results.Path,ADAdminUser, _
ADAdminPassword,AuthenticationTypes.Secure);
'if so then return the DirectoryEntry object
Return searchResults.GetDirectoryEntry()
Else
Return Nothing
End If
End Function
''' <summary>
''' Override method which will perfrom query based on combination of username
'''and password This is used with the login process to validate the user
'''credentials and return a user object for further validation. This is
'''slightly different from the other GetUser... methods as this will use the
'''UserName and Password supplied as the authentication to check if the user
'''exists, if so then the users object will be queried using these
'''credentials
''' </summary>
''' <param name="UserName"></param>
''' <param name="password"></param>
''' <returns></returns>
Public Shared Function GetUser(ByVal UserName As String, ByVal Password _
As String) As DirectoryEntry
'create an instance of the DirectoryEntry
Dim dirEntry As DirectoryEntry = GetDirectoryObject(UserName, Password)
'create instance fo the direcory searcher
Dim dirSearch As New DirectorySearcher()
dirSearch.SearchRoot = dirEntry
'set the search filter
dirSearch.Filter = "(&(objectClass=user)(cn=" + UserName + "))"
dirSearch.SearchScope = SearchScope.Subtree
'set the property to return
'deSearch.PropertiesToLoad.Add("givenName");
'find the first instance
Dim searchResults As SearchResult = dirSearch.FindOne()
'if a match is found, then create directiry object and return,
'otherwise return Null
If Not searchResults Is Nothing Then
'create the user object based on the admin priv.
dirEntry = New DirectoryEntry(searchResults.Path, ADAdminUser, _
ADAdminPassword, AuthenticationTypes.Secure)
Return dirEntry
Else
Return Nothing
End If
End Function
IsUserValid
此过程将检查以确保它是有效的用户帐户。
''' <summary>
''' This method will attempt to log in a user based on the username and
''' password
''' to ensure that they have been set up within the Active Directory.
'''This is the basic UserName, Password
''' check.
''' </summary>
''' <param name="UserName"></param>
''' <param name="Password"></param>
Public Shared Function IsUserValid(ByVal UserName As String, _
ByVal Password As String) As Boolean
Try
'if the object can be created then return true
Dim dirUser As DirectoryEntry = GetUser(UserName, Password)
dirUser.Close()
Return True
Catch generatedExceptionName As Exception
'otherwise return false
Return False
End Try
End Function
IsUserActive
这将检查以查看它是否为活动用户帐户。
''' <summary>
''' This will perfrom a logical operation on the userAccountControl values
''' to see if the user account is enabled or disabled. The flag for determining if the
''' account is active is a bitwise value (decimal =2)
''' </summary>
''' <param name="userAccountControl"></param>
''' <returns></returns>
Public Shared Function IsAccountActive(ByVal userAccountControl As Integer) _
As Boolean
Dim accountDisabled As Integer = _
Convert.ToInt32(ADAccountOptions.UF_ACCOUNTDISABLE)
Dim flagExists As Integer = userAccountControl And accountDisabled
'if a match is found, then the disabled flag exists within the control flags
If flagExists > 0 Then
Return False
Else
Return True
End If
End Function
关注点
这实际上是关于在 VB.NET 中使用 Active Directory 的一个高层概述。我下载的封装 DLL 中还有更多功能,例如查询 AD 中的所有活动组,返回指定组的所有成员用户等。乍一看,使用 Active Directory 可能会令人生畏,但不要因此而退缩。一旦您学会了少量内容,它就不比从数据库中查询信息更复杂了。
*特别感谢 Erika Ehrli,她的文章 VBDotNetHeaven.Com 帮助我解决了一些我曾苦苦挣扎的 AD 逻辑问题。*
祝您编码愉快!