C#LDAP性能

在我工作的地方,我们有两种身份validation模式:

  • CAS( http://www.jasig.org/cas )
  • LDAP

CAS是主要方法,但在高峰时段通常不可靠,因此当我们注意到CAS停机时,我们一直使用LDAP作为后备模式。 以前,我们使用PHP来执行LDAP回退并获得合理的性能。 除了预期的网络延迟时间之外,登录期间没有明显的延迟。 使用LDAP完成登录大约需要250-500毫秒。

现在,我们正在创建一个新系统,并选择ASP.NET MVC4作为平台而不是PHP,我的任务是尝试让这个回退再次运行。 我已经把头发拉了大约6个小时,现在一遍又一遍地尝试不同的东西,得到相同的结果(也许我疯了)。 我终于设法连接到LDAP,validation用户身份,并从LDAP获取其属性。 但是,无论我尝试什么方法,查询始终需要4.5秒才能完成。

这让我感到非常惊讶 ,因为PHP版本能够在1/8的时间内完成几乎相同的事情,并且似乎.NET框架对LDAP / ActiveDirectory提供了出色的支持。 我做了一件非常可怕的错误吗?

以下是我现在的function内容(这是最新的迭代,可以在一个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版本遵循以下顺序:

  1. 匿名绑定并使用basedn和cn查找用户信息
  2. 使用用户的用户名和密码再次绑定,以查看它们是否可信

它在.NET版本执行一次的过程中,在1/8的时间内完成两个绑定(连接?)! 这种事情让我觉得我错过了什么。

我尝试过基于以下网站的方法:

  • http://roadha.us/2013/04/ldap-authentication-with-c-sharp/ – 需要2个查询来做我想要的并且太慢了。 我经历了6次不同的尝试(不同的身份validation和连接设置等)。
  • http://web.byu.edu/docs/ldap-authentication-0 – 一个PHP版本,但底部有一个关于.NET的小片段。 我也需要获取配置文件,但它们并不完全具有描述性。
  • System.DirectoryServices很慢? – 当前版本

编辑:

使用wireshark,我看到以下请求:

  1. bindRequest传递我的uid(delta 0.7ms)
  2. bindResponse成功(delta 2ms)
  3. searchRequest“ou = People,o = byu.edu”wholdSubtree(delta 0.2ms)
  4. searchResEntry“uid = my uid ,ou = People,o = byu.edu”| searchResDone成功1结果(delta 10.8ms)
  5. unbindRequest(delta 55.7ms)

显然,开销来自.NET,而不是来自请求。 这些不会以任何方式,形状或forms累加4.5秒。

ldap.byu.edu肯定看起来像一个完全限定的DNS主机名。 您应该将LdapDirectoryIdentifier构造函数更改为new LdapDirectoryIdentifier("ldap.byu.edu", 636, true, false)

我认为你使用System.DirectoryServices肯定是在正确的轨道上,所以你可能只需稍微调整你的搜索请求。

你只想在这里得到一个结果,对吗? 相应地设置您的尺寸:

 request.SizeLimit = 1; 

这是一个棘手的问题,但也要确保你也要抑制推荐绑定。 您需要在调用connection.SendRequest(request)之前设置此项:

 //Setting the DomainScope will suppress referral binds from occurring during the search SearchOptionsControl SuppressReferrals = new SearchOptionsControl(SearchOption.DomainScope); request.Controls.Add(SuppressReferrals);