我正在尝试
PropertyChangeSupport
,它有有用的 firePropertyChange
方法。如果安全性是一个问题,那么使用反射来触发方法(如下面的行所示)实际上是否安全,或者简单地硬编码对方法名称的调用是否更好?如果反射是一个潜在问题,如何防止它?
method.invoke(instance, newValue);
如果安全性是一个问题,那么使用反射来触发方法实际上是否安全[...],或者简单地硬编码对方法名称的调用是否更好?
一般来说,最好不要使用反射。如果您使用普通(非反射)调用,您的应用程序将更快、更简单(例如更少的代码行)并且更不易脆弱(例如不太可能抛出未经检查的异常)。最好仅在更简单的方法不起作用时才使用反射。
[更新 - 以下讨论仅适用于旧版本的 Java。 Java 安全管理器和安全沙箱已被弃用,并且从 Java 17 开始删除该功能。Java 不再支持运行不受信任的代码。]
反射的安全性也是一个潜在的问题。
如果您的 JVM 正在运行不受信任或未知的代码,这些代码可能会尝试做坏事,那么反射 API 通常会提供很多做坏事的机会。例如,它允许不良代码调用 Java 编译器会阻止的方法和访问字段。 (它甚至允许代码做一些邪恶的事情,例如更改
final
属性的值以及其他通常被认为是不可变的事情。)
即使您的 JVM 运行完全可信的代码,设计缺陷或系统级安全问题仍然有可能允许黑客注入类或方法名称。然后,反射 API 会尽职尽责地尝试调用意外的方法。
如果反射是一个潜在问题,如何防止它?
这很容易。应用程序需要各种权限才能成功调用反射 API 中的相关安全敏感方法。默认情况下,这些权限授予受信任的应用程序,而不是沙盒应用程序。您可以自由调整它们。
简单的解决方案:如果您正在运行受信任的代码,或者如果您担心可能存在安全性设计缺陷,请在安全沙箱中运行所有相关代码,以防止使用反射 API。 (缺点是一些第三方库是在假设它们可以使用反射的情况下设计的......并且会在沙箱中崩溃。)
(显然,对于实际的
Method.invoke(...)
调用没有权限检查。当应用程序代码从 Method
获取 Class
对象时,检查会提前发生。)
取决于您所说的“安全”是什么意思。对于使用受信任库的不受信任代码的上下文,似乎通常存在一些漏洞。否则,这只是糟糕的代码,似乎与任何其他糟糕的代码一样有可能引入漏洞。
硬编码方法名称对于性能而言更可取,因为通过反射调用方法会产生额外的开销。
安全方面,您可以禁用对反射对象的访问检查,这样您就可以调用其他类的私有和受保护方法,只要 SecurityManager 不阻止即可。