从 Web 服务调用时 Domain.GetDomain(...) 失败

发布于 2024-08-16 11:02:54 字数 1599 浏览 1 评论 0 原文

我在从 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 会失败?再说一次,调用本身并没有失败......它返回一个具有不可读属性的域对象。

提前致谢!

I have the following code in a class that is called from a web service:

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

If I instantiate the class directly, all is well, I have a valid domain object that I can work with. If I go through the web service, the domain object is created, but most of the properties throw exceptions, e.g.:

'domain.Children' threw an exception of type ActiveDirectoryOperationException

I have impersonation enabled and am explicitly setting the credentials before calling the web service. Examining Thread.CurrentPrincipal.Identity.Name on the web service side shows the username of the credentials I've explicitly set.

If I look at Request.LogonUserIdentity, I have the following properties:

Name:  "domain\\username"  (is correct)
ImpersonationLevel:  Impersonation
IsAnonymous:  false
IsAuthenticated:  true
AuthenticationType:  NTLM

Anonymous access is disabled (enabling it makes no difference), and 'Basic Authentication' and 'Integrated Windows Authentication' are both checked. The web service is running under IIS 5.1 on my development box.

The code that calls the web service, resulting in a failed call to 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();

The code that calls directly and succeeds:

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

Any ideas why calls to Active Directory would fail when made in the context of a web service? And again, the call doesn't fail per se... it returns a domain object with unreadable properties.

Thanks in advance!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

花期渐远 2024-08-23 11:02:54

当您这样做时...

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

...您实际上只是使用特定的 NetworkCredentials 创建一个 (System.DirectoryServices.Protocols).LdapConnection ,并根据该凭据验证您的“用户”和“密码”凭据。但随后您不再使用连接对象;相反,您创建一个新的完全不相关的 (System.DirectoryServices.ActiveDirectory).DirectoryContext 对象。

因为您没有使用显式指定用户名和密码的构造函数,所以 DirectoryContext 对象将获得 使用运行应用程序池的用户的凭据(在 IIS 6+ 中,在 IIS 5.1 中,如果我没记错的话,应用程序将始终是本地系统帐户 - IUSR_XXX - 将无法访问 Active Directory,因为它不是域帐户)。

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

尝试使用构造函数为 DirectoryContext 对象指定用户名和密码

就模拟而言,使用此代码片段可能会有更好的运气...

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:如何在 ASP.NET 应用程序中实现模拟

When you do...

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

...you're in fact just creating a (System.DirectoryServices.Protocols).LdapConnection with specific NetworkCredentials and you validate your "user" and "password" credentials against that. But then you don't use the connection-object anymore; instead you create a new entirely unrelated (System.DirectoryServices.ActiveDirectory).DirectoryContext-object.

And because you're not using a constructor where you're explicitly specifying a username and a password the DirectoryContext-object will get using the credentials of the user running the Application Pool (in IIS 6+, in IIS 5.1 the application will, if memory serves me right, always be a/the local system account - IUSR_XXX - which won't be able to access Active Directory because it's not a domain account).

The different credentials that are used when you're running your code in an IIS-environment versus just testing using a console application (where you're running code as the logged in/interactive user) is a common cause of problems in programming Directory Services.

Try using the constructor where you specify a username and password for the DirectoryContext-object.

As far as impersonation is concerned you might have better luck by using this code-snippet...

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

...taken from KB306158: How to implement impersonation in an ASP.NET application.

执妄 2024-08-23 11:02:54

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

In the end, I converted this to a WCF service hosted in IIS, and the impersonation is fine. I'd love to know what the problem was, but I had to move forward, and a WCF service is a better solution overall, anyway. Thanks for the help, though!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文