问题描述
我需要为我的Intranet Web应用程序的方法将使用的DirectoryServices
用户进行身份验证,无论是对一个默认域,或用户指定的一个。
I need to create a method for my intranet web application that will authenticate a user using DirectoryServices
, either against a default domain, or a user specified one.
在我的登录表单,用户将能够要么会给那里的凭据用户名
和密码$ C的形式$ C>或
域\\用户名
和密码
当用户在相同的域中的网络服务器,是相当straightfoward第一情况下,可以使用。在code我用的是:
On my login form the user will be able to either give there credentials in the form of "username"
and "password
" or "domain\username"
and "password"
The first case can be used when the user is in the same domain as the webserver and is quite straightfoward. The code I use is:
string domain = "";
// Code to check if the username is in form of "domain\user" or "user"
string username = ParseUsername(username, out domain);
if(domain == "")
domain = defaultDomain;
PrincipalContext context = new PrincipalContext(ContextType.Domain, domain, username, password);
bool IsAuthenticated = context.ValidateCredentials(username, password)
我传递给PrincipalContext构造的用户名和密码才能在我尝试访问另一个域情况下,调用绑定。
I pass the username and password to the PrincipalContext constructor in order to bind the call in cases where I try to access another domain.
有关本地域中code正常工作。然而,当我尝试检查针对正在通过用户名指定的另一个域,然后我得到一个服务器无法联系的错误。
For the local domain the code works fine. However when I try to check against another domain that is being specified through the username, then I get a "Server could not be contacted" error.
我也使用不同的尝试 ContextOptions
如 ContextOptions.SimpleBind
或 ContextOptions.Negotiate
但我似乎总是会得到相同的结果。
I also tried using different ContextOptions
such as ContextOptions.SimpleBind
or ContextOptions.Negotiate
but I always seem to be getting the same result.
我要实现这一点,因为应用程序被运到不同客户,采用单域或多个域环境。
有没有别的东西,我应该在远程域案件指定?的code需要灵活,因为这将在各种环境中部署。
I need to implement this, since the application is being shipped to various customers, with either single domain or multiple domain environments.Is there something else I should specify in cases of "remote" domains? The code needs to be flexible since this will be deployed in various environments.
感谢
修改:我必须指出,我preFER用做 DirectoryServices.AccountManagement
和 PrincipalContext
以利用其他功能,它提供了为好。
EDIT: I must point out, that I prefer to do it using DirectoryServices.AccountManagement
and PrincipalContext
in order to take advantage of other functionality it provides as well.
另外,不得不提的就是对我的测试中,我的开发机器上10.0.0。*网络和I测试对第二区域是在10.0.1。*。我有一个路线,同时,我可以使用LDAP客户端连接succesfuly,所以问题是,为什么我无法通过我的asp.net应用程序连接到域。
Also, I must mention that for my tests, my Dev machine is on a 10.0.0.* network and the second domain I test against is on a 10.0.1.*. I have a route and all, and I can succesfuly connect using an ldap client, so the question is why I cannot connect to the domain via my asp.net application.
推荐答案
我想出了这个解决问题的办法。
I have come up with this solution to the problem.
为了支持多个域,无论是在信任关系,甚至在隔离的网络,首先我在web.config中列出域和域控制器增加了一个NameValueCollection中。
In order to support multiple domains, either in trust relationships or even in isolated networks, first of all I added a NameValueCollection in my web.config to list the domains and their domain controllers.
<domains>
<add key="domain1" value="10.0.0.1"/>
<add key="domain2" value="10.0.1.11"/>
</domains>
(上的配置除了在this所以问题)
然后下一步是读取用户的凭据域在我的问题提了道路。我们已经有了我试着查找从配置值,根据域控制器的域名,以获得正确的LDAP连接字符串。所以,我的方法是这样的:
Then the next step was to read the domain from the User's credentials in the way I mention in the question. Having gotten the domain I try to lookup the according domain controller from the configuration values, in order to get the proper LDAP connection string. So my method is this:
private string GetLDAPConnection(string a_Domain, string a_Username, string a_Password)
{
// Get the domain controller server for the specified domain
NameValueCollection domains = (NameValueCollection)ConfigurationManager.GetSection("domains");
string domainController = domains[a_Domain.ToLower()];
string ldapConn = string.Format("LDAP://{0}/rootDSE", domainController);
DirectoryEntry root = new DirectoryEntry(ldapConn, a_Username, a_Password);
string serverName = root.Properties["defaultNamingContext"].Value.ToString();
return string.Format("LDAP://{0}/{1}", domainController, serverName);
}
在我回到正确的连接字符串我做为了一个新的呼叫对用户进行认证,通过解决适当的LDAP
Once I get back the proper connection string I make a new call in order to authenticate the user, by addressing the proper LDAP
...
string ldapConn = GetLDAPConnection(domain, username, a_Password);
DirectoryEntry entry = new DirectoryEntry(ldapConn, username, a_Password);
try
{
try
{
object obj = entry.NativeObject;
}
catch(DirectoryServicesCOMException comExc)
{
LogException(comExc);
return false;
}
DirectorySearcher search = new DirectorySearcher(entry);
search.Filter = string.Format("(SAMAccountName={0})", username);
search.PropertiesToLoad.Add("cn");
SearchResult result = search.FindOne();
从这点上我也可以执行所有其他疑问我想,如用户的组成员等。
From this point on I can also perform all the other queries I want such as the user's group membership etc.
由于调用远程域需要绑定到用户,我用的是呼唤的用户凭据。通过这种方式获取用户的身份验证,并呼叫被绑定到特定的用户。此外,我指定一个默认的域,让用户提供他们的凭据,而无需指定域的情况。
Since the call to the remote domains needs to be bound to a user, I use the "calling" users credentials. This way the user get's authenticated and the Call is bound to the specific user. Furthermore, I specify a "default" domain, for cases where users provide their credentials without specifying the domain.
我没能然而,这使用PrincipalContext因为我想,但光明的一面,这种解决方案也适用于旧的.NET 2.0应用程序也是如此。
I did not manage to this however using the PrincipalContext as I wanted, but on the bright side, this solution is also applicable for older .NET 2.0 applications as well.
我不知道,这是解决问题的最佳解决方案,但它似乎在我们目前执行的测试工作。
I am not sure that this is the best solution to the problem, however it seems to work in the tests we have so far performed.
这篇关于使用的DirectoryServices跨域认证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!