【问题标题】:Why does creating List<> from GAC'd assembly fail in sandboxed plugin?为什么在沙盒插件中从 GAC 程序集创建 List<> 失败?
【发布时间】:2012-12-01 02:28:53
【问题描述】:

我正在尝试编写一个 MS Dynamics CRM 2011 插件以在沙盒模式下运行,但使用 GAC 程序集中的类。我遇到了一个问题,即从 GAC 程序集创建类型列表会产生错误,我不明白为什么。生成的异常是System.MethodAccessException 类型,并且有这样的消息:

Attempt by method 'IsolatedModeExceptionsTestingPlugin.Plugin.Execute(System.IServiceProvider)' to access method 'System.Collections.Generic.List`1<System.__Canon>..ctor()' failed.

有人可以解释为什么这会失败,以便我可以修改我的代码/环境来解决失败吗?

我在下面的一组简单的类中重新创建了场景。

我在运行 Dynamics 2011 Rollup 7 的 Win2008 R2 服务器上运行测试,然后在 Rollup 11 上再次运行。 我的两个程序集都是针对 .Net 4.0 构建的,Dynamics IIS AppPool 是为 .Net 4 配置的。两个程序集都经过签名(使用相同的密钥对)。

请注意,如果我将插件的隔离模式从“沙盒”更改为“无”,插件可以正常工作——只有在沙盒模式下才会发生这种情况,这意味着在生成列表时存在某种安全违规。另请注意,创建一个 List(或其他 .Net 类型)可以正常工作,就像在我自己​​的程序集中创建一个 List 类一样。它似乎特定于 GAC 的程序集。

我在 GAC 中放置的程序集名为“ClassLibrary1”并且只包含一个类:

namespace ClassLibrary1
{    
    public class MyCustomAssemblyClass
    {
        public string GetAString()
        {
            return "The current time is " + System.DateTime.Now.ToString();
        }
    }
} 

我通过在服务器(已安装 Windows SDK v7.1)上运行以下命令将其放入 GAC:"c:\program files\Windows SDKs\Windows\v7.1\bin\NETFX 4.0 Tools\gacutil.exe" -i classlibrary1.dll

我的插件代码如下所示:

using System.Collections.Generic;
using System.Text;
using System;
using ClassLibrary1;
using Microsoft.Xrm.Sdk;

namespace IsolatedModeExceptionsTestingPlugin
{
    public class Plugin : IPlugin
    {
        public void Execute(IServiceProvider serviceProvider)
        {            
            var pluginExecutionContext = (IPluginExecutionContext) serviceProvider.GetService(typeof (IPluginExecutionContext));
            var tracingService = (ITracingService) serviceProvider.GetService(typeof (ITracingService));

            try
            {
                tracingService.Trace("Entered Plugin.Execute()");
                tracingService.Trace(string.Format("Isolation Mode: {0}, Mode: {1}\n\n",
                                                   pluginExecutionContext.IsolationMode,
                                                   pluginExecutionContext.Mode));

                try
                {                    
                    tracingService.Trace(string.Format("*** Creating List<{0}>", typeof (MyCustomAssemblyClass)));
                    var list = new List<MyCustomAssemblyClass>(); //XXX Exception thrown here!!
                    tracingService.Trace("    Success");
                }
                catch (Exception ex)
                {                    
                    tracingService.Trace(GetExpectionTraceMessage(ex));
                    throw new Exception("An error occurred in one of the tests", ex);
                }
                finally
                {
                    tracingService.Trace("*** Finished TestListOfGACClassCxtr\n\n");
                }

                //This will force a failure to allow viewing of the trace file
                //    throw new Exception("TEST SUCCESSFULL");                

            }           
            finally
            {
                tracingService.Trace("Exiting Plugin.Execute()");
            }
        }


        private string GetExpectionTraceMessage(Exception ex)
        {
            var message = new StringBuilder();
            message.AppendFormat("EXCEPTION: {0}\n", ex.GetType());
            message.AppendFormat("\tMessage: {0}\n", ex.Message);
            message.AppendFormat("\tStack: {0}\n", ex.StackTrace);

            if (ex.InnerException != null)
            {
                message.AppendLine("---- INNER EXCEPTION ----");
                message.AppendLine(GetExpectionTraceMessage(ex.InnerException));
            }

            return message.ToString();
        }

    }
}

当实体更新时,我将插件注册为在数据库中以沙盒模式运行。执行插件后,我通过“业务流程错误”对话框的“下载日志文件”得到以下输出:

