不要通过名称来比较类
有时候,您可能需要比较两个对象的类,以确定它们是否相同;或者,您可能想看看某个对象是否是某个特定类的实例 。因为 JVM 可能包括多个具有相同名称的类(具有相同名称但却在不同包内的类),所以您不应该根据名称来比较类 。
影响
如果根据名称来比较类,您可能无意中将您不希望授予别人的权利授予了闯入者的类,因为闯入者可以定义与您的类同名的类 。
例如,请假设您想确定某个对象是否是类 com.bar.Foo 的实例 。清单 11 演示了完成这一任务的错误方法:
清单 11. 比较类的错误方法
if(obj.getClass().getName().equals("Foo"))// Wrong!
// objects class is named Foo
}else{
// object's class has some other name
}
建议
在那些非得根据名称来比较类的情况下,您必须格外小心,必须确保使用了当前类的 ClassLoader 的当前名称空间,如清单 12 中所示:
清单 12. 比较类的更好方法
if(obj.getClass() == this.getClassLoader().loadClass("com.bar.Foo")){
// object's class is equal to
//the class that this class calls "com.bar.Foo"
}else{
// object's class is not equal to the class that
// this class calls "com.bar.Foo"
}
然而 , 比较类的更好方法是直接比较类对象看它们是否相等 。例如,如果您想确定两个对象 a 和 b 是否属同一个类,那么您就应该使用清单 13 中的代码:
清单 13. 直接比较对象来看它们是否相等
if(a.getClass() == b.getClass()){
// objects have the same class
}else{
// objects have different classes
}
尽可能少用直接名称比较 。
不要使用内部类
Java 字节码没有内部类的概念,因为编译器将内部类转换成了普通类 , 而如果没有将内部类声明为 private,则同一个包内的任何代码恰好能访问该普通类 。
影响
因为有这一特性,所以包内的恶意代码可以访问这些内部类 。如果内部类能够访问括起外部类的字段,那么情况会变得更糟 。可能已经将这些字段声明为 private,这样内部类就被转换成了独立类,但当内部类访问外部类的字段时,编译器就将这些字段从专用(private)的变为在包(package)的作用域内有效的 。内部类暴露了已经够糟糕的了,但更糟糕的是编译器使您将某些字段成为 private 的举动成为徒劳 。
建议 如果能够不使用内部类就不要使用内部类 。
对付低严重性暴露的技巧
请遵循下列建议以避免低严重性静态安全性暴露:
避免返回可变对象
检查本机方法
避免返回可变对象
Java 方法返回对象引用的副本 。如果实际对象是可改变的,那么使用这样一个引用调用程序可能会改变它的内容,通常这是我们所不希望见到的 。
影响
请考虑这个示例:某个方法返回一个对敏感对象的内部数组的引用,假定该方法的调用程序不改变这些对象 。即使数组对象本身是不可改变的 , 也可以在数组对象以外操作数组的内容,这种操作将反映在返回该数组的对象中 。如果该方法返回可改变的对象,那么事情会变得更糟;外部实体可以改变在那个类中声明的 public 变量 , 这种改变将反映在实际对象中 。
清单 14 演示了脆弱性 。getExposedObj() 方法返回了 Exposed 对象的引用副本 , 该对象是可变的:
清单 14. 返回可变对象的引用副本
class Exposed{
private int id;
private String name;
public Exposed(){
}
public Exposed(int id, String name){
this.id = id;
this.name = name;
推荐阅读
- flutter书籍下载,flutter中文教程
- 企业如何做营销渠道策划的简单介绍
- 视频号怎么发产品链接,视频号怎么发产品链接给别人
- 一加安卓桌面布局图标,安卓手机显示桌面布局已锁定
- jquery对象自定义属性,jquery有自定义选择器吗
- java家庭记账源代码 javaweb记账管理系统
- 京东买的硬盘怎么保修,京东保修服务怎么用
- 美国dns服务器列表,美国ip和dns
- 超能陆战队安卓版本,超能陆战队安卓版本怎么下载