Java Sonar报返回可变对象引用漏洞 各类数组及对象处理方案
Sonar报这个错误的核心原因是你直接把类内部私有可变属性的引用对外返回,外部调用方拿到引用后可以直接修改类内部的私有数据,破坏封装性,存在安全风险。
1. 所有「基本类型+[]」形式的数组都是可变的吗?
是的,Java中所有数组(包括基本类型数组、引用类型数组)本身都是可变对象:
- 数组的长度在初始化后不可修改,但数组每个下标位置的元素值都可以被重新赋值
- 外部拿到你返回的int[]引用后,执行
returnedArray[0] = 100就会直接修改你类内部integerArray的对应值,这就是该漏洞的风险点。
2. 如何在仍返回int数组的前提下解决该问题?
不要直接返回原数组的引用,改为返回原数组的拷贝即可,修改后的getter代码如下:
// 记得先导入java.util.Arrays public int[] getIntegerArray() { return Arrays.copyOf(integerArray, integerArray.length); }
该方案返回的是和原数组内容完全一致的新数组,外部对返回值的任何修改都不会影响类内部的原始数据,同时也满足了返回int数组的要求。
3. 如果将int[]替换为String[]、StringBuilder或任意对象数组,对应的解决方案是什么?
根据元素的可变性分两类处理:
- 元素是不可变类型的数组:比如
String[]、Integer[]等不可变类的数组,处理逻辑和基本类型数组完全一致,返回数组的拷贝即可,因为不可变类型的元素本身无法被修改,只要不对外暴露原数组引用就没有风险。 - 元素是可变类型的数组:比如
StringBuilder[]、自定义可变类的数组,仅拷贝数组不够,因为新数组的元素还是和原数组指向同一个可变对象,外部修改元素属性仍然会影响内部数据,需要做深拷贝,示例代码如下:
private StringBuilder[] sbArray = {new StringBuilder("foo"), new StringBuilder("bar")}; public StringBuilder[] getSbArray() { StringBuilder[] copy = new StringBuilder[sbArray.length]; for (int i = 0; i < sbArray.length; i++) { // 每个可变元素单独生成拷贝 copy[i] = new StringBuilder(sbArray[i]); } return copy; }
- 单个可变对象(如单个StringBuilder):和可变元素的处理逻辑一致,返回该对象的拷贝即可,自定义可变类可以通过拷贝构造函数或者重写
clone()方法实现拷贝逻辑。
内容的提问来源于stack exchange,提问作者user31468
相关产品推荐
相关产品推荐

