沙箱环境是一种受限的执行环境,它允许程序仅访问特定的资源,并防止沙箱中发生的问题影响到服务器环境的其他部分。实时应用程序将在沙箱环境中托管和执行,但完全在沙箱执行范围内完成项目是不现实的。在许多情况下,可能需要创建文件、访问文件系统或以Farm Admin身份执行某些操作。
为了演示这种情况,创建了一个沙箱解决方案,其中包含一个简单的Web部件,该Web部件有一个简单的按钮。以下是Web部件的代码:
        namespace SandboxTest.TestWebpart {
            [ToolboxItemAttribute(false)]
            public class TestWebpart : WebPart {
                protected override void CreateChildControls() {
                    Button objBtn = new Button { Text = "Submit", ID = "btnSubmit" };
                    objBtn.Click += new EventHandler(btnSubmit_Click);
                    this.Controls.Add(objBtn);
                }
                protected void btnSubmit_Click(object sender, EventArgs e) {
                    ((Button)sender).Text = FullTrustMethod("Pratap", 100);
                }
                protected string FullTrustMethod(string strParameter, int intParameter) {
                    string strReturnValue = "";
                    SPSecurity.RunWithElevatedPrivileges(delegate() {
                        strReturnValue = strReturnValue + "String Parameter = " + strParameter + "; Integer Parameter = " + intParameter.ToString();
                    });
                    return strReturnValue;
                }
            }
        }
    
按钮点击事件将调用一个FullTrustMethod()方法,该方法以提升的权限执行代码,并在按钮上显示简单文本,如下所示。但如果尝试执行这段代码,将得到一个错误,提示在部分信任环境中尝试执行全信任代码。
这就是代理类发挥作用的地方。实现并注册代理以从沙箱解决方案执行全信任代码涉及几个步骤。
步骤1:创建一个单独的SharePoint解决方案,以农场解决方案模式运行。将把沙箱解决方案中的全信任代码移动到这个农场解决方案中。
步骤2:创建一个代理类,其中嵌入了全信任方法。代理类应该继承自SPProxyOperation基类。
        namespace SandboxProxyTest {
            public class ProxyFullTrustClass : SPProxyOperation {
                public override object Execute(SPProxyOperationArgs args) {
                    var proxyargs = args as SandboxProxyArgs;
                    return FullTrustMethod(proxyargs.strParameter, proxyargs.intParameter);
                }
                protected string FullTrustMethod(string strParameter, int intParameter) {
                    string strReturnValue = "";
                    SPSecurity.RunWithElevatedPrivileges(delegate() {
                        strReturnValue = strReturnValue + "String Parameter = " + strParameter + "; Integer Parameter = " + intParameter.ToString();
                    });
                    return strReturnValue;
                }
            }
        }
    
步骤3:创建一个类,列出特定全信任方法所需的所有参数。这个类应该继承自SPProxyOperationArgs基类。
        namespace SandboxProxyTest {
            [Serializable]
            public class SandboxProxyArgs : SPProxyOperationArgs {
                public string strParameter { get; set; }
                public int intParameter { get; set; }
                public static string ProxyOperationTypeName {
                    get { return "SandboxProxyTest.ProxyFullTrustMethod"; }
                }
                public static string ProxyAssemblyName {
                    get { return "SandboxProxyTest, Version=3.0.0.0, Culture=neutral, PublicKeyToken=104629d871066b35"; }
                }
            }
        }
    
为代理操作类添加只读属性,包括类型名称和程序集名称。类型名称应该是完全限定的,程序集名称应该是程序集的四部分强名称。
步骤4:在AssemblyInfo.cs中进行一些更改。根据在ProxyAssemblyName属性中分配的值更改版本号。
        [assembly: AssemblyVersion("3.0.0.0")]
        [assembly: AssemblyFileVersion("3.0.0.0")]
        [assembly: AllowPartiallyTrustedCallers]
    
添加以下属性,使程序集可以从沙箱解决方案调用。
步骤5:为农场解决方案添加一个功能和一个接收器。现在,需要使用UserCode服务注册代理操作和代理参数,以使代理方法对所有沙箱调用者可用。将使用功能激活方法来实现这一点。
        [Guid("36d1494b-decd-45b9-bc6e-6ad06536f81a")]
        public class SandboxProxyFeatureEventReceiver : SPFeatureReceiver {
            public override void FeatureActivated(SPFeatureReceiverProperties properties) {
                SPUserCodeService userCodeService = SPUserCodeService.Local;
                var FullTrustOperation = new SPProxyOperationType(
                    SandboxProxyArgs.ProxyAssemblyName,
                    SandboxProxyArgs.ProxyOperationTypeName);
                userCodeService.ProxyOperationTypes.Add(FullTrustOperation);
                userCodeService.Update();
            }
        }
    
完成代理创建后,部署项目并激活添加的功能。仅作为验证,请转到GAC并验证程序集,其名称、文化、版本和公钥令牌详细信息是否在步骤3中正确提及。
步骤6:回到沙箱解决方案,注释掉webpart.cs类中的fulltrust方法。将代理解决方案的引用,即SandboxProxyTest.dll,添加到沙箱项目中。
现在修改btnSubmit_Click()方法,以调用注册的代理方法,而不是Full-Trust方法本身。
        protected void btnSubmit_Click(object sender, EventArgs e) {
            var proxyargs = new SandboxProxyTest.SandboxProxyArgs();
            proxyargs.strParameter = "Pratap";
            proxyargs.intParameter = 100;
            var result = SPUtility.ExecuteRegisteredProxyOperation(SandboxProxyTest.SandboxProxyArgs.ProxyAssemblyName,
                SandboxProxyTest.SandboxProxyArgs.ProxyOperationTypeName, proxyargs);
            ((Button)sender).Text = result.ToString();
        }
    
部署沙箱项目并验证Web部件的按钮执行。
最终!使用代理从沙箱项目中执行了全信任代码(GAC部署)程序集。