开发者

Domain.GetDomain(...) fails when called from a web service

开发者 https://www.devze.com 2022-12-14 21:33 出处:网络
I have the following code in a class that is called from a web service: NetworkCredential credentials = new NetworkCredential(\"user\", \"password\");

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:  Imperso开发者_Python百科nation
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!


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.


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!

0

精彩评论

暂无评论...
验证码 换一张
取 消