简体   繁体   English

C#查询Active Directory

[英]C# Query Active Directory

I am developing an Intranet web app and I am using the System.DirectoryServices.AccountManagement to query the Active Directory of the current user's Windows Identity. 我正在开发一个Intranet Web应用程序,并且正在使用System.DirectoryServices.AccountManagement来查询当前用户的Windows身份的Active Directory。 On my development machine, the query returns a UserPrincipal populated with the user information. 在我的开发机器上,查询返回一个UserPrincipal,其中填充了用户信息。 The application directory under Default Web Site of the local IIS on my machine has Windows authentication and Impersonate enabled. 我的计算机上本地IIS的“默认网站”下的应用程序目录已启用Windows身份验证和“模拟”。 However, when the application is published to our hosting IIS, the Principal is returned but with no user information. 但是,当应用程序发布到我们的托管IIS时,将返回Principal,但没有用户信息。 Does anyone know why? 有人知道为什么吗? The server admin said that I have to use a service account and password to connect to AD server to do the query. 服务器管理员说,我必须使用服务帐户和密码连接到AD服务器才能执行查询。 If it's true, then querying from my local machine should have not worked either. 如果是真的,那么从我的本地计算机查询也不应该起作用。 Is this correct? 这个对吗?

public class LDAP_Helper
{
    public string NetworkName { get; private set; }
    public string LastName { get; private set; }
    public string FirstName { get; private set; }
    public string MiddleName { get; private set; }
    public string Email { get; private set; }
    public string VoicePhone { get; private set; }

    public LDAP_Helper()
    {
        using (var context = new System.DirectoryServices.AccountManagement.PrincipalContext(
            System.DirectoryServices.AccountManagement.ContextType.Domain))
        {
            try
            {
                string currentUser = HttpContext.Current.User.Identity.Name;
                var principal = System.DirectoryServices.AccountManagement.UserPrincipal.FindByIdentity(context, currentUser);

                NetworkName = principal.SamAccountName;
                LastName = principal.Surname;
                FirstName = principal.GivenName;
                MiddleName = principal.MiddleName;
                Email = principal.EmailAddress;
                VoicePhone = principal.VoiceTelephoneNumber;
            }
            catch { }

        }

        return;
    }

Web.config settig: Web.config settig:

    <identity impersonate="true" />

IIS7身份验证IIS7应用程序池

First off, you catch all exceptions and do nothing about them, so that's not good. 首先,您会捕获所有异常,而对它们不执行任何操作,所以这不好。 If you did handle the exception, you would probably get first a PrincipalOperationException telling you that no user by that name was found, and then 6 NullReferenceExceptions because your principal variable is Nothing. 如果确实处理了该异常,则可能首先会收到一个PrincipalOperationException,告诉您找不到该名称的用户,然后是6个NullReferenceExceptions,因为您的主体变量为Nothing。 I am not a C# guy, but this VB bit should not be too hard to translate. 我不是C#专家,但是这个VB位应该不太难翻译。 You should also specify the domain when you create the context to avoid problems on networks with multiple domain controllers. 创建上下文时,还应该指定域,以避免在具有多个域控制器的网络上出现问题。 You do need to have permissions to query the Active Directory server, but by no means does that have to be a service account. 您确实需要具有查询Active Directory服务器的权限,但是决不是必须是服务帐户。 Just a regular account with the appropriate group membership. 只是具有适当组成员身份的普通帐户。

 Public Function FindUserPrincipal(ByVal userName As String) As UserPrincipal
    Try
        Return UserPrincipal.FindByIdentity(New PrincipalContext(ContextType.Domain, "mydomain"), IdentityType.SamAccountName, userName)
    Catch ex As PrincipalOperationException
        Return Nothing
    End Try
End Function

You can also narrow your search to a single organizational unit on the server by specifying the search root in the form of a LDAP distinguished name when you create the context, that can significantly improve performance on large networks. 通过在创建上下文时以LDAP可分辨名称的形式指定搜索根,还可以将搜索范围缩小到服务器上的单个组织单位,这可以显着提高大型网络的性能。

Private Function GetPrincipalContext(ByVal domain As String, ByVal ldapDn As String) As PrincipalContext
    Try
        If String.IsNullOrWhiteSpace(ldapDn) Then
            Return New PrincipalContext(ContextType.Domain, domain)
        Else
            Return New PrincipalContext(ContextType.Domain, domain, ldapDn)
        End If
    Catch ex As PrincipalOperationException
        Return Nothing
    End Try
End Function

You can specify a username and password in the PrincipalContext constructor to connect to the store with. 您可以在PrincipalContext构造函数中指定用户名和密码来连接商店。 Here's the MSDN documentation link. 这是MSDN 文档链接。

The easiest way to deal with this would be to setup a WCF service to handle interaction with Active Directory, and have your web app query that service, running under a privileged account. 解决此问题的最简单方法是设置WCF服务以处理与Active Directory的交互,并让您的Web应用程序以特权帐户运行该服务。 This way only the service needs to run elevated, the client just needs to be able to reach the service. 这样,只有服务需要提升运行,客户端才需要能够访问该服务。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM