如何从匿名委托或lambda访问安全关键字段?

Mat*_*zer 19 .net c# security .net-4.0 .net-4.5

脚本

假设我们有下一个代码:

[SecuritySafeCritical]
public void SomeMethod()
{
    SomeCriticalClass critical = new SomeCriticalClass();

    Action someDelegate = () => 
    {
         critical.Do();
    }

    someDelegate();
}
Run Code Online (Sandbox Code Playgroud)
  1. SomeMethod签名具有[SecuritySafeCritical]属性.
  2. SomeCriticalClass是一些[SecurityCritical]在类或方法Do级别具有属性的类.
  3. 我们创建一个自动推断的匿名委托Action.

问题

调用critical.Do()导致a 因为安全透明方法(匿名方法)正在尝试访问安全关键字段(SomeCriticalClass局部变量).MethodAccessException FieldAccessExceptioncritical

你怎么克服这个?

简单的方法是实现标记的实际方法,[SecuritySafeCritical]而不是使用匿名委托.但这将我们带到了前匿名代表和拉姆纳斯时代.我不想要这个.

其他简单的方法就是不使用安全透明度.这不是解决方案.

几乎所有来自Microsoft和开源社区的可用库都没有考虑到安全透明性.也就是说,任何自己的自定义代码都必须通过[SecuritySafeCritical]或者[SecurityCritical]/ methods/properties/delegates 与第三方库进行互操作.

实际上我相信安全透明度是一个很好的工具,因为它会强制更好,更安全的软件设计,关键操作非常本地化,其余代码以最小的权限工作.

Mat*_*zer 18

对不起,我等不及其他的回答者...我得到了解决方案!

通过实验,我可以确定用[SecuritySafeCritical]具有在其体内创建匿名方法的方法的类进行标记,就可以了!

换句话说,或者谈论代码:

[SecurityCritical]
public class SomeCriticalClass
{
      [SecurityCritical]
      public void Do()
      {
      }
}

[SecuritySafeCritical]
public sealed class SomeClass
{
    [SecuritySafeCritical]
    public void SomeMethod()
    {
          SomeCriticalClass critical = new SomeCriticalClass()

          // No more FieldAccessException!
          Action action = () => critical.Do();         
    }
}
Run Code Online (Sandbox Code Playgroud)

我想澄清一下:

  • 标志着类SomeClass[SecuritySafeCritical],并不意味着所有声明的方法将是[SecuritySafeCritical]默认.这意味着该类可以由部分信任的调用者使用.您仍然需要使用[SecuritySafeCritical]属性标记可由部分信任的调用方访问的方法,属性或字段.

  • 似乎[SecuritySafeCritical]在类级别使局部变量和匿名方法(也许是匿名对象!)安全性安全至关重要.

是! 我希望我的问题和我自己的答案对每个人都有用,因为我相信我的问题所描述的情况经常发生!

  • @JeroenWiertPluimers 没问题!我很高兴它对其他 stackoverflowers 有用!;) (2认同)