【问题标题】:Attempt by security transparent method X to access security critical method Y failed通过安全透明方法 X 尝试访问安全关键方法 Y 失败
【发布时间】:2012-08-09 14:33:20
【问题描述】:

我有一个相当稳定的服务器应用程序版本,已经在几十个客户中部署了将近一年。

一位新客户最近设置了应用程序并收到以下错误:

System.MethodAccessException:通过安全透明方法尝试 [SomeMethod] 访问安全关键方法 [SomeOtherMethod] 失败了。

SomeMethod 和 SomeOtherMethod 都是我编写的程序集中的方法,它们是针对 .NET 4 构建的,并且在 Windows 服务中运行。如果有所不同,SomeOtherMethod 确实引用了针对 .NET 2.0 构建的第 3 方程序集 (EntLib 4.1) 中的类型。查看 EntLib 4.1 的代码,我确实看到它们同时使用 SecurityTransparent 和 APTC 属性,但这从未在其他客户端引起问题。

这些程序集是从 .NET 2.0 CLR 升级而来的,但在很久以前。这个确切的代码在其他客户上运行得很好,我没有明确使用 APTC 属性,也没有在任何地方使用 SecurityCritical 属性。

这使我得出结论,这是一个配置问题,或者可能是 .NET Framework 补丁问题。是否有针对 .NET 发布的补丁会导致这种重大变化?是否有配置设置强制执行这种默认关闭但我的客户可能已启用的检查?

最后一点。我的服务利用 SSRS RDLC 生成 PDF。由于 .NET 4 中的一些变化,我必须通过以下配置强制服务使用旧版安全策略:

  <runtime>
    <NetFx40_LegacySecurityPolicy enabled="true" />
  </runtime>

有关我为什么需要这样做的更多详细信息,请参阅此 stackoverflow 帖子:Very High Memory Usage in .NET 4.0

重要的是,我对所有其他客户也这样做。只有这一位客户有问题。

【问题讨论】:

    标签: security .net-4.0 cas code-access-security


    【解决方案1】:

    唉,负责企业库的 Microsoft 模式和实践团队所采用的模式和实践非常可悲。好吧,例外是准确的,你不能从装饰有“嗯,我不会检查安全性所以不要费心烧CPU周期来检查它”的代码中调用一个装饰为“我一定会检查安全性”的方法.这与 Java 中使用的异常规范一样可扩展。 CAS 非常有用,但诊断异常是一件令人头疼的事情,并且通常涉及您不拥有且无法修复的代码。它在 .NET 4 中被弃用的主要原因。

    编辑完成。解决这个问题,你需要找出为什么在这里强制执行 CAS。对此最简单的解释是该服务没有完全信任地运行。 那个最简单的解释是客户端没有在本地硬盘上安装服务。或者即使在本地程序集上通常以不信任模式运行代码,一个非常偏执的管理员可能更喜欢这样做。这需要使用 Caspol.exe 进行配置,该工具的命令行选项与 CAS 一样神秘。在不受信任的位置解释中进行射击,您的客户需要运行 Caspol,如 blog post 所示。或者只是简单地在本地部署服务,以便应用默认的“我信任你”。

    在 OP 发现的真正原因中进行编辑:当从不受信任的 Internet 或网络位置下载文件时,请注意 alternate data stream 会被添加到文件中。该文件将获得一个名为“Zone.Identifier”的流,该流使用“ZoneId”值跟踪它的来源。正是该值覆盖了从存储位置派生的信任。通常把它放在 Internet 区域。使用资源管理器,右键单击文件并单击“取消阻止”以删除该流。在您确定可以信任该文件之后:)

    【讨论】:

    • 这是有道理的。我今天正在检查这个。我的第一个想法实际上是由于 Windows 中将通过电子邮件或 IE 下载的文件标记为不安全的功能而阻止了程序集。我以前被咬过。
    • 您的回答很有帮助。事实上,事实证明是阻塞的程序集把事情搞砸了。删除文件阻止(属性 -> 取消阻止)解决了这个问题。
    • @RMD 谢谢!该死的Windows。
    【解决方案2】:

    如果它可以帮助其他人,我会发布我的解决方案:

    1) 在 AssemblyInfo.cs 上,删除/注释了 [assembly: SecurityTransparent] 行。

    2) 执行实际作业的类和方法标记为[SecuritySafeCritical],在我的例子中是建立网络连接:

    [SecuritySafeCritical]
    public class NetworkConnection : IDisposable
    {
        [SecuritySafeCritical]
        public NetworkConnection(string networkName, NetworkCredential credentials)
        {
            .............
        }
    }
    

    3) 调用者类和方法被称为 [SecurityCritical]:

    [SecurityCritical]
    public class DBF_DAO : AbstractDAO
    {
        [SecurityCritical]
        public bool DBF_EsAccesoExclusivo(string pTabla, ref ArrayList exepciones)
        {
            ....
            using (new NetworkConnection(DBF_PATH, readCredentials))
            {
                ....
            }
        }
    }
    

    【讨论】:

    • 谢谢乔尔曼。我遇到了同样的问题。这是帮我解决的
    【解决方案3】:

    在使用他们的 ServiceModelEx 库时,我在运行从 http://www.idesign.net/ 下载的 WCF 示例时遇到了类似的问题。 我在 ServiceModelEx 项目的 AssemblyInfo.cs 中注释掉了以下行

    //[assembly: AllowPartiallyTrustedCallers]
    

    它对我有用。

    【讨论】:

    • 我正在使用通过 ClickOnce 部署的 WinForms 应用程序中的库。 ClickOnce 是上面描述的@hans-passat CAS 的野兽。幸运的是,我有该库的源代码,因此注释掉上面的行为我解决了这个问题。
    • 谢谢 - 经过大量搜索后,这对我有用。似乎您的某些程序集在其 AssemblyInfo.cs / .vb 文件中具有此指令,而有些则没有,这就是 .net 感到困惑的地方 - 删除它的所有实例似乎可以解决问题
    【解决方案4】:

    在我的情况下,当我在解决方案中管理 NuGet 包时,某些包会覆盖主网站项目中的 System.Web.Mvc 程序集版本绑定,这是一个问题。设置回 4.0.0.0(我安装了 5.0)。我没有更改通知更改,因为 Mvc v4.0 已安装并可通过 GAC 访问。后退

    【讨论】:

      猜你喜欢
      • 2013-12-13
      • 1970-01-01
      • 1970-01-01
      • 2014-06-09
      • 2017-03-15
      • 1970-01-01
      • 2014-11-06
      • 2013-10-04
      • 2015-06-20
      相关资源
      最近更新 更多