【问题标题】:How can I use AOP to intercept the constructor of File, FileReader, FileWriter, FileInputStream and FileOutputStream?如何使用 AOP 拦截 File、FileReader、FileWriter、FileInputStream 和 FileOutputStream 的构造函数?
【发布时间】:2014-06-25 00:07:16
【问题描述】:

我想拦截 File、FileReader、FileWriter、FileInputStream 和 FileOutputStream 的构造函数,并防止任何文件名包含“..”(防止路径遍历攻击)或“\0”(防止文件名空字符攻击)。

我还有一个关于如何使用 SecurityManager 做同样事情的未决问题,但还没有人回答,所以我希望这种替代方法能奏效。

这是用于 tomcat 上的 spring webapp。

我知道我可以通过创建自己的 SafeFile、SafeFileReader 等类并修改代码以使用它们来手动执行此操作。但是,我们的代码中有 960 个地方使用了这些对象的构造函数,所以我宁愿避免这种情况,除非这是唯一的方法。

【问题讨论】:

  • 你有接受文件路径作为参数的 960 个服务吗?虽然您可能有 960 个与文件交互的位置,但路径的来源真的到处都是不可信的吗?
  • 与其使用繁重的方法作为 AOP 相比,使用工厂来创建文件不是更容易。修改960个地方使用那个工厂,你就解决了。修改所有这些地方应该不难重构。当然,您可以使用 AspectJ 做任何您想做的事情,并使用加载时编织(不是使用普通 Spring AOP)修改您提到的类,但感觉就像使用大炮杀死苍蝇。

标签: java spring aop aspectj


【解决方案1】:

即使 Sotirios Delimanolis 链接到这里的答案是正确的(我自己写的),只要 AspectJ 而不是基于代理的 Spring AOP 是必要的,请注意,您不能将 execution(*.new(..)) 用于 JDK 类,因为它们被排除在外默认情况下从方面编织。为了织入 JDK 类(执行连接点在逻辑上在被调用者代码中),您需要修改 JDK 的 rt.jar 或至少将修改后的 JDK 类放在 JDK 本身之前的 bootclasspath 上。这是可能的,但不是那么简单。

但是有一个更简单的选择:通过call(*.new(..)) 编织到调用者(您自己的代码),而不是被调用者 - 注意call()execution() 之间的区别。这反过来意味着您不能拦截对不是由您自己的编织代码或来自 JDK 本身的 JDK 类的调用。因此,如果您需要一个 100% 的解决方案,即使对于不受您自己控制的代码,您最终也会编织 JDK。如果您只想保护自己的课程,可能没有必要这样做。 :-)

尽管我是 AspectJ 的忠实拥护者,但我想强调我也是干净代码和重构的坚定支持者。任何像 IntelliJ IDEA 或 Eclipse 这样的体面的 IDE 都应该使重构 960 调用以使用您建议的安全包装器类变得非常简单。如果它如此重要,你为什么不这样做呢? IDEA 的结构搜索和替换可以在几分钟甚至几秒钟内为您完成。 AOP 可以,但不应该用来修补你自己代码的缺陷。所以请去重构,你会更快乐。

【讨论】:

  • FWIW,既然你知道如何用 aop 来做,然后说我应该重构,我就继续重构了。我为 QA 部门感到难过,但这样理解当然很简单。
【解决方案2】:

Simple Spring AOP (with proxying) does not support constructor join points.

Spring AOP 目前只支持方法执行连接点 (建议在 Spring bean 上执行方法)。

如果你可以选择aspectjthat should do the trick。否则,您将不得不自己使用字节码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多