简单纪要:如何防止单例模式被java的反射攻击

上篇我们介绍了单例模式的几种创建方式(传送门:https://www.cnblogs.com/Rnan/p/16685539.html),

但是这都是基于,不会通过反射调用对象的私有化构造器,我们举个例子,看下java反射攻击单例模式:

public class Singleton {

    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class<?> classType = SingletonLazy.class;
        Constructor<?> declaredConstructor = classType.getDeclaredConstructor(null);
        // 可以访问私有化构造器
        declaredConstructor.setAccessible(true);

        SingletonLazy s1 = (SingletonLazy) declaredConstructor.newInstance();
        SingletonLazy s2 = SingletonLazy.getInstance();
        System.out.println(s1);
        System.out.println(s2);
        System.out.println(s1 == s2);
    }
}

class SingletonLazy {

    private static volatile SingletonLazy singletonLazy = null;

    private SingletonLazy() {
    }

    public static SingletonLazy getInstance() {
        if (singletonLazy == null) {
            synchronized (SingletonLazy.class) {
                if (singletonLazy == null) {
                    singletonLazy = new SingletonLazy();
                }
            }
        }
        return singletonLazy;
    }
}

 

我们可以看到,通过反射获取构造函数,然后调用setAccessible(true)就可以调用私有的构造函数,通过反射创建对象,生成的s1和s2就是两个不同的对象。

如果要抵御这种攻击,可以修改构造器,让它在被要求创建第二个实例的时候抛出异常。

 

 1、可以看到这样就可以防止反射进行创建bean,防止攻击。

2、我们上篇文章中讲解的,枚举也是可以防止反射攻击的,还可以防止序列化破坏单例,由此可见,单元素的枚举类型已经成为实现Singleton模式的最佳方法;

以上就是我们本次的内容,小伙伴有问题,可以评论留言哦~我们下次见,see you again~

posted @ 2022-09-12 10:29  爱吃螃蟹的牧羊人  阅读(531)  评论(0编辑  收藏  举报