java 为什么公共静态最终数组是一个安全漏洞?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2842169/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why are public static final array a security hole?
提问by unj2
Effective java says:
有效的Java 说:
// Potential security hole!
static public final Thing[] VALUES = { ... };
// 潜在的安全漏洞!
static public final Thing[] VALUES = { ... };
Can somebody tell me what is the security hole?
有人能告诉我什么是安全漏洞吗?
回答by mdma
Declaring static final publicfields is usually the hallmark of a class constant. It's perfectly fine for primitive types (ints, doubles etc..), and immutable classes, like strings and java.awt.Color. With arrays, the problem is that even though the array reference is constant, the elements of the array can still be changed, and as it's a field, changes are unguarded, uncontrolled, and usually unwelcome.
声明static final public字段通常是类常量的标志。对于原始类型(整数、双精度数等)和不可变类(如字符串和java.awt.Color. 对于数组,问题是即使数组引用是常量,数组的元素仍然可以更改,而且由于它是一个字段,更改是不受保护的、不受控制的,并且通常是不受欢迎的。
To combat this, the visibility of the array field can be restricted to private or package private, so you have a smaller body of code to consider when looking for suspicious modification. Alternatively, and often better, is to do away with the array together and use a 'List', or other appropriate collection type. By using a collection, you control if updates are allowed, since all updates go through methods. You can prevent updates by wrapping your collection using Collections.unmodifiableList(). But beware that even though the collection is immutable, you must also be sure that the types stored in it are also immutable, or the risk of unsolicited changes on a supposed constant will reappear.
为了解决这个问题,可以将数组字段的可见性限制为私有或包私有,因此在查找可疑修改时需要考虑的代码体较少。或者,通常更好的是,一起取消数组并使用“列表”或其他适当的集合类型。通过使用集合,您可以控制是否允许更新,因为所有更新都通过方法。您可以通过使用 包装您的集合来防止更新Collections.unmodifiableList()。但请注意,即使集合是不可变的,您还必须确保其中存储的类型也是不可变的,否则对假定的常量进行未经请求的更改的风险将再次出现。
回答by Stephen C
To understand why this is a potential security hole and not just poor encapsulation, consider the following example:
要理解为什么这是一个潜在的安全漏洞,而不仅仅是糟糕的封装,请考虑以下示例:
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");
}
}
As you can see, the mistaken use of a final array means that untrusted code can subvert the restriction that the trusted code / sandbox is trying to impose. In this case, this is clearly a security issue.
如您所见,错误使用 final 数组意味着不受信任的代码可以破坏受信任代码/沙箱试图强加的限制。在这种情况下,这显然是一个安全问题。
If your code is not part of a security critical application, then you could ignore this issue. But IMO this is a bad idea. At some point in the future you (or someone else) might reuse your code in a context where security is a concern. At any rate, thisis why the author calls public final arrays a security issue.
如果您的代码不是安全关键应用程序的一部分,那么您可以忽略此问题。但 IMO 这是一个坏主意。在未来的某个时候,您(或其他人)可能会在需要考虑安全性的上下文中重用您的代码。无论如何,这就是作者将公共最终数组称为安全问题的原因。
Amber said this in a comment:
琥珀在评论中说:
No more a security hole than private would be, if you can read the source code and/or bytecode either way...
如果您可以以任何一种方式阅读源代码和/或字节码,那么就没有比私有更安全的漏洞了……
This is not true.
这不是真的。
The fact that a "bad guy" can use source code / bytecodes to determine that a privateexists and refers to an array is not sufficientto break security. The bad guy alsohas to inject code into a JVM that has the required permissions to use reflection. This permission is not available to untrustedcode running in a (properly implemented) security sandbox.
“坏人”可以使用源代码/字节码来确定 aprivate存在并引用数组这一事实不足以破坏安全性。坏人还必须将代码注入具有使用反射所需权限的 JVM。此权限不适用于在(正确实施的)安全沙箱中运行的不受信任的代码。
回答by Bill the Lizard
Note that a nonzero-length array is always mutable, so it is wrong for a class to have a public static final array field, or an accessor that returns such a field.If a class has such a field or accessor, clients will be able to modify the contents of the array.
-- Effective Java, 2nd Ed. (page 70)
请注意,非零长度数组始终是可变的,因此类具有公共静态最终数组字段或返回此类字段的访问器是错误的。如果一个类有这样的字段或访问器,客户端将能够修改数组的内容。
-有效的 Java,第 2 版。(第 70 页)
回答by L??o???n???g???p??o???k???e???
An outside class can modify the contents of the array, which is probably not what you want users of your class to do (you want them to do it through a method). It's sounds like the author meant it violates encapsulation, and not security.
外部类可以修改数组的内容,这可能不是您希望您的类的用户执行的操作(您希望他们通过方法来执行此操作)。听起来作者的意思是它违反了封装,而不是安全性。
I guess someone declaring this line could think other classes can't modify the array contents since it's marked as final, but this is not true, final only stops you from re-assigning the attribute.
我想声明这一行的人可能认为其他类不能修改数组内容,因为它被标记为 final,但这不是真的,final 只会阻止你重新分配属性。
回答by Michu93
I would also add what Joshua Bloch proposed in Effective Java 3rd edition. Of course we can easily change the value of the array if it is declared as:
我还将添加 Joshua Bloch 在 Effective Java 3rd edition 中提出的建议。当然,如果数组声明为:
public static final String[] VALUES = { "a", "b" };
a.VALUES[0] = "changed value on index 0";
System.out.println(String.format("Result: %s", a.VALUES[0]));
and we get Result: changed value on index 0
我们得到 Result: changed value on index 0
Joshua Bloch proposed to return copy of array:
Joshua Bloch 提议返回数组的副本:
private static final String[] VALUES = { "a", "b" };
public static final String[] values()
{
return VALUES.clone();
}
so now when we try:
所以现在当我们尝试:
a.values()[0] = "changed value on index 0";
System.out.println(String.format("Result: %s", a.values()[0]));
we get Result: aand that's what we wanted to achieve - the VALUESare immutable.
我们得到了Result: a,这就是我们想要实现的 -VALUES是不可变的。
There is also nothing bad in declaring public static finala primitives values, Strings or other immutable objects like public static final int ERROR_CODE = 59;
声明public static final原始值、字符串或其他不可变对象(如public static final int ERROR_CODE = 59;
回答by Lalith
In this declaration, a client can modify Thing[0], Thing[1], etc (i.e. elements in the array).
在此声明中,客户端可以修改 Thing[0]、Thing[1] 等(即数组中的元素)。
回答by AaronM
Think it just means the whole public vs private thing. It's supposed to be good practice to have local variables declared private, then using get and set methods, rather than accessing them directly. Makes them a little harder to mess with outside of your program. About it as far as I'm aware.
认为这只是意味着整个公共与私人的事情。最好将局部变量声明为私有,然后使用 get 和 set 方法,而不是直接访问它们。使它们在您的程序之外更难弄乱。据我所知。
回答by Amareswar
Because, final keyword assures only reference value (assume it as memory location for example) but not the content in it.
因为,final 关键字只保证引用值(例如假设它是内存位置)而不是其中的内容。

