getResource 的不安全使用¶
ID: java/unsafe-get-resource
Kind: problem
Security severity:
Severity: warning
Precision: medium
Tags:
- reliability
- maintainability
Query suites:
- java-security-and-quality.qls
使用 Class.getResource
方法是将一些非代码资源包含在应用程序中的常见方法。
当使用 x.getClass().getResource()
(对于某些变量 x
)调用此方法时存在问题。这并不是检索资源的安全方法。方法 getClass
返回 x
的运行时类(即,它的实际,“最派生”类,而不是其声明类型),这会导致两个潜在问题。
如果接收对象的运行时类型是声明类型的子类,并且位于不同的包中,则资源路径的解释可能会有所不同。根据其约定,
Class.getResource
使用当前包名限定非绝对路径,从而可能返回不同的资源或无法找到请求的资源。Class.getResource
将查找资源的任务委托给加载该类的类加载器。在运行时,不能保证某个类型的子类都由同一个类加载器加载,这会导致难以诊断的资源查找失败。
建议¶
与其使用依赖于动态分派和运行时类型的getClass
方法,不如使用class
字面量。例如,不要在类型为Foo
的对象上调用getClass().getResource()
,而是调用Foo.class.getResource()
。类字面量始终引用它们所使用的声明类型,从而消除了对运行时类型的依赖。
示例¶
在以下示例中,对getPostalCodes
的调用返回不同的结果,具体取决于调用所针对的类:类Address
在包framework
中,而类UKAddress
在包client
中。
package framework;
class Address {
public URL getPostalCodes() {
// AVOID: The call is made on the run-time type of 'this'.
return this.getClass().getResource("postal-codes.csv");
}
}
package client;
class UKAddress extends Address {
public void convert() {
// Looks up "framework/postal-codes.csv"
new Address().getPostalCodes();
// Looks up "client/postal-codes.csv"
new UKAddress().getPostalCodes();
}
}
在以下更正后的示例中,getPostalCodes
的实现进行了更改,以便它始终对同一个类调用getResource
。
package framework;
class Address {
public URL getPostalCodes() {
// GOOD: The call is always made on an object of the same type.
return Address.class.getResource("postal-codes.csv");
}
}
package client;
class UKAddress extends Address {
public void convert() {
// Looks up "framework/postal-codes.csv"
new Address().getPostalCodes();
// Looks up "framework/postal-codes.csv"
new UKAddress().getPostalCodes();
}
}
参考资料¶
Java API 规范:Class.getResource().