如何阻止或拦截对 Directory.Delete(path, true) 的调用



最近我正在调试一个"噗-所有客户-数据消失"的问题。没花太多时间就发现错误的分支导致了Directory.Delete(customerRoot, true)行代码。灾难性的行是由常规的GUI开发人员编写的。导致这种灾难的线路并不多。所以我的问题是如何防止这个特定的电话。(DirectoryInfo.Delete()是第二个)。

这是我列出的可能解决方案的优先级列表

  • 编译错误,没有第三方更改构建过程
  • 运行时拦截,没有第三方
  • 使用第三方进行运行时拦截(不更改构建过程)
  • 第三方编译错误(我想PostSharp会这样做)
  • 面向 GUI 开发人员的教育研讨会,了解客户如何热爱他们的数据

还有其他想法吗?

我会提到我们的系统有一个专门的服务(验证和记录)用于文件/文件夹删除。

要在运行时"拦截"调用,您可以使用 FileSystemWatcher 类,但它实际上不会阻止删除,只需让您知道它已经发生。防止实际删除要棘手得多。Windows不提供Linux的ptrace功能,因此您无法拦截系统调用本身(这里有一篇关于此的文章,但据我所知,可用性相当有限)。其他人的建议 - 设置访问权限和信任级别 - 可能会起作用,但是当您确实需要删除某些内容并且您的"删除服务"只是.NET方法的包装器时,您也会阻止它工作。

另一种选择是使用第三方工具并在编译时检查这一点 - 这个问题正好有你需要的东西,包括示例,并且有更多的工具可以做到这一点(我只使用 Resharper,但我想它也可以完成任务)。

但是,我不认为这是这里的重点。你的开发人员犯了一个错误,它破坏了一些客户数据,没有人对此感到高兴。这并不意味着您需要制定系统范围的规则并强制执行该规则,这意味着开发人员应该更好地测试他或她的代码和/或应该使用您提到的删除服务(无论那是什么)。无论你多么努力,你都无法阻止人们做傻事。您不想花费时间和金钱围绕 Directory.Delete() 方法进行防御工事,只是为了发现其他人犯了一个不同的愚蠢错误,而这个特定的事情将永远不会再成为问题。除非像这样的问题(滥用 Directory.Delete() )在你的系统中比平时更容易发生,否则放手,专注于其他事情。

您可以将应用程序修改为不在完全信任下运行。配置限制对物理磁盘访问的信任级别。看看FileIOPermission。请注意,这可以针对特定位置进行配置,从而为您提供相当多的控制。

良好的需求概览

更新再想一想,我也会建议做一个"保姆测试"。如果要执行任何类型的测试,则可以添加一个测试,该测试查看程序集中的所有类型,并检查对任何 FileSystem 方法的调用。任何此类调用都需要在白名单上,否则测试将失败。我正在从事的项目使用了这个,它提供了很多价值。

更新 2有人评论如何进行这种类型的保姆测试。基本上,您需要使用反射来获取所有方法,然后在 IL 中查找禁止的调用。这听起来比实际更复杂。

从程序集中提取特定 IL(.NET 中间语言)签名的机制

更新 3还有另一种更好的方法来进行这种类型的保姆测试,它不直接涉及弄乱 IL。我在我的博客上发布了一篇文章如何做到这一点。

http://datatoknowledge.com/2012/09/10/nanny-tests/

埃里克

您可以在全局包含的命名空间中包含单独的目录类(和 DirectoryInfo) - 这不会阻止某人使用 System.IO.Directory.Delete,但这是另一个想法,可能有助于捕获它并推迟它们,特别是如果您包含一个相同的虚拟函数,该函数会抛出带有消息的异常。

最新更新