我们正在ASP.NET应用程序中调用System.IO.Packaging.Package.Open()。此外,在调用此命令之前已执行Windows模拟,因为要打开的包存储在安全的位置,并且需要模拟才能读取它。
问题是Package.Open()调用EventTrace.EasyTraceEvent(),该事件又调用MS.Utility.EventTrace.IsClassicETWRegistryEnabled(),该事件抛出了请求的注册表访问的安全异常。
即使在Web.config中特别禁用,也会发生这种情况。在调试和发布模式下。
因此我的困境。模拟是必需的,因为文件(包)的存储方式仅使模拟帐户可以访问。将其复制到不安全的位置将破坏安全性的目的。
授予模拟帐户对注册表的访问权限会在另一个方向上打开一个安全漏洞。除了一组特定的文件和文件夹之外,该帐户无权访问任何其他系统资源。
我真正想要的是让EventTrace跳下悬崖,但我不知道如何告诉它做到这一点。
有什么想法吗?
简短回答:使用流。进行模拟以打开流,结束模拟,然后将仍然打开的流传递给Package.Open()。
长回答:
错误的来源是EventTrace的静态类初始化程序。它调用IsClassicETWRegistryEnabled(),然后依次访问注册表。因为它在类初始化器中,所以它意味着无法禁用它,并且在模拟方面,EventTrace从根本上被破坏。
Package.Open()实际上是"new ZipPackage()"的包装。
ZipPackage是Package抽象类的密封实现。
ZipPackage没有公共构造函数。
ZipPackage依次在ZipArchive上使用内部方法,该方法在MS.Internal.IO.Zip命名空间中,并且也是密封的类。
结论:
System.IO.Packaging在模拟没有足够的注册表访问权限时,模拟遇到问题。
System.IO.Packaging应该被视为私有的Microsoft名称空间,而不是公共的名称空间。
选项:
将文件移出安全区域,因此无需模拟。
不需要模拟时加载文件,并以其他方式存储数据(例如,在数据库中)。
在模拟下打开流,结束模拟,然后在该流上使用Package.Open()。
[如果有人好奇我们正在阅读的软件包是Visio 2013 VSDX文件。
我浏览了.NET源引用,它需要访问的密钥是HKEY_CURRENT_USER \ Software \ Microsoft \ Avalon.Graphics。授予该特定密钥“所有人”的读取访问权限不会产生我认为可以解决的安全问题,并且可以解决问题。