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

Posted

技术标签:

【中文标题】如何从匿名委托或 lambda 访问安全关键字段?【英文标题】:How to access a security critical field from an anonymous delegate or lambda? 【发布时间】:2012-12-07 01:07:41 【问题描述】:

场景

假设我们有下一个代码:

[SecuritySafeCritical]
public void SomeMethod()

    SomeCriticalClass critical = new SomeCriticalClass();

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

    someDelegate();

    SomeMethod 签名具有[SecuritySafeCritical] 属性。 SomeCriticalClass 是在类或方法Do 方法级别中具有[SecurityCritical] 属性的类。 我们创建了一个匿名委托,自动推断为Action

问题

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

问题

你是如何克服这个问题的?

简单的方法是实现一个标有[SecuritySafeCritical] 的实际方法,而不是使用匿名委托。但这使我们进入了匿名代表和lambas时代。 我不想要这个。

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

几乎所有来自 Microsoft 和开源社区的可用库在设计时都没有考虑到安全透明性。也就是说,任何自己的自定义代码都必须通过[SecuritySafeCritical][SecurityCritical] 方法/属性/委托与第三方库进行互操作。

实际上,我认为安全透明性是一个很好的工具,因为它可以强制进行更好、更安全的软件设计,关键操作非常本地化,并且其余代码以最少的权限运行。

【问题讨论】:

在您给出的特定情况下,您根本不需要 lambda。你可以只使用Action someDelegate = critical.Do;,不是吗? 在这个问题上查看 MSDN .. 谷歌错误就像我做的那样让你有一个很好的起点来解决这个问题。 msdn.microsoft.com/en-us/library/bb264475.aspx 或 msdn.microsoft.com/en-us/library/dd233102.aspx @JonSkeet 我是我的真实世界场景并不那么容易。好吧,我可以做到,但这不会在一个地方,而是在很多地方。这非常糟糕,因为使用安全透明性使我无法使用现代且紧凑的匿名 lambda 委托,这节省了大量代码行并使代码更小但可读性。 @MatíasFidemraizer:正如您在问题的底部所说的那样 - “关键操作非常本地化” - 如果您没有很多地方可以这样做,您可以保留 most i> 你的代码“现代”,只是在几个地方有更详细的代码 @DJKRAZE 感谢您的贡献,但我真的知道安全透明的工作原理。我问这个问题是因为这是使用它的真正限制。 【参考方案1】:

抱歉,我等不及其他回答者了……我找到了解决方案!

通过实验,我可以确定使用[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();         
    

我想澄清一下:

[SecuritySafeCritical] 标记类SomeClass 并不意味着所有声明的方法默认都是[SecuritySafeCritical]这意味着该类可以被部分信任的调用者使用。您仍然需要用[SecuritySafeCritical] 属性标记那些可以被部分信任的调用者访问的方法、属性或字段。

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

是的! 我希望我的问题和我自己的回答都对大家有用,因为我相信我的问题中描述的情况会经常发生!

【讨论】:

@JeroenWiertPluimers 没问题!我很高兴它对其他 ***ers 有用! ;) 这似乎不是一个安全漏洞吗?如果您的匿名方法的隐藏实现被标记为 SecuritySafeCritical,那么任何具有足够权限(带有 ReflectionPermissionFlag.MemberAccess 标志的ReflectionPermission)的人都可以调用它。 @LOST 也许你是对的。顺便说一句,这个问题已经过去很长时间了,我不确定在我的情况下我是否根本没有那个安全漏洞..

以上是关于如何从匿名委托或 lambda 访问安全关键字段?的主要内容,如果未能解决你的问题,请参考以下文章

从匿名方法到 Lambda 表达式的推演过程

委托与匿名委托

#yyds干货盘点#愚公系列2023年02月 .NET/C#知识点-委托匿名方法Lambda泛型委托表达式树的进化史

linq-匿名方法,匿名委托,lambda演化

linq和匿名方法委托匿名委托lambda

lambda,linq