【问题标题】:Domain.GetDomain(...) fails when called from a web service从 Web 服务调用 Domain.GetDomain(...) 失败
【发布时间】:2009-12-29 19:11:42
【问题描述】:

我在从 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 服务的代码,导致对 Domain.GetDomain() 的调用失败:

MyServiceProxy proxy = new MyServiceProxy ();

CredentialCache credCache = new CredentialCache();
NetworkCredential netCred = new NetworkCredential(user, password, domain);
credCache.Add(new Uri(proxy.Url), "Ntlm", netCred);
proxy.Credentials = credCache;

proxy.MethodCall();

直接调用成功的代码:

MyService myService = new MyService();
myService.MethodCall();

您知道为什么在 Web 服务的上下文中调用 Active Directory 会失败吗?再一次,调用本身并没有失败......它返回一个具有不可读属性的域对象。

提前致谢!

【问题讨论】:

  • 我很欣赏 Per Noalt 的意见,他提供了一些有价值的信息,但正如我在他回答下的 cmets 中解释的那样,我无法访问他在回答中使用的对象,因为我不是从网页调用。因此它没有回答这个问题。 Per 的帮助值得称赞,我可以将他的答案标记为已接受,但这不会误导其他来这里寻找相同问题答案的人吗?

标签: c# active-directory dns


【解决方案1】:

当你这样做时......

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 与特定的 NetworkCredentials 并验证您的“用户”和“密码”凭据。但是你不再使用连接对象了;而是创建一个新的完全不相关的 (System.DirectoryServices.ActiveDirectory).DirectoryContext-object。

而且由于您没有使用明确指定用户名和密码的构造函数,DirectoryContext-object 将获得using the credentials of the user running the Application Pool(在 IIS 6+ 中,在 IIS 5.1 中,如果记忆对我有用,应用程序将,始终是/本地系统帐户 - IUSR_XXX - 因为它不是域帐户,所以无法访问 Active Directory。

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

尝试使用构造函数where you specify a username and password for the DirectoryContext-object

就模仿而言,使用此代码-sn-p 可能会带来更好的运气...

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();

...取自KB306158: How to implement impersonation in an ASP.NET application

【讨论】:

  • 您没有在域调用中使用连接是对的......该连接在代码的其他地方使用并且与当前问题无关,抱歉包含它!调用代码在代理上设置的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 服务总体上是一个更好的解决方案。不过,感谢您的帮助!
【解决方案2】:

最后,我将其转换为托管在 IIS 中的 WCF 服务,并且模拟很好。我很想知道问题出在哪里,但我必须继续前进,无论如何,WCF 服务总体上是一个更好的解决方案。不过感谢您的帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-29
    • 1970-01-01
    相关资源
    最近更新 更多