上文我们了解了一个外部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 工作进程的前端 Web 服务器。可在管理中心应用程序内配置要使用的服务器,这种配置有两种选项。
I、"本地模式(local mode)":这意味着将在运行 IIS 工作进程(W3WP)的同一前端 Web 服务器上处理对沙盒解决方案的每个请求,即本地处理。
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 策略施加的限制如下:
- 沙盒中的代码不能调用非托管代码。
- 沙盒中的代码不能调用 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进程下。