在我工作的地方,我们有两种身份验证模式:
- CAS ( http://www.jasig.org/cas )
- LDAP
CAS 是主要方法,但在流量高峰期通常不可靠,因此当我们注意到 CAS 已关闭时,我们一直使用 LDAP 作为备用模式。以前,我们使用 PHP 进行 LDAP 回退并获得了合理的性能。除了预期的网络延迟时间外,登录期间没有明显的延迟。使用 LDAP 完成登录大概需要 250-500 毫秒。
现在,我们正在制作一个新系统,并选择了 ASP.NET MVC4 作为平台而不是 PHP,我的任务是尝试让这个后备方案再次工作。我已经拉了大约 6 个小时的头发,现在一遍又一遍地尝试不同的东西,得到相同的结果(也许我疯了)。我终于设法连接到 LDAP,对用户进行身份验证,并从 LDAP 获取他们的属性。但是,无论我尝试什么方法,查询始终需要 4.5 秒才能完成。
看到 PHP 版本能够以 1/8 的时间完成几乎相同的事情,这让我感到非常惊讶,而且 .NET 框架似乎对 LDAP/ActiveDirectory 具有出色的支持。我在做一些非常可怕的错误吗?
这是我现在的功能的内容(这是最新的迭代,它设法在一个 4.5 秒的查询中完成所有操作):
public Models.CASAttributes Authenticate(string username, string pwd)
{
string uid = string.Format("uid={0},ou=People,o=byu.edu", username);
LdapDirectoryIdentifier identifier = new LdapDirectoryIdentifier("ldap.byu.edu", 636, false, false);
try
{
using (LdapConnection connection = new LdapConnection(identifier))
{
connection.Credential = new NetworkCredential(uid, pwd);
connection.AuthType = AuthType.Basic;
connection.SessionOptions.SecureSocketLayer = true;
connection.SessionOptions.ProtocolVersion = 3;
string filter = "(uid=" + username + ")";
SearchRequest request = new SearchRequest("ou=People,o=byu.edu", filter, SearchScope.Subtree);
Stopwatch sw = Stopwatch.StartNew();
SearchResponse response = connection.SendRequest(request) as SearchResponse;
sw.Stop();
Debug.WriteLine(sw.ElapsedMilliseconds);
foreach (SearchResultEntry entry in response.Entries)
{
Debug.WriteLine(entry.DistinguishedName);
foreach (System.Collections.DictionaryEntry attribute in entry.Attributes)
{
Debug.WriteLine(attribute.Key + " " + attribute.Value.GetType().ToString());
}
Debug.WriteLine("");
}
}
}
catch
{
Debugger.Break();
}
Debugger.Break();
return null; //debug
}
其 PHP 版本遵循以下顺序:
- 匿名绑定,使用 basedn 和 cn 查找用户信息
- 使用用户的用户名和密码再次绑定,看看是否真实
它执行两次绑定(连接?)的时间是 .NET 版本执行一次的时间的 1/8!正是这种事情让我觉得我错过了一些东西。
我尝试了基于以下站点的方法:
- http://roadha.us/2013/04/ldap-authentication-with-c-sharp/ - 需要 2 个查询来做我想做的事,而且太慢了。我大概经历了 6 次不同的尝试(改变身份验证和连接设置等)。
- http://web.byu.edu/docs/ldap-authentication-0 - 一个 PHP 版本,但在底部有一个关于 .NET 的小片段。我还需要获取个人资料,但它们并不完全具有描述性。
- System.DirectoryServices 很慢?- 当前版本
编辑:
使用wireshark,我看到了以下请求:
- bindRequest 沿我的 uid 传递(增量 0.7 毫秒)
- bindResponse 成功(增量 2 毫秒)
- searchRequest "ou=People,o=byu.edu" wholdSubtree (delta 0.2ms)
- searchResEntry "uid=我的 uid ,ou=People,o=byu.edu" | searchResDone 成功 1 个结果(增量 10.8 毫秒)
- unbindRequest(增量 55.7 毫秒)
显然,开销来自 .NET 而不是请求。这些以任何方式、形状或形式加起来都不超过 4.5 秒。