有效的java说:
//潜在的安全漏洞!
static public final Thing [] VALUES = {...};
谁能告诉我什么是安全漏洞?
声明static final public
字段通常是类常量的标志.对于原始类型(整数,双精度等)和不可变类,如字符串和java.awt.Color
.对于数组,问题在于即使数组引用是常量,数组的元素仍然可以更改,并且因为它是一个字段,所以更改是无人看管的,不受控制的,并且通常是不受欢迎的.
为了解决这个问题,可以将数组字段的可见性限制为私有或包私有,因此在查找可疑修改时需要考虑较小的代码体.或者,通常更好的方法是将阵列一起取消并使用"列表"或其他适当的集合类型.通过使用集合,您可以控制是否允许更新,因为所有更新都通过方法进行.您可以使用包装集合来阻止更新Collections.unmodifiableList()
.但请注意,即使集合是不可变的,您还必须确保存储在其中的类型也是不可变的,否则将重新出现对假定常量的未经请求的更改的风险.
要理解为什么这是一个潜在的安全漏洞,而不仅仅是糟糕的封装,请考虑以下示例:
public class SafeSites { // a trusted class with permission to create network connections public static final String[] ALLOWED_URLS = new String[] { "http://amazon.com", "http://cnn.com"}; // this method allows untrusted code to connect to allowed sites (only) public static void doRequest(String url) { for (String allowed : ALLOWED_URLS) { if (url.equals(allowed)) { // send a request ... } } } } public class Untrusted { // An untrusted class that is executed in a security sandbox. public void naughtyBoy() { SafeSites.ALLOWED_URLS[0] = "http://myporn.com"; SafeSites.doRequest("http://myporn.com"); } }
如您所见,错误使用最终数组意味着不受信任的代码可以破坏受信任的代码/沙箱试图强加的限制.在这种情况下,这显然是一个安全问题.
如果您的代码不是安全关键应用程序的一部分,那么您可以忽略此问题.但IMO这是一个坏主意.在将来的某个时刻,您(或其他人)可能会在安全性受到关注的环境中重用您的代码.无论如何,这就是作者将公共最终数组称为安全问题的原因.
安伯在评论中说:
如果你能以任何方式读取源代码和/或字节码,就不会有私有的安全漏洞......
这不是真的.
"坏人"可以使用源代码/字节码来确定private
存在并引用数组这一事实不足以破坏安全性.坏人还必须将代码注入具有使用反射所需权限的JVM.在(正确实施的)安全沙箱中运行的不受信任的代码不能使用此权限.
请注意,非零长度数组始终是可变的,因此类具有公共静态最终数组字段或返回此类字段的访问器是错误的. 如果类具有此类字段或访问者,则客户端将能够修改该数组的内容.
- 有效的Java,第二版.(第70页)