14

Windows 7/IIS 7.5 で実行されている ASP.NET 4.0 アプリケーションが、ネットワーク サービスとして実行するように構成された "ASP.NET v4.0 Classic" アプリケーション プールにあります。アプリケーションにはApplication_EndRequest、ローカルの SQL Server インスタンスに接続するハンドラーがあります。SQL 接続文字列は を指定しますIntegrated Security=SSPI。Web.config にはありませ<identity impersonate="true" />

を参照するhttp://localhost/TestSite/と、次の例外がスローされます。

System.Data.SqlClient.SqlException (0x80131904): Login failed for user 'NT AUTHORITY\IUSR'.
   ...
   at System.Data.SqlClient.SqlConnection.Open()
   at Global.Application_EndRequest(Object sender, EventArgs e)

(IIS で構成された既定のドキュメント) またはその他の .aspx ページを参照しても、この例外はスローされません。http://localhost/TestSite/default.aspxそのような場合、アプリケーションは有効なログインである "NT AUTHORITY\NETWORK SERVICE" として SQL Server に正しく接続します。

偽装が無効になっているにもかかわらず、ASP.NET が EndRequest で "NT AUTHORITY\IUSR" を偽装するのはなぜですか? これは ASP.NET のバグですか?

次の Global.asax.cs ファイルは、問題を示しています。

public class Global : HttpApplication
{
    public Global()
    {
        this.BeginRequest += delegate { Log("BeginRequest"); };
        this.PreRequestHandlerExecute += delegate { Log("PreRequestHandlerExecute"); };
        this.PostRequestHandlerExecute += delegate { Log("PostRequestHandlerExecute"); };
        this.EndRequest += delegate { Log("EndRequest"); };
    }

    protected void Application_EndRequest(Object sender, EventArgs e)
    {
        try
        {
            using (SqlConnection connection = new SqlConnection("Server=.;Integrated Security=SSPI"))
            {
                connection.Open();
            }
        }
        catch (Exception ex)
        {
            Trace.WriteLine(ex);
        }
    }

    private static void Log(string eventName)
    {
        HttpContext context = HttpContext.Current;
        Type impersonationContextType = typeof(HttpContext).Assembly.GetType("System.Web.ImpersonationContext", true);
        Trace.WriteLine(string.Format("ThreadId={0} {1} {2} Impersonating={3}",
            Thread.CurrentThread.ManagedThreadId,
            context.Request.Url,
            eventName,
            impersonationContextType.InvokeMember("CurrentThreadTokenExists", BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.GetProperty, null, context, null)));
    }
}

トレース出力は次のとおりです。

ThreadId=3 http://localhost/TestSite/ BeginRequest Impersonating=False
ThreadId=3 http://localhost/TestSite/ PreRequestHandlerExecute Impersonating=False
ThreadId=7 http://localhost/TestSite/default.aspx BeginRequest Impersonating=False
ThreadId=7 http://localhost/TestSite/default.aspx PreRequestHandlerExecute Impersonating=False
ThreadId=7 http://localhost/TestSite/default.aspx PostRequestHandlerExecute Impersonating=False
ThreadId=7 http://localhost/TestSite/default.aspx EndRequest Impersonating=False
ThreadId=7 http://localhost/TestSite/ PostRequestHandlerExecute Impersonating=True
ThreadId=7 http://localhost/TestSite/ EndRequest Impersonating=True
System.Data.SqlClient.SqlException (0x80131904): Login failed for user 'NT AUTHORITY\IUSR'.
   ...
   at System.Data.SqlClient.SqlConnection.Open()
   at Global.Application_EndRequest(Object sender, EventArgs e)

TestSite/( にマップされている) へのリクエストは、( にマップされている)へのネストされたリクエストをDefaultHttpHandler生成するように見えることに注意してください。ASP.NET は の処理を​​終了した後、 への要求の処理を再開するときに "NT AUTHORITY\IUSR" を偽装します。TestSite/default.aspxASP.default_aspxTestSite/default.aspxTestSite/

