うまくいかなかったこと
ほぼすべての IIS 構成の順列を試してみましたが、うまくいきませんでした。NTLM、Negotiate、Negotiate:Kerberos などの Windows 認証プロバイダーの設定をいじってみました。それらのどれもトリックをしていないようでした。ブラウザは認証を再試行することを決定しているため、これはそれほど驚くべきことではありません。
401無許可
リクエストにはユーザー認証が必要です。応答には、要求されたリソースに適用可能なチャレンジを含む WWW-Authenticate ヘッダー フィールド (セクション 14.47) を含める必要があります。クライアントは、適切な Authorization ヘッダー フィールド (セクション 14.8) を使用してリクエストを繰り返すことができます。要求に認証資格情報が既に含まれている場合、401 応答は、それらの資格情報に対する認証が拒否されたことを示します。
ソース: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.2
何が機能したか
これを修正するために、いくつかのダウンした汚れた ASP.NET を活用することにしました。以下は、サーバー上のいくつかのテキスト ファイルと ASP.NET の動的コンパイルを使用して、応答の書き換えを実装します。(これまで動的コンパイルを使用したことはありませんが、コンパイルは静的サイトにとってはやり過ぎのように思えました。)
以下の Global.asax ファイルは、EndRequest イベントをフックし、ユーザーが Windows ユーザーとして正常に認証された場合、HTTP 401 応答を HTTP 403 に書き換えますが、他の何らかの理由で要求が拒否されています (理由は承認に違いないと思います)。失敗)。
web.config ファイルには、ASP.NET パイプラインを介してすべての要求をルーティングし、"Sales" Windows グループのメンバーではない認証済みユーザーへのアクセスを拒否するためのエントリが含まれています。
このソリューションは、IIS 統合パイプライン モード (つまり、クラシック モードではない) で実行されているアプリがあり、Windows 認証を有効にし、他のすべての認証方式を無効にしていることを前提としています。
/Global.asax:
<Script language="C#" runat="server">
void Application_EndRequest() {
// rewrite HTTP 401s to HTTP 403s if the user is authenticated using
// integrated Windows auth with impersonation, but,
// the user lacks permissions to the requested URL
if (Context.User != null &&
Context.User.Identity != null &&
Context.User.Identity.IsAuthenticated &&
Context.User is System.Security.Principal.WindowsPrincipal &&
Context.Response.StatusCode == 401)
{
Context.Response.Clear();
Context.Response.StatusCode = 403;
}
}
</script>
/web.config:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<security>
<authorization>
<remove users="*" roles="" verbs="" />
<add accessType="Allow" roles="Sales" />
</authorization>
</security>
<modules runAllManagedModulesForAllRequests="true" />
</system.webServer>
</configuration>
今後の参考のために、Gist @
https://gist.github.com/steve-jansen/6234700を作成しました。