Unhandled Exception: System.ServiceModel.FaultException`1[[Microsoft.Xrm.Sdk.OrganizationServiceFault, Microsoft.Xrm.Sdk, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]: Unexpected exception from plug-in (Execute): IsolatedModeExceptionsTestingPlugin.Plugin: System.Exception: An error occurred in one of the testsDetail: 
<OrganizationServiceFault xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/xrm/2011/Contracts">
  <ErrorCode>-2147220956</ErrorCode>
  <ErrorDetails xmlns:d2p1="http://schemas.datacontract.org/2004/07/System.Collections.Generic" />
  <Message>Unexpected exception from plug-in (Execute): IsolatedModeExceptionsTestingPlugin.Plugin: System.Exception: An error occurred in one of the tests</Message>
  <Timestamp>2012-11-29T18:09:26.5671559Z</Timestamp>
  <InnerFault i:nil="true" />
  <TraceText>

[IsolatedModeExceptionsTestingPlugin: IsolatedModeExceptionsTestingPlugin.Plugin]
[6d245108-b638-e211-bae5-000c29d5e4ba: IsolatedModeExceptionsTestingPlugin.Plugin: Update of new_insurancequote]

Entered Plugin.Execute()
Isolation Mode: 2, Mode: 0


*** Creating List&lt;ClassLibrary1.MyCustomAssemblyClass&gt;
EXCEPTION: System.MethodAccessException
    Message: Attempt by method 'IsolatedModeExceptionsTestingPlugin.Plugin.Execute(System.IServiceProvider)' to access method 'System.Collections.Generic.List`1&lt;System.__Canon&gt;..ctor()' failed.
    Stack:    at IsolatedModeExceptionsTestingPlugin.Plugin.Execute(IServiceProvider serviceProvider)

*** Finished TestListOfGACClassCxtr


Exiting Plugin.Execute()


</TraceText>
</OrganizationServiceFault>

作为参考,.Net 框架似乎使用 System.__Canon 类型在 JIT 中为所有泛型创建可重用代码。见:http://www.marklio.com/marklio/PermaLink,guid,1fa8a82b-a6d6-4fbb-8cca-5e352ff3c9e9.aspx

【问题讨论】:

  • 1.请确认上面的确切代码正在生成引用的错误。我遇到过人们发布简化代码的问题,但真正的错误在于实际的、更复杂的代码。 2. 如果您将 GAC 的代码重新定位到插件 DLL 本身,错误会自行解决还是在沙盒模式下运行时仍然出现?
  • @Nicknow 回答:1)这是我发布的确切代码,2)如果我将类从 GAC 程序集移到我的插件程序集中,我使用该类没有问题。跨度>

标签: c# dynamics-crm-2011


【解决方案1】:

隔离模式模仿 CRM Online。在 CRM Online 中,如果不检查低级别原因,您就无法从根本上添加到 GAC,我相信这就是您的代码失败的原因。

(因此我猜List&lt;&gt; 是一个红鲱鱼,甚至实例化 GACed 类型的单个实例也会失败)

编辑

GAC 默认授予程序集完全信任。在沙盒/隔离模式下运行的插件在部分信任下运行 - 这就是为什么我不相信你在沙盒模式下运行时能够实例化 MyCustomAssemblyClass (这就是为什么我认为 List&lt;&gt; 无关紧要) .

从下面我自己的评论中-我认为这是对它的总结:

我认为这个问题从根本上是一个提升 - 即是否一个 部分受信任的程序集(即插件,它被限制在 它可以做什么)应该被信任以运行完全信任的插件 (可以做任何事情)。如果部分信任,这似乎是合乎逻辑的 代码被允许运行完全信任的代码,它会有效地 因此提升部分信任程序集的权限 创建漏洞。

【讨论】:

  • CRM 2011 确实支持访问 GAC 中的 DLL。在 CRM Live 中,您无法部署到 GAC,因此您仅限于 MS 服务器提供的内容 - .NET 4 和 CRM DLL。在本地部署中,您可以访问在 GAC 中注册的 DLL。也就是说,这些 DLL 仍然受到某些限制,据我所知,这些限制并没有很好地定义。
  • 我认为我们说的是同一件事...问题是隔离模式而不是 OP 所指出的 GAC。
  • @GregOwens 你说得对,这并不特定于 List。我修改了代码以将 List 构造函数替换为“var list = new MyCustomAssemblyClass();”,这也引发了异常:尝试通过安全透明方法“IsolatedModeExceptionsTestingPlugin.Plugin.Execute(System.IServiceProvider)”进行访问安全关键方法“ClassLibrary1.MyCustomAssemblyClass..ctor()”失败。我不明白为什么我不能从 GAC 运行代码。正如您所提到的,这些应该得到充分的信任,这应该使它们更容易获得,而不是更少。
  • 我认为这个问题从根本上是一个提升问题 - 即是否应该信任 部分 受信任的程序集(即插件,它的功能受到限制)运行一个完全受信任的插件(它可以做任何事情)。如果允许部分信任的代码运行完全信任的代码,这似乎是合乎逻辑的,它将有效地提升部分信任的程序集的权限,从而产生漏洞。
  • @GregOwens 但这就是为什么它需要服务器操作系统上的管理权限才能将 .dll 添加到 GAC。因此,通过在 GAC 中添加内容,您(服务器管理员)是在说“我信任此代码,让它以完全信任的方式运行”。
【解决方案2】:

查看this link 并尝试将允许部分受信任的调用者属性添加到您的 GAC。

最终,CRM 使用 .NET 4 (link on AppDomain) 中的 AppDomain 类并使用 AppDomain 运行沙盒插件。

我面临的挑战是,我找不到任何 Microsoft 文档清楚地说明 CRM 沙盒服务将哪些规则应用于它为执行插件而创建的 AppDomain。这使得在 GAC 中配置一个类以使其可由沙盒代码调用基本上是反复试验。

【讨论】:

    猜你喜欢
    • 2017-03-20
    • 2012-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-29
    • 2012-01-31
    • 1970-01-01
    • 2017-08-16
    相关资源
    最近更新 更多