2014-12-04 131 views
1

我有IIS託管的Web應用程序。它使用表單身份驗證和匿名身份驗證進行配置,並且啓用了模擬。 應用程序池帳戶是網絡服務。匿名賬戶是Costa。 Costa正在訪問數據庫。 NetworkService無法訪問數據庫。WindowsIdentity.Impersonate()混淆

的問題是,請求線程(父線程)可以訪問數據庫,但子線程不能。

爲了解決這個問題。我將主線程的窗口標識對象發送給子線程,然後我調用Impersonate()。冒充的意思是「指定當前線程Windows身份驗證與模擬的帳戶 我的問題:這是一個好做法是有風險

\\Request thread code (Parent thread) 

\\WindowsIdentity.GetCurrent() return Costa identity (impersonated) 
requestFields.CurrentPrincipal = new WindowsPrincipal(WindowsIdentity.GetCurrent()); 
ThreadPool.QueueUserWorkItem(LogRequest, requestFields); 

-

\\ Sub thread code that works 
RequestFields requestFields = (RequestFields)obj; 
HttpRequest httpRequest = requestFields.Request; 

var impersonationContext = ((WindowsIdentity)requestFields.CurrentPrincipal.Identity).Impersonate(); 
. 
. 
. 
impersonationContext.Undo(); 
+0

你不要說你使用的是哪個版本的IIS。具有集成管道的IIS7或更高版本不再直接在配置中支持模仿,主要是因爲異步請求問題(即,當您使用asyc /等待請求可以在不再有您的模擬的不同線程上恢復時)。所以我不確定你的意思是「啓用模擬」。 – 2014-12-06 05:21:24

回答

0

的原因,工作線程ISN。? 「T自動從請求線程模擬用戶的是,.NET線程池管理的創建和重新使用它的線程。如果你通過下面的示例代碼創建自己的線程,我希望它繼承安全環境(包括模擬)自動,但你也不會重新使用會添加一些執行的線程(請參閱Thread vs ThreadPool瞭解兩者之間差異的細節以及使用線程池線程的好處)。

由於您知道IIS模擬用戶,並且根據http://blogs.msdn.com/b/tmarq/archive/2007/07/21/asp-net-thread-usage-on-iis-7-0-and-6-0.aspx它使用線程池來處理它的請求,所以我會斷定在線程池線程上進行模擬並不危險,只要您採取措施以使其成爲儘可能確保在特殊情況下假冒行爲將被撤消。如果模擬沒有撤消,您運行的其他代碼,使用線程池(你的,其他庫,或.NET Framework本身)被分配給使用一些隨機的身份,而不是的應用程序池標識一個線程的風險。

我不確定什麼是RequestFields類(快速搜索似乎表明它不是.NET框架的一部分),所以我不明白爲什麼有必要將WindowsIdentity包裝在WindowsPrincipal中您不使用身份以外的任何屬性,並強制您在另一個線程上投射。如果你擁有這個類並且可以改變它,我建議改變CurrentPrincipal屬性來直接接受WindowsIdentity,這樣它就可以在沒有不必要的WindowsPrincipal包裝的情況下傳遞。

我認爲這是對你罰款,以當前的WindowsIdentity傳遞到另一個線程池中的線程,並調用冒充你這樣做的方式。但是,您絕對應該將impersonationContext包裝在using塊中,或者將Undo包裝在try/finally塊的finally部分中,該塊在調用Impersonate時開始,以確保即使在發生異常或線程中止時也可以取消模擬。您還應該確保由WindowsIdentity.GetCurrent()創建的WindowsIdentity的副本也被處理,因此所有對身份後面的非託管用戶令牌的引用都是確定性地關閉的(即不是垃圾回收器終止)。創建一個新的線程

示例代碼:

Thread myThread = new Thread(LogRequest); 

// the CLR will not wait for this thread to complete if all foreground threads 
// have been terminated; this mimics the thread pool since all thread pool threads 
//are designated as background threads 
myThread.IsBackground = true; 

myThread.Start(requestFields); 

示例代碼正確處理的WindowsImpersonationContext和的WindowsIdentity與使用塊對象(impersonationContext.Dispose將調用撤消):

using (var identity = (WindowsIdentity)requestFields.CurrentPrincipal.Identity) 
using (var impersonationContext = identity.Impersonate()) 
{ 
    . 
    . 
    . 
} 
+0

如果App Pool線程被模擬,然後在不調用undo的情況下退出,並且該線程被重用,即使您未調用模擬,它也將保留模擬身份。我可以使用一些測試代碼來確認這一點。 – Costa 2015-03-16 11:04:12