更新:この問題をMicrosoft Connectに送信しました。

4

2 に答える 2

30

ほとんどの場合、サーバー、サイト、またはアプリケーションの設定は、「匿名認証」モードでページ要求がIUSRユーザーとして処理されるように設定されています。アプリケーションがなりすましを要求していないことは問題ではありません。IISはそれを強制しています。(ちなみに、「なりすまし」は、Windowsランドでは、別のユーザーの資格情報を想定するための一般的な用語です。ASP.NETに固有のものではありません。)

少し背景:

セキュリティ上の理由から、IISでは、サーバーがさまざまなシステム資格情報の下で「匿名」および「認証済み」の要求を処理できるようになっています。

現在、IIS 7.5では、匿名認証とフォーム認証の両方が有効になっている場合(これは一般的です)、Webサイトユーザーがフォーム経由でログインする前に、ユーザーは「匿名」と見なされます。ユーザーがFormsAuthでログインすると、ユーザーは「認証済み」と見なされます。

この動作は、Forms認証を認識せず、すべてのForms認証ユーザーを匿名と見なしていたIIS 6.0からの変更であるため、最初は混乱を招きました。

必要に応じて、匿名リクエストのフィールドとなるIDを変更できます。私の好み(そしてあなたのようにも聞こえます)は、それらが私のサイトのアプリプールと同じシステムクレデンシャルの下で実行されることです。 IISにそれを行わせるには、次のようにします。

  1. IISマネージャー(inetmgr)を開きます
  2. [接続]パネルで、サイトのノードにドリルダウンして選択します
  3. 右側のパネルの[IIS]グループで、[認証]アイコンをダブルクリックします。
  4. 「匿名認証」を右クリックし、コンテキストメニューから「編集...」を選択します。
  5. ポップアップダイアログで、[アプリケーションプールID ]ラジオボタンを選択します。
  6. [OK]をクリックします。

「アプリケーションプールID」は「アプリケーションプール疑似アカウント」(IIS 7.5のもう1つの新機能)を意味すると思ったので、ステップ5でも最初は混乱しました。もちろん、それが実際に意味するのは、「アプリプールが実行するように構成されているのと同じアカウントである」ということです。

そのサーバー上のすべてのWebサイト、または特定のサイトの単一のアプリケーションに対してデフォルトでこの動作が必要な場合は、これらのレベルで認証オプションを構成することもできます。[接続]ペインで構成するノードを選択し、手順3〜6を繰り返します。

于 2012-07-09T23:05:01.300 に答える
1

アプリケーションが (おそらく) 偽装を使用していないにもかかわらず、アプリケーションが "NT AUTHORITY\IUSR" としてログインしようとするのはなぜですか?

もしあなたがそうするなら

<identity impersonate="true"/>

ログインしているユーザーになりすます

もしあなたがそうするなら

<identity impersonate="true" userName="contoso\Jane" password="pass"/>

上記で設定したユーザーになりすます。

ただし、まったく偽装せずに Windows 認証を使用する場合は、デフォルトのシステム アカウントを使用するのが理にかなっています。

最初に IUSR として試行し、その後の要求で自動的に NETWORK SERVICE に切り替える理由がわかりません。しかし、あるサーバーから別のサーバーにジャンプするときに、アプリケーション プールの資格情報が使用されないことはわかっています。以下に示すように偽装ユーザーを設定しない限り、NETWORK SERVICE はサーバー外のリソースをフェッチするために使用されるデフォルト アカウントです。

    <connectionStrings>
        <add name="myConnectionString" connectionString="Data Source=MyServerName;Initial Catalog=MyDataBaseName;Integrated Security=True;"
          providerName="System.Data.SqlClient" />
      </connectionStrings>

<identity impersonate="true" userName="contoso\Jane" password="pass"/>
于 2012-05-09T14:18:11.277 に答える