2012-05-09 54 views
12

我有一個ASP.NET 4.0應用程序在「ASP.NET v4.0 Classic」應用程序池中的Windows 7/IIS 7.5上運行,該應用程序池配置爲作爲網絡服務運行。該應用程序具有連接到本地SQL Server實例的Application_EndRequest處理程序。 SQL連接字符串指定Integrated Security=SSPI。 Web.config確實不是<identity impersonate="true" />ASP.NET模擬NT AUTHORITY IUSR但禁用模擬。 ASP.NET錯誤?

當我瀏覽到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) 

此異常是當我瀏覽到http://localhost/TestSite/default.aspx(在IIS配置的默認文件)或任何其他.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),似乎產生一個嵌套請求TestSite/default.aspx(它映射到ASP.default_aspx)。 ASP.NET完成處理TestSite/default.aspx後,它在恢復處理請求到TestSite/時模擬「NT AUTHORITY \ IUSR」。

更新:我已將此問題提交至Microsoft Connect

+0

嘗試http://msdn.microsoft.com/en-us/library/ms998320.aspx – Arcturus

+0

哪部分?我已經在IIS和SQL Server中設置了網絡服務。 –

回答

1

即使應用程序(可能)未使用模擬,應用程序爲什麼會嘗試以「NT AUTHORITY \ IUSR」身份登錄?

如果你

<identity impersonate="true"/> 

這將模擬登錄的用戶

如果你

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

它會模擬用戶設定以上。

但是,如果您根本不模擬並使用Windows身份驗證,則使用默認的系統帳戶是有道理的。

我不知道它爲什麼首次嘗試IUSR,然後在後續請求中自動切換到NETWORK SERVICE。但是我確實知道,當你從一臺服務器跳到另一臺服務器時,應用程序池credenticals不被使用。除非按如下所示設置模擬用戶,否則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"/> 
+0

IIS和SQL Server都在我的開發機器上運行。 –

+0

我用更多的信息更新了我的問題。 –

22

最有可能,爲您的服務器,網站或應用程序的設置被設定成「匿名身份驗證」模式會導致頁面請求的IUSR用戶進行處理。你的應用程序沒有請求模仿並不重要; IIS迫使它。 (順便說一句,「模仿」是Windows的土地通稱假設其他用戶的憑據它不是特定於ASP.NET。)

一點背景:

出於安全原因,IIS允許您的服務器在不同系統憑據下輸入「匿名」和「已驗證」請求。

現在,在IIS 7.5,如果你有兩個匿名身份驗證,並在通過表格表格啓用身份驗證(這是典型的),你的網站用戶登錄之前,它認爲你的用戶「匿名」。用戶使用Forms Auth登錄後,它會認爲您的用戶「已通過身份驗證」。

我首先發現這種行爲混亂,因爲它是從IIS 6.0開始的一個變化,它不知道Forms auth,並且認爲所有的Forms-Authenticated用戶都是匿名的!

如果需要,您可以更改匿名請求所在的身份。我的偏好(聽起來和你一樣)是因爲他們在與我的網站的應用程序池相同的系統憑據下運行爲了使IIS做到這一點,做到以下幾點:

  1. 打開IIS管理器(inetmgr)
  2. 在「連接」面板中,深入到你的網站的節點,然後選擇它
  3. 在右在「IIS」組下,雙擊「身份驗證」圖標。
  4. 右鍵單擊「匿名身​​份驗證」,然後從上下文菜單中選擇「編輯...」。
  5. 在彈出的對話框中,選擇「應用程序池標識」單選按鈕。
  6. 單擊確定。

第5步也讓我起初感到困惑,因爲我認爲「應用程序池標識」意味着「應用程序池僞帳戶」(IIS 7.5中的另一個新功能)。當然,它的真正含義是「應用程序池配置爲在相同的帳戶下運行,無論如何。」

如果您希望默認情況下爲該服務器上的所有網站使用此行爲,或者甚至只需要在特定站點下的單個應用程序,則也可以在這些級別配置身份驗證選項。只需在「連接」窗格中選擇要配置的節點,然後重複步驟3-6。

+0

這並不能解釋爲什麼.aspx請求從開始到結束處理爲網絡服務,而默認文檔請求在請求生命週期的第一部分和第二部分期間作爲網絡服務處理。 –

+0

這是否解釋了爲什麼我必須將「IIS AppPool \ 」和「NT AUTHORITY \ IUSR」安全登錄添加到我的數據庫? –