イントラネット内の Active Directory ドメイン環境で、統合 Windows 認証によってシングルサインオンが実現されているサイトがあって、そこに非ドメインユーザーがアクセスしてきたとき、そのユーザーを誘導する(例えば、ドメインユーザー専用である旨通知するとか、別のサイトにリダイレクトする)方法について書きます。(MSDN フォーラム の話をまとめたものです)
クライアントが Windows 認証サイトにアクセスしてくると、認証手続きが始まって、認証が成功し、要求したページが表示されるまで、上の画像(キャプチャツール Fiddler2 のもの。NTLM の場合)のように要求 / 応答がやり取りされます。
NTLM の場合、具体的には以下のステップ 1 ~ 9 のようになります。上の Fiddler2 の画像の左側のウィンドウのライン #1 がステップ 1 ~ 4、#2 がステップ 5 ~ 6、#3 がステップ 7 ~ 8 に該当します。
Kerberos の場合は NTLM より一回ラウンドトリップが少なくなります。以下のステップ 5 ~ 6 がないという感じです。(あくまで「感じ」です。詳しくは MSDN Blog の記事 Two easy ways to pick Kerberos from NTLM in an HTTP capture を見てください)
-
ブラウザからページ(この例では Default.aspx)を GET 要求。
-
サーバーは 401 応答を返す。その際、サーバー側で AuthenticateRequest, EndRequest イベント発生。イベントハンドラで User は null になる。
-
クライアントには認証ダイアログが表示される。
-
ユーザー名とパスワード入力して[OK]ボタンをクリック。
-
ブラウザは再度 Default.aspx を GET 要求。
-
サーバーは 401 応答を返す。この時はサーバー側で AuthenticateRequest, EndRequest イベントは発生しない。
-
ブラウザは再々度 Default.aspx を GET 要求。
-
サーバーは 200 応答を返す。サーバー側で AuthenticateRequest, EndRequest イベント発生。イベントハンドラで User はログインユーザーの WindowsPrincipal になる。
-
ブラウザには Default.aspx が表示される。
統合 Windows 認証の場合、How IIS authenticates browser clients によると、認証済み / 未認証ユーザーの手続きの違いは、Kerberos でも NTLM でも、ステップ 3 ~ 4 の有無ということです。(自分の PC を立ち上げた時にドメインにログイン済みのユーザーの場合はステップ 3 はスキップ、ステップ 4 は自動的に行われる)
ステップ 3 でダイアログが表示された時、非ドメインユーザーができることは、[キャンセル]または[X]ボタンをクリックするか、3 回ユーザー名とパスワードを入力して認証に失敗するかですが、いずれの場合でも標準のエラーページが表示されます。
従って、アクセスしたサイトがドメインユーザー専用であることを説明するなどしたカスタムエラーページを作り、標準のエラーページと差し替えることによって、非ドメインユーザーを適切に誘導することができます。
自分の開発環境の IIS7 の場合ですが、applicationHost.config ファイルの httpErrors 要素に、カスタムページ ErrorPage.htm を以下のように設定することで差し替えることができます。
(注:自分の環境では applicationHost.config で httpErrors に対しては overrideModeDefault="Deny" と設定されているので web.config では httpErrors を設定できませんが、IIS7.5 では web.config で設定可能とのことです。ご自分の環境で確認ください)
<location path="Default Web Site/WindowsAuthentication">
<system.webServer>
<httpErrors errorMode="Custom">
<remove statusCode="401" />
<error statusCode="401"
path="C:\inetpub\custerr\ja-JP\ErrorPage.htm"
responseMode="File" />
</httpErrors>
</system.webServer>
</location>
認証ダイアログが表示された直後に[キャンセル]または[X]ボタンをクリックした場合は、差し替えたカスタムエラーページが表示されます。
しかし、自分の環境で試した限りですが、一旦認証ダイアログに ID / パスワードを入力して認証に失敗した後に返ってくるエラーページは最初の標準エラーページとは異なり、これをカスタムエラーページに差し替えることはではできませんでした。
(注:IIS7.5 ではカスタムエラーページに差し替えられたとの報告があります。その場合は以下の対応は不要となります。ご自分の環境で確認ください)
その場合、EndRequest イベントで User.Identity.IsAuthenticated が true、Response.StatusCode が 401 になることで判定でき、以下のようにすることにより対応できます。ステップ 5 ~ 6 ではイベントは発生しないのでこのやり方でうまくいきます。
void Application_EndRequest(object sender, EventArgs e)
{
if (User != null)
{
bool auth = User.Identity.IsAuthenticated;
int statusCode = Response.StatusCode;
if (auth && statusCode == 401)
{
HttpContext.Current.Response.Redirect("リダイレクト先");
}
}
}
ちなみに正しい ID / パスワードが入力され認証に成功した場合は Response.StatusCode が 200 になりますので、リダイレクトされてしまうということはありません。
ユーザー名とパスワードを入力するダイアログが表示されるのは避けられないとうところが難ありですが、それでよければ上記の案で非ドメインユーザーを適切に誘導することができそうです。興味があればお試しください。
なお、統合 Windows 認証は IE2 以降でのみサポートされているということなので(参考:認証について)、User Agent を調べてブラウザが IE 以外なら即リダイレクト等の処置をとってもいいかもしれません。