C# 从web服务调用Domain.GetDomain(…)时失败

C# 从web服务调用Domain.GetDomain(…)时失败,c#,active-directory,dns,C#,Active Directory,Dns,在从web服务调用的类中,我有以下代码: NetworkCredential credentials = new NetworkCredential("user", "password"); connection = new LdapConnection("domain"); connection.Bind(credentials); DirectoryContext directoryContext = new DirectoryContext(DirectoryContextT

在从web服务调用的类中,我有以下代码:

NetworkCredential credentials = new NetworkCredential("user", "password");

connection = new LdapConnection("domain");
connection.Bind(credentials);

DirectoryContext directoryContext = 
    new DirectoryContext(DirectoryContextType.Domain, "domain");

//  This call returns a domain object with unreadable properties
Domain domain = Domain.GetDomain(directoryContext);
如果我直接实例化这个类,一切正常,我有一个有效的域对象可以使用。如果我使用web服务,则会创建域对象,但大多数属性会引发异常,例如:

'domain.Children' threw an exception of type ActiveDirectoryOperationException
我已启用模拟,并在调用web服务之前显式设置凭据。在web服务端检查
Thread.CurrentPrincipal.Identity.Name
将显示我显式设置的凭据的用户名

如果查看
Request.LogonUserIdentity
,我有以下属性:

Name:  "domain\\username"  (is correct)
ImpersonationLevel:  Impersonation
IsAnonymous:  false
IsAuthenticated:  true
AuthenticationType:  NTLM
匿名访问被禁用(启用它没有任何区别),并且“基本身份验证”和“集成Windows身份验证”都被选中。该web服务在“我的开发”对话框上的IIS 5.1下运行

调用web服务的代码,导致对域的调用失败。GetDomain()

直接调用并成功的代码:

MyService myService = new MyService();
myService.MethodCall();
你知道为什么在web服务上下文中调用Active Directory会失败吗?再说一次,呼叫本身并没有失败。。。它返回一个属性不可读的域对象

提前谢谢

当你这样做的时候

NetworkCredential credentials = new NetworkCredential("user", "password"); 

connection = new LdapConnection("domain"); 
connection.Bind(credentials); 

DirectoryContext directoryContext =  
    new DirectoryContext(DirectoryContextType.Domain, "domain"); 

//  This call returns a domain object with unreadable properties 
Domain domain = Domain.GetDomain(directoryContext);
…实际上,您只是使用特定的网络凭据创建了一个(System.DirectoryServices.Protocols).LdapConnection,并根据该凭据验证您的“用户”和“密码”凭据。但是你不再使用连接对象了;而是创建一个完全不相关的新对象(System.DirectoryServices.ActiveDirectory).DirectoryContext对象

而且,由于您没有使用构造函数,在该构造函数中,您显式指定了DirectoryContext对象将获得的用户名和密码(在IIS 6+中,在IIS 5.1中,如果内存没有问题,应用程序将始终是本地系统帐户(IUSR_XXX),因为它不是域帐户,所以无法访问Active Directory)

在IIS环境中运行代码与仅使用控制台应用程序(在控制台应用程序中以登录/交互用户身份运行代码)进行测试时使用的凭据不同,这是目录服务编程中出现问题的常见原因

尝试使用构造函数

就模拟而言,使用此代码段可能会更幸运

System.Security.Principal.WindowsImpersonationContext impersonationContext;
impersonationContext = 
    ((System.Security.Principal.WindowsIdentity)User.Identity).Impersonate();

//Insert your code that runs under the security context of the authenticating user here.

impersonationContext.Undo();

…摘自。

最后,我将其转换为托管在IIS中的WCF服务,模拟效果良好。我很想知道问题出在哪里,但我必须向前迈进,总之,WCF服务是一个更好的解决方案。不过,谢谢你的帮助

你没有在域调用中使用连接是对的。。。该连接在代码中的其他地方使用,与当前问题无关,很抱歉包含它!调用代码在代理上设置的
CredentialCache
决定了调用
GetDomain()
的身份。因为这是一个web服务,可能无法从网页调用它,所以我不相信我可以从User.Identity模拟。如果我错了,请更正我。我还尝试将Thread.CurrentPrincipal设置为模拟的通用主体,但没有成功。谢谢你的意见!基于您提供的代码,很难为您提供更多帮助。代理对象和对Domain.GetDomain的调用之间的链接是如何建立的?连接到AD时,是否要使用netCred用户/通行证?您要使用的是最终用户的凭据吗?代理对象是否位于单独的层上?因为这可能是NTLM与Kerberos的双跳问题。您可以调试并查看用于调用Domain.GetDomain的凭据吗?你能像我建议的那样显式地设置凭据,看看它是否可以这样工作吗?它什么时候工作,什么时候不工作?通过代理对象调用调用Domain.GetDomain的方法。我正在设置的NetworkCredential是一个具有查询Active Directory权限的用户帐户。当我从web服务内部检查凭据时,它们被正确设置。代理和对象是独立的应用程序域,但在同一台计算机上运行。我没有调用方的
User
对象的句柄(调用方不是网页),因此无法使用您建议的模拟。最后,我将其转换为托管在IIS中的WCF服务,模拟效果良好。我很想知道问题出在哪里,但我必须向前迈进,总之,WCF服务是一个更好的解决方案。不过,谢谢你的帮助!我感谢Per Noalt的意见,他有一些有价值的信息,但正如我在他回答下的评论中所解释的,我无法访问他在回答中使用的对象,因为我不是从网页上打电话。因此它不能回答这个问题。佩尔的帮助值得赞扬,我可以将他的回答标记为已被接受,但这对来这里寻找同一问题答案的其他人来说难道不具有误导性吗?
System.Security.Principal.WindowsImpersonationContext impersonationContext;
impersonationContext = 
    ((System.Security.Principal.WindowsIdentity)User.Identity).Impersonate();

//Insert your code that runs under the security context of the authenticating user here.

impersonationContext.Undo();