上文我們瞭解了一個外部Http Request進入IIS 背景工作處理序(W3WP)的處理與執行信任模型,這個階段是Sharepoint的四種執行模型都必須經過的處理階段,其中Sharepoint場解決方案與任何 ASP.NET 應用程式一樣就是在 IIS 背景工作處理序(w3wp)中啟動並執行,所以上文也就包含了場解決方案的處理與執行信任模型。
這裡繼續我們的話題,就是看看Sharepoint的沙箱化解決方案在這方面是什麼情況。
沙箱化解決方案是 SharePoint 2010 的新功能。沙箱化解決方案是直接部署到網站集合根網站中(The top Website of the Site Collection)的指定庫的資源集合。此庫稱為"解決方案庫(Solution Gallery)"。我們可以像場解決方案一樣,將沙箱化解決方案打包為 SharePoint 方案套件 (WSP)。不過,可以通過 Web 使用者介面 (UI) 直接上傳 WSP 來部署沙箱化解決方案,而不必物理訪問伺服器檔案系統,也不必 IT 團隊參與。相反,網站集合管理員確定誰有許可權向其網站集合添加沙箱化解決方案。所以,沙箱化解決方案對開發和管理團隊是很有誘惑力的。
一、IIS背景工作處理序(w3wp)交權給執行管理器(Execution Manager)
如果使用者的Http 請求(Http Request)中包含有對沙箱化解決方案的處理模型,Http請求到了IIS背景工作處理序(w3wp), IIS背景工作處理序(w3wp)就會發現,這個請求裡涉及到沙箱處理模型,這時,IIS背景工作處理序(w3wp)就會調用它裡面啟動並執行執行管理器(Execution Manager),由執行管理器(Execution Manager)來接管下一步的處理權移交。如:
中的SPUCHostService.exe、SPUCWorkerProcess.exe 和 SPUCWorkerProcessProxy.exe 檔位於
%ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\UserCode。
二、執行管理器(Execution Manager)交權給沙箱背景工作處理序(SPUCWorkerProcess)
IIS 背景工作處理序中啟動並執行 SharePoint執行管理器(Execution Manager)負責尋找沙箱化解決方案的代碼將在其中啟動並執行沙箱背景工作處理序(SPUCWorkerProcess)(如果未運行任何沙箱背景工作處理序,則負責啟動一個沙箱背景工作處理序)。
請注意,執行管理器(Execution Manager)啟動或定位的沙箱背景工作處理序(SPUCWorkerProcess)並不一定是在同一伺服器上,這可以從上面的中看出。
2.1沙箱背景工作處理序(SPUCWorkerProcess) 宿主機的要求
一般而言,執行管理器(Execution Manager)會在Sharepoint伺服器陣列中任何運行 SharePoint Foundation 沙箱化程式碼服務 (SPUCHostService: Sharepoint User Code Host Service) 的伺服器上啟動此沙箱背景工作處理序(SPUCWorkerProcess)。
在 Windows"服務"對話方塊中,它稱作"SharePoint 2010 使用者代碼主機"服務,如:
SharePoint Foundation 沙箱化程式碼服務(SPUCHostService)在伺服器陣列帳戶下運行,此帳戶與應用程式集區帳戶(Application Pool Account)擁有一樣的許可權,此帳戶歸屬於沙箱化程式碼服務所啟動並執行宿主伺服器上的WSS_WPG、WSS_ADMIN_WPG、IIS_USERS這三個組。
2.2運行Microsoft SharePoint Foundation沙箱化程式碼服務(SPUCHostService)物理伺服器的定位元模式
運行 SharePoint Foundation 沙箱化程式碼服務的伺服器可以是(但並不一定是)運行 IIS 背景工作處理序的前端網頁伺服器。可在管理中心應用程式內配置要使用的伺服器,這種配置有兩種選項。
I、"本地模式(local mode)":這意味著將在運行 IIS 背景工作處理序(W3WP)的同一前端網頁伺服器上處理對沙箱化解決方案的每個請求,即本地處理。
II、"遠程模式(remote mode)"(有時稱作"相似性模式[affinity mode]"):在此模式中啟動每個沙箱進程,執行管理器將尋找運行 SharePoint Foundation 沙箱化程式碼服務的伺服器,該伺服器已在其 SPUCWorkerProcess進程內為相同的沙箱化解決方案建立了 一個應用程式定義域(application domain)。(如果其他網站集合的另一個使用者之前已請求該相同的沙箱化解決方案,則將出現此情況)。如果存在一個匹配的應用程式定義域,則會將請求發送到相同的應用程式定義域以進行處理。如果運行 SharePoint Foundation 沙箱化程式碼服務的任何伺服器都不具有沙箱化解決方案的應用程式定義域,則執行管理器會將請求分配給這些伺服器中最閑的伺服器。之後,該伺服器將建立所需的應用程式定義域並處理對沙箱化解決方案的請求。
不管使用的是"本地模式"還是"相似性模式",沙箱背景工作處理序中的應用程式定義域(application domain)都將在處理完請求後保持活動狀態,且如果存在對相同沙箱化解決方案的其他請求,則將重用該應用程式定義域。
預設情況下,由給定伺服器處理的所有沙箱化解決方案都在相同的沙箱背景工作處理序中運行,但這種配置是可以通過object Model進行修改的。每個沙箱化解決方案會在常規進程(common process)中擷取其自己的應用程式定義域(application domain),而這種配置也是可以通過object Model進行修改的
2.3 運行"Microsoft SharePoint Foundation沙箱化程式碼服務"物理伺服器的分配方法
如果你的伺服器陣列包含了若干台伺服器,那麼你既可以在所有物理伺服器上啟動"Microsoft SharePoint Foundation沙箱化程式碼服務",也可以只選擇在某幾台應用伺服器上啟動"Microsoft SharePoint Foundation沙箱化程式碼服務"。
當然你也可以準備一台配置比較高的伺服器加入到伺服器陣列中專門用於運行"Microsoft SharePoint Foundation沙箱化程式碼服務"。這樣,無論伺服器陣列中的哪一台前端伺服器需要運行沙箱化解決方案中的自訂代碼,這些請求都會被發送到這台強大的物理伺服器上進行處理。
三、沙箱背景工作處理序(SPUCWorkerProcess) 內的代碼執行和安全模型
前面我們提到,沙箱方案其實就是一種"受限"方案,正因為受限,所以才安全。所以,在沙箱背景工作處理序(SPUCWorkerProcess)中啟動並執行所有代碼會受到執行和訪問約束的限制。
這種約束有兩個體系:
3.1、第一個體系稱作"伺服器端物件模型約束"
此約束體系僅適用於沙箱化解決方案中的代碼對主 SharePoint Foundation 程式集(即 Microsoft.SharePoint.dll)的調用,其調用只作用於Microsoft.SharePoint.dll中的部分object model。這種約束不僅僅是指從使用者建立的Sharepoint Solution中調用Microsoft.SharePoint.dll,而且還包括從Sharepoint的其它程式集(eg: Microsoft.Sharepoint.Linq.dll)來調用Microsoft.SharePoint.dll程式集。
3.1.1伺服器端物件模型約束體系中的主要限制是:
只能從沙箱化解決方案調用 Microsoft.SharePoint.dll 程式集中的部分 API。調用任何禁止的 API 會引發異常(將捕獲該異常,並將其作為錯誤報表給使用者)。
以下是可訪問的 SharePoint 物件模型的一些限制:
- SPWebApplication 類不可用。此外,這意味著,沙箱化解決方案無法訪問其託管網站集合外部的任何內容。
- Microsoft.SharePoint.WebControls 命名空間中的所有類幾乎都不可用,這意味著,您只能使用沙箱化解決方案中的 ASP.NET 控制項。
3.1.2 伺服器端物件模型約束通過以下機制來施加:
此限制由一對位於%ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\UserCode\assemblies 中的特別受限版本的 Microsoft.SharePoint.dll 程式集(稱作填充程式 程式集)實現。這兩個版本與標準 Microsoft.SharePoint.dll 程式集的主要差異是,它們僅包含標準版本中的部分類和成員。
這兩個填充程式程式集之一由沙箱背景工作處理序(SPUCWorkerProcess)載入,另一個填充程式程式集在完全信模式下啟動並執行特殊代理進程 (SPUCWorkerProcessProxy) 中載入,並由 SharePoint Foundation沙箱化程式碼服務(SPUCHostService)管理。
此外,標準 Microsoft.SharePoint.dll 程式集也在此代理進程中載入。
這兩個填充程式程式集的主要工作是:
I、篩選出禁止的 SharePoint 類和成員
在從沙箱背景工作處理序中的任何代碼調用 Microsoft.SharePoint.dll 時,它將重新導向到程式集的填充程式版本。如果要調用的 API 未在填充程式程式集中,則將引發異常(將捕獲該異常,並將其作為錯誤報表給使用者)。
當沙箱化解決方案調用填充程式程式集中包含的已獲批准的 API 時,第一個填充程式程式集會(它由沙箱背景工作處理序SPUCWorkerProcess載入)在完全信任代理進程中將此 API 傳遞給第二個填充程式程式集(它由特殊代理進程 (SPUCWorkerProcessProxy)載入),而第二個填充程式程式集會將此 API 傳遞給標準 Microsoft.SharePoint.dll。任何返回的結果將傳遞迴原始調用代碼。可通過 .NET 遠程來實現此跨進程互動。
沙箱背景工作處理序和完全信任代理進程總是一起啟動並成對出現。如果其中一個進程崩潰,則另一個進程也會停止。
II、對傳遞給Sharepoint API的參數進行特殊限制
該限制也由填充程式程式集強制實施。我們可似從沙箱化解決方案中調用某些 SharePoint API,但只會將針對參數的特殊限制傳遞給這些 API。這些輸入限制由填充程式程式集強制實施,並確保在發生衝突時引發異常。在 SharePoint Foundation 2010 中,僅 SPSite(String) 和 SPSite(Guid) 建構函式屬於此應用情況。雖然它們對沙箱化解決方案可用,但只能將引用安裝了沙箱化解決方案的網站集合的 URL 或 GUID 傳遞給它們。
因為第二個填充程式程式集和標準 Microsoft.SharePoint.dll 在完全信任進程中運行,所以上述限制就不 適用於對 Microsoft.SharePoint.dll 程式集中的 API 的調用,更進一步說就是通過這些API就可以完成某些在沙箱方案中被禁止的操作。比如: 對 GetLocalizedString 方法的調用可從檔案系統中的資源檔讀取,而對 SPList 對象的調用可讀取並寫入到內容資料庫中,無論其所在的伺服器如何。(但是,不能將檔案部署到沙箱化解決方案中的磁碟,因此,必須將 .resx 作為場解決方案單獨安裝。)
3.2、第二個體系稱作"一般約束"
此約束體系適用於所有其他 調用,包括對所有其他 SharePoint 程式集和 .NET Framework 程式集的調用,只要不是對主 SharePoint Foundation 程式集(即 Microsoft.SharePoint.dll)的調用就行。
上面這兩個體系是互斥的:一般約束不 適用於對 Microsoft.SharePoint.dll 程式集的調用,你只能二選 一。此外,還有一些由沙箱化解決方案中使用的分頁呈現系統產生的雜項約束。
"一般約束"通過兩種機制來施加:
I、第一種機制
是通過在wss_usercode.config 檔案所定義的高度限制的 CAS 原則來大大限制沙箱背景工作處理序中可執行檔代碼,此檔案在%ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\CONFIG 中定義,並在 %ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\UserCode 下的 web.config 檔案中引用了該策略。(微軟不支援更改此檔案。)由 CAS 原則施加的限制如下:
- 沙箱中的代碼不能調用Unmanaged 程式碼。
- 沙箱中的代碼不能調用 Microsoft .NET Framework 3.5 反射 API。
- 沙箱中的代碼只能調用具有 AllowPartiallyTrustedCallersAttribute 屬性的 .NET Framework 3.5 程式集。這將阻止對約三分之二的 .NET Framework 3.5 API(例如,包括 System.Printing)的訪問。此外,一些 SharePoint 程式集不具有此屬性。
CAS 原則將強式名稱 Microsoft Office 程式集視作例外。這些程式集授予了完全信任。
II、第二種機制
是通過安全性權杖來實施,即給沙箱背景工作處理序賦予一個低許可權的安全性權杖。
- 該令牌拒絕進程對檔案系統進行讀取或寫入的許可權。
- 該令牌拒絕進程對網路進行調用的許可權。因此,只能訪問運行沙箱背景工作處理序的伺服器上可用的資源。例如,無法訪問外部資料庫。
- 該令牌拒絕進程對註冊表進行寫入的許可權。
- 該令牌拒絕對未在常規組件快取(GAC)中的任何程式集進行調用的許可權,即使它具有 AllowPartiallyTrustedCallersAttribute 屬性也是如此,否則它將符合從沙箱背景工作處理序進行調用的資格。
沙箱化解決方案自身的部署階段在沙箱背景工作處理序中運行,並受相同執行約束的限制。例如,在部署沙箱化解決方案時,無法將檔案部署到磁碟。這是使用者控制項(ASCX 檔案)不能位於沙箱化解決方案中的主要原因。
四、關於沙箱方案資源使用的限制
沙箱方案既然把一定的權力下放,但由此卻帶來潛在的問題,那就是對Sharepoint資源的分配。設想如果不加控制,那麼某個使用者就可能把特定的資源消耗殆盡。所以,Sharepoint也就自然引入了針對資源的使用限制,具體有如下三條限制規則
- 每個請求(請求遭到處罰):對於完成沙箱化解決方案所需的時間有一個硬性限制。預設情況下,此時間限制為 30 秒。如果沙箱化解決方案超出了該限制,則將終止請求(而非沙箱背景工作處理序)。(此限制是可配置的,但只能通過針對物件模型的自訂代碼進行此操作。物件模型的相關部分對沙箱化解決方案不可用,因此,任何沙箱化解決方案都無法更改此限制。)
- 每個請求(進程遭到處罰):有一組適用於請求的附加資源限制(共 15 條)。如果請求超出某個限制,則將終止進程(以及進程中啟動並執行所有 沙箱化解決方案)。
- 每天/每個網站集合(網站集合遭到處罰):每個網站集合均受可配置的每日"資源點"最大數的限制。這些點基於某種演算法進行累計,該演算法會考慮網站集合中安裝的沙箱化解決方案對 15 類資源的使用。當網站集合超出其允許的最大點數時,該網站集合中的所有沙箱化解決方案將終止,且在剩餘時間內再也無法運行。
五、沙箱的分頁呈現
當用戶端電腦請求包含沙箱化解決方案中的組件(例如,沙箱化解決方案中部署的 Web 組件)的 SharePoint 頁時,SharePoint 會呈現多個頁對象。其中一個頁對象在 Microsoft ASP.NET 背景工作處理序 (w3wp.exe) 中呈現,而其他頁對象在沙箱背景工作處理序中呈現。所有非沙箱組件會在 ASP.NET 背景工作處理序中的頁上呈現,而第一個沙箱組件會在沙箱背景工作處理序中的一個頁對象上呈現。在完全呈現沙箱背景工作處理序中的該頁時,會將該頁併入 ASP.NET 進程中的頁對象。如果使用者請求的頁上有多個沙箱組件,則將在這些組件在沙箱背景工作處理序中所對應的頁對象上單獨呈現它們。反過來,每個此類頁對象將併入 ASP.NET 進程中的頁對象。
六、擺脫沙箱限制
沙箱化解決方案可通過兩大方式擺脫常規限制。
1.使用用戶端代碼訪問無法從沙箱化解決方案中的伺服器端代碼訪問的資源。
例如,沙箱化解決方案可包含帶 JavaScript 的自訂網頁,JavaScript 可調用 SharePoint 的 JavaScript 用戶端物件模型。此外,沙箱化解決方案可包含承載 Microsoft Silverlight 應用程式的 Web 組件。後面的應用程式可調用 SharePoint 的 Silverlight 用戶端物件模型。沙箱化解決方案上的任何限制都不適用於用戶端代碼。不存在以下限制:代碼執行限制、資源訪問限制和資源使用率限制。
2.通過完全信任代理。
即開發一個伺服器陣列解決方案,它包括派生自 SPProxyOperation 的一個或多個類,其中的每個類均定義一個將在完全信任下啟動並執行操作,並且可通過 ExecuteRegisteredProxyOperation 方法從沙箱化解決方案中調用這些類。具體而言,將在運行標準 Microsoft.SharePoint.dll 程式集的相同代理進程 (SPUCWorkerProcessProxy.exe) 中執行這些完全信任代理操作。代理操作可將資料返回到沙箱化解決方案。
七、Sharepoint執行的其它情況
並不是所有的Sharepoint 實施都依賴於IIS背景工作處理序(IIS worker process),沙箱背景工作處理序(sandboxed worker process)或其代理進程(proxy process)。下面就是一些例子:
- Sharepoint的Timer Service,用於執行預設的作業,它可以影響其它服務,它以Farm帳戶運行在owstimer進程下。
- SharePoint的Tracing Service ,以本地的服務帳戶(local service account)運行在wsstracing進程下。
- SharePoint Administration Service 以本地系統帳戶(local system account)運行在wssadmin進程下。