2

私が働いている場所では、2 つの認証モードがあります。

CAS が主要な方法ですが、トラフィックのピーク時には信頼性が低いことが多いため、CAS がダウンしていることに気付いた場合のフォールバック モードとして LDAP を使用しています。以前は、LDAP フォールバックを行うために PHP を使用していましたが、適切なパフォーマンスが得られました。予想されるネットワーク ラグ タイム以外に、ログイン中に目立った遅延はありませんでした。LDAP を使用してログインを完了するには、おそらく 250 ~ 500 ミリ秒かかりました。

現在、私たちは新しいシステムを作成しており、PHP ではなく ASP.NET MVC4 をプラットフォームとして選択しました。私は、このフォールバックを再び機能させることを任されています。私は約6時間髪を引き抜いてきましたが、さまざまなことを何度も試してみましたが、同じ結果が得られました(おそらく私は正気ではありません). ようやく LDAP に接続し、ユーザーを認証し、LDAP から属性を取得することができました。ただし、どの方法を試しても、クエリの完了には一貫して 4.5 秒かかります。

PHP バージョンが 1/8 の時間でほぼ同じことを行うことができ、.NET フレームワークが LDAP/ActiveDirectory に対して優れたサポートを提供しているように見えるので、これは私にとって非常に驚くべきことです。私は信じられないほどひどく間違ったことをしていますか?

現在の私の関数の中身は次のとおりです (これは、1 回の 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. ユーザーのユーザー名とパスワードを使用して再度バインドし、認証されているかどうかを確認します

2 つのバインド (接続?) を、.NET バージョンが 1 つ実行するのにかかる時間の 1/8 で実行します! この種のことで、私は何かが欠けていると思います。

以下のサイトを参考に方法を試してみました。

編集:

Wireshark を使用して、次の要求が行われていることを確認しました。

  1. bindRequest が uid を渡す (デルタ 0.7ms)
  2. bindResponse の成功 (差分 2 ミリ秒)
  3. searchRequest "ou=People,o=byu.edu" wholdSubtree (デルタ 0.2ms)
  4. searchResEntry "uid=私の uid ,ou=人,o=byu.edu" | searchResDone 成功 1 件の結果 (デルタ 10.8ms)
  5. unbindRequest (デルタ 55.7ms)

明らかに、オーバーヘッドは要求ではなく .NET から発生しています。これらは、どのような方法、形、または形であっても、合計して 4.5 秒にはなりません。

4

2 に答える 2

3

ldap.byu.edu完全修飾 DNS ホスト名のように見えます。LdapDirectoryIdentifier コンストラクターを に変更する必要がありますnew LdapDirectoryIdentifier("ldap.byu.edu", 636, true, false)

于 2013-08-15T01:14:24.273 に答える
2

これを使用して間違いなく正しい軌道に乗っていると思うSystem.DirectoryServicesので、検索リクエストを少し調整する必要があるかもしれません.

ここで返される結果は 1 つだけですよね?それに応じてサイズを設定します。

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);
于 2013-08-13T20:13:30.893 に答える