java安全编码指南之:Mutability可变性

不要相信equals
我们知道在HashMap中怎么去查找一个key呢?先去找这个key的hash值,然后去判断key.equals方法是否相等,考虑下面这种情况:

private final Map<Window,Extra> extras = new HashMap<>();

    public void op(Window window) {
        Extra extra = extras.get(window);
    }

op方法接收一个Window对象,然后将其当成key从HashMap中取出对应的value。

如果,这个时候,我们有一个类A继承了Window,并且hash值和equals都和另外一个Window对象B相同,那么使用A这个key可以获取到B这个key存储的数据!

怎么解决这个问题呢?

Java中有一个特别的HashMap:IdentityHashMap,这个Map的key和value比较是用==而不是equals方法,所以可以有效的避免上面出现的问题。

private final Map<Window,Extra> extras = new IdentityHashMap<>();

    public void op(Window window) {
        Extra extra = extras.get(window);
    }

如果没有这样的Map可用,那么可以使用不可变对象作为key或者使用Window的私有变量,从而恶意攻击者无法获得这个变量。

public class Window {
/* pp */
class PrivateKey {
Window getWindow() {
return Window.this;
}
}
final PrivateKey privateKey = new PrivateKey();

        private final Map<Window.PrivateKey,Extra> extras =
             new WeakHashMap<>();
        ...
    }

    public class WindowOps {
        public void op(Window window) {
            // Window.equals may be overridden,
            // but safe as we don't use it.
            Extra extra = extras.get(window.privateKey);
            ...
        }
    }

不要直接暴露可修改的属性
如果一个可变类中的某个属性确实需要暴露被外部使用,那么一定要将这个属性定义为private,并且使用wrapper方法将其包装起来。

如果直接暴露出去,那么基本上就没有权限控制可言,任何程序只要能够拿到你这个对象,就可以对属性进行修改。考虑下下面的应用方式,我们在修改state的方法中加入了一个参数校验和权限控制。

public final class WrappedState {
// private immutable object
private String state;

        // wrapper method
        public String getState() {
            return state;
        }

        // wrapper method
        public void setState(final String newState) {
            this.state = requireValidation(newState);
        }

        private static String requireValidation(final String state) {
            if (...) {
                throw new IllegalArgumentException("...");
            }
            return state;
        }
    }

public static fields应该被置位final
同样的,如果你是一个类变量,当然不希望这个变量会被任何人修改,那么需要将其置位final。

public class Files {
public static final String separator = “/”;
public static final String pathSeparator = “:”;
}
public static final field 应该是不可变的
如果类变量是public static final的,那么这个变量一定要是不可变的。

有人会问了,都定义成了final了,是不是就已经不可变了?

其实不然,比如我们定义了一个final的List,虽然这个list不能变化,但是list里面的值是可以变化的。我们需要将可变变量修改为不可变变量,如下所示:

import static java.util.Arrays.asList;
import static java.util.Collections.unmodifiableList;

public static final List names = unmodifiableList(asList(
“Fred”, “Jim”, “Sheila”
));
如果使用JDK9中引入的of()或者ofEntries()方法,可以直接创建不可修改的集合:

public static final List
names =
List.of(“Fred”, “Jim”, “Sheila”);
龙华大道1号http://www.kinghill.cn/LongHuaDaDao1Hao/index.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值