私たちは何を持っていますか?
クライアント: win8、ie11、ドメイン資格情報を使用してシステムにログイン。
サーバー: Apache 2.2.22 を超えて実行される 3 つの tomcat7 ノード。アプリケーションはワッフル ライブラリを使用して、sso 方式でドメインにログインしている Windows ユーザーを認証します。
アプリケーションは春のセキュリティを使用しており、このトピックに関する主なことは、フォームを介してログインを処理するフィルターが認証ヘッダーを処理するフィルターの前に来ることです。
- NegotiateSecurityFilterProvider は、NTLM ではなく Negotiate プロトコルのみをサポートします
私達がすること?
直接リンク経由でアプリケーションに入ります: https://app.domain.com/app_name/subordinates.do。大丈夫です。有効な kerberos ヘッダーを持っています (フィドラーが「認証ヘッダー (ネゴシエート) には kerberos チケットが含まれているようです」と説明する、優れた大きな 1 つの kerberos トークンです^^)。 .
ログアウト。
ログイン ページのフォームからログインします。user_name とパスワードを使用してポスト リクエストを作成します。ここでも、同じ kerberos トークンを使用します。アプリケーションは、ワッフル WindowsAuthenticationProvider の助けを借りて、user_name とパスワードを使用してログインします。ここでは、NegotiateSecurityFilter をリッチにする前に認証を受けるため、サーバーからの応答内に kerberos ヘッダーはありません。とにかくすべてが大丈夫です。
OS経由でMSアカウントにログインします。そして魔法が起こります。
直接リンク経由でログインしようとすると、SPRING_SECURITY_LAST_EXCEPTION 定数としてログイン ページに「指定されたハンドルが無効です」というエラーが表示されます。私の推測では、何らかの無効な認証ヘッダーを送信していると思われます
フォーム経由でログインしようとすると、「パラメーターが正しくありません」と表示されます。ここで、空の本文でntlmタイプ1 POSTリクエストを送信すると思いますが、まだ無効なヘッダーがあるため、アプリケーションはそれを認識せず、401応答を送信せず、その後ワッフルがnull名をADに送信し、ここでエラーが発生します(推測)
しかし、フィドラーをオンにして実際に何が起こっているかを確認すると、MS アカウントにログインする前と同じようにすべてが正常に機能し始めます。
OK、サーバーに送信されるヘッダーを把握するために、cmd ファイル内のコードを使用しました。
UDPATED追加コードと出力
var cookieContainer = new CookieContainer();
var authRequest = (HttpWebRequest) WebRequest.Create("https://app.domain.com/app_name/home.do");
var credentials = CredentialCache.DefaultNetworkCredentials;
authRequest.Credentials = credentials;
authRequest.CookieContainer = cookieContainer;
authRequest.AllowAutoRedirect = false;
var authResponse = (HttpWebResponse)authRequest.GetResponse();
Console.WriteLine("Request headers:");
foreach (string header in authRequest.Headers.AllKeys) {
Console.WriteLine("\t{0}: {1}", header, authRequest.Headers.Get(header));
}
Console.WriteLine("\nResponse: {0} {1}", (int)authResponse.StatusCode, authResponse.StatusDescription);
Console.WriteLine("Response headers:");
foreach (string header in authResponse.Headers)
Console.WriteLine("\t{0}: {1}", header, authResponse.GetResponseHeader(header));
foreach (var cookie in cookieContainer.GetCookies(new Uri("https://app.domain.com/app_name/")))
Console.WriteLine("Received cookie: {0}", cookie);
Console.WriteLine("\nPress ENTER to exit");
Console.ReadLine();
ここで私が得るもの:
Request headers:
Authorization: Negotiate oTMwMaADCgEBoioEKE5UTE1TU1AAAQAAAJeCCOIAAAAAAAAAAAAAAAAAAAAABgOAJQAAAA8=
Host: {host}
Cookie: JSESSIONID={sessionId}
Response: 302 Found
Response headers:
Vary: Accept-Encoding
Content-Length: 0
Content-Type: text/ plain; charset=UTF-8
Date: Tue, 04 Feb 2014 11:44:15 GMT
Location: https://app.domain.com/app_name/login.do?error_code=1
Server: Apache/2.2.22 (Win32) mod_ssl/2.2.22 OpenSSL/0.9.8t mod_jk/1.2.37
Received cookie: JSESSIONID={sessionId}
認証が機能するときにフィドラーが見るのは、kerberos ヘッダーよりもはるかに小さいヘッダーです。
質問は次のとおり
です。 1. MS アカウントにログインすると、サーバーに送信されるヘッダーに影響するのはなぜですか?
2. フィドラーをオンにすると機能し始めるのはなぜですか?
3. このヘッダーのタイプ: oTMwMaADCgEBoioEKE5UTE1TU1AAAQAAAJeCCOIAAAAAAAAAAAAAAAAAAAAABgOAJQAAAA8= をネゴシエートし、サーバーでどのように処理する必要がありますか?
UPDATE 2014 年 3 月 17 日: Wireshark キャプチャは、tgs 要求の後に KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN エラーを示します。サポート チームと調査した結果、異なるノードで Tomcat サーバーを実行するために使用される特別なユーザーが、apache を使用するマシンのドメイン名の spn を持っていないことがわかりました (リソース ドメイン名の spn はありましたが、現在のマシンの spn はありませんでした)。spn が追加された後、問題はなくなりました。