LogonUser で DC 認証をする

アプリケーション内でユーザー認証するシナリオがあります。
ユーザー認証する際には、LogonUser() を使用することが多いですね。

BOOL LogonUser(
  LPTSTR lpszUsername,  // ユーザー名を指定する文字列
  LPTSTR lpszDomain,  // ドメインまたはサーバーを指定する文字列
  LPTSTR lpszPassword,  // パスワードを指定する文字列
  DWORD dwLogonType,  // ログオン動作のタイプを指定する
  DWORD dwLogonProvider,  // ログオンプロバイダを指定する
  PHANDLE phToken  // トークンハンドルを受け取る変数へのポインタ
);

MSDN の LogonUser() の説明はこちらから…

今回は、LogonUser() に関する Tips です。

まずは、1つ目のTipsです。
lpszDomain パラメーターは必ず指定しましょう。
NULL 指定でも動きますが、検索に癖があります。
NULL を指定すると、LogonUser() は最初にローカルのアカウントデータベースを検索し、
次に信頼される側のドメインに対して、アカウントが見つかるか、すべてのアカウントデータベースを
検索し終わるまで作業を続けるよう指示します。

これだけ見ると、便利なように思えますが、DC 認証を行った際に、そんなアカウントは無いよっていう
エラーが返ってこないと、次の検索に進みません。つまり、検索でエラーが返ってきたときには
LogonUser() はエラーを返して終了してしまいます。あら、残念。。。

次の話しに進めましょう。
通常、DC 環境は、マルチ構成にしますよね。
1台の DC がダウンしても、アプリケーションはサービスを提供できるようにって。 この場合を考えて見ましょう。

Windows クライアントは、ドメインに対してコンピューター認証を行います。
この認証が通ると、ドメインメンバーとして認められるわけで、ユーザーはドメインログオンができます。
Windows XP 以降の OS は、コンピューター認証を行う際、DC ロケータが動作しますが、その際
DsGetDcName() を使い、認証に使用した DC 名をキャッシュしておきます。
LogonUser() を使い、ドメインユーザー認証を行う場合、使用する DC は、ここでキャッシュされているものを使用することになります。

では、コンピューター認証に使用した DC がダウンしていたら、どうなるでしょうか。
アプリケーションが、LogonUser() を使用すると、残念ながら、認証エラー(1326) になるでしょう。
これでは、何のために DC をマルチ構成にしたのか、わかりませんよね。

これは、アプリケーション側の処理不足によって起こる現象です。

アプリケーションでドメインユーザー認証を行う際に、LogonUser() を使う場合には
必ず、最新の DC ロケータ情報にしておく必要があります。
つまり、アプリケーションでも、DsGetDcName() を使い、DC ロケータを呼び出しておき、応答可能な DC を
確実に抑えておくという必要があるわけです。

DWORD DsGetDcName(
  LPCTSTR ComputerName,  // コンピューター名
  LPCTSTR DomainName,  // ドメイン名
  GUID* DomainGuid,  // ドメインの GUID
  LPCTSTR SiteName,  // サイト名
  ULONG Flags,  // 動作フラグ
  PDOMAIN_CONTROLLER_INFO* DomainControllerInfo  // ドメイン情報が格納される構造体
);

MSDN の DcGetDcName() の説明は、こちらから…

この際、Flags には、必ず、DS_FORCE_REDISCOVERY を指定しましょう。DS_FORCE_REDISCOVERY は
キャッシュを無視して再度検索にいくフラブです。こうすることで認証 DC を再検索するのでオフラインになった DC は
当然除外され新しい DC に切り替わります。
こうなれば、LogonUser() は常に最新の情報を利用して、正しいドメイン認証ができます。

エンタープライズ系の製品で LogonUser() を利用して、ドメイン認証を行うのであれば、必ず、DC ロケータの情報を
最新にしておくようにしましょう。なお、Windows 自体の Netlogon サービスも DcGetDcName() を使っています。

あと、Windows Server 2008 で DsGetDcName() を使う時には、少しだけ注意してくださいね。
DC の使い方によって、RODC の影響を受けることがありますから。

今回は、この辺で。

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中

%d人のブロガーが「いいね」をつけました。