再談 ASP.NET 應用程式的「雙躍點」(double-hop)問題與解決方法

摘要:再談 ASP.NET 應用程式的「雙躍點」(double-hop)問題與解決方法

上一篇介紹 Active Directory 與 Single Sign-On 網站的作法時,曾提到「雙躍點」(double-hop)問題。這裡再補充一些相關的概念(其實是個人的筆記啦Smile),包括:Security Context、Trusted Subsystem、與 Deligated Model。如果能夠瞭解這些概念,相信對於開發 ASP.NET 應用程式時經常碰到的存取遠端資源權限不足的問題應該會有些幫助。

Security Context

當 使用者執行某個 Windows 應用程式時(例如:在檔案總管中雙擊某個 Windows 應用程式的執行檔),作業系統會以該使用者的身分來執行應用程式,並以目前登入的使用者身份來決定該應用程式能夠執行什麼動作、是否有權限存取哪些資源。 換句話說,建立了該 process 的 security context。

Windows 應用程式的 security context 很明確,就是目前登入的使用者。但對 ASP.NET 應用程式來說就不是這樣了。ASP.NET 應用程式是部署於有安裝  IIS 的伺服器上,而當使用者從遠端以 IE 存取網站時,IIS 伺服器當時可能根本沒有使用者登入,那麼,ASP.NET 應用程式的 process 應該要用哪個帳戶來決定其 security context?由此可見,一定有一個預先指定的帳戶來執行 ASP.NET 應用程式。

在 Windows 2003(IIS 6)裡面,這個帳戶預設是 NETWORK SERVICE(網路服務),此帳戶的權限不高,例如,它沒有權限寫入伺服器的磁碟檔案。剛開始學習 ASP.NET 程式設計的人,在撰寫檔案處理的程式時經常會碰到權限不足的情況,就是這個原因。解決方法很簡單,只要修改存取的檔案目錄權限,讓 NETWORK SERVICE 有權限讀寫即可。

你也可以把 ASP.NET 應用程式的預設啟動帳戶改成別的使用者帳戶,稍後在介紹 Trusted Subsystem 時就會提到。

雙躍點(Double-hop)問題

前面提到的檔案讀寫權限不足的問題很容易解決,可是當你的 ASP.NET 應用程式是要存取遠端的網路資源時,情況就變得複雜一些了。參考下圖:


這 張簡化過的圖形說明了 ASP.NET 應用程式在存取遠端資源時常碰到的「雙躍點」問題。首先,使用者開啟 IE 並對 IIS 發出 HTTP request,IIS 會驗證使用者的身份,這是第 1 個跳躍點。當 ASP.NET 程式中有存取遠端伺服器資源的動作時,則 IIS 必須代理我們的應用程式去模擬一個使用者身份,以便和遠端的伺服器驗證(否則遠端的伺服器憑什麼讓它任意存取資源?)。問題是這個代理機制預設是未啟用 的,因為 Windows 預設不允許將本機的使用者憑證傳遞給遠端的伺服器。於是在這個例子當中,IIS 會以匿名使用者身份去存取遠端資源,匿名使用者沒什麼權限,於是結果可想而知──存取被拒。

解決雙躍點問題的方式大致上可分為兩種:Trusted Subsystem 和 Deligated Model,以下分別說明之。

Trusted Subsystem

若採用 trusted subsystem 方法,表示當你的程式要存取遠端的網路資源時,是模擬成某個特定的使用者身分去存取該資源。

例如,你可以開啟 Windows 2003 的「IIS 管理員」,打開某個「應用程式集區」的內容(例如 ASP.NET V2.0),然後切到「身分識別」頁籤。如下圖:

 

預 設的應用程式集區身分識別是「網路服務」,也就是 NETWORK SERVICE。ASP.NET 應用程式的 process 就是以這個身份執行,因此其權限也受限於此帳戶的權限(通常很低)。如果你把這個預先定義的身分識別改成「本機系統」,那麼屬於該集區的 ASP.NET 應用程式就會以「本機系統」的身分執行(注意!此帳戶的權限很大)。這種方式雖然可以快速解決權限不足的問題,可是卻會影響該集區的所有 ASP.NET 應用程式,並造成更大的安全風險。比較好的作法是個別設定 ASP.NET 應用程式的 web.config,使用 <identity> 標籤來指定要模擬的使用者,例如:

  <identity impersonate="true" userName="Domain\UserName" password="p@ssw0rd" />

若要控制得更精細,還可以在程式中呼叫 WindowsIdentity.Impersonate 方法,這樣就可以只在需要的時候才模擬成特定的使用者,用起來更彈性,也更安全。

Deligated Model

若採用 Deligated Model,則表示當應用程式要存取遠端的網路資源時,是模擬成前端登入的使用者身份。也就是說,ASP.NET 應用程式不是像 Trusted Subsystem 那樣以特定的服務帳戶執行,而是以目前登入的使用者身份來執行。

例如,修改 ASP.NET 應用程式的 web.config,使用 <identity> 標籤來指定要啟用模擬機制,但不指定要模擬成哪個使用者:

  <identity impersonate="true" />

這 樣的話,網域管理員就可以設定每個使用者存取網路資源的權限,當使用者執行你的 ASP.NET 應用程式時,他能夠存取的資源即受限於網域管理員設定給他的權限。如果是 Trusted Subsystem,則一視同仁,因為不論目前登入的使用者身份為何,它都是以同一個事先指定的帳戶去存取遠端的資源。