你写的单例一定安全吗?

简介: 前言:在并发环境中,我们可以用各种锁来保持单例的线程安全,当然这是从业务角度来考虑的;但是,从一个攻击者的角度来看,你的单例也许只保证了线程安全,当攻击者通过反射new出单例的实例时候(反射的可以改变你的私有构造函数)...

前言:

在并发环境中,我们可以用各种锁来保持单例的线程安全,当然这是从业务角度来考虑的;但是,从一个攻击者的角度来看,你的单例也许只保证了线程安全,当攻击者通过反射new出单例的实例时候(反射的可以改变你的私有构造函数),那攻击者就可以控制你的单例干很多坏事

举例:

单例代码:

/**
 * 懒汉式单例(简单点),不考虑多线程并发的模型
 */
public class MyInstance {
    private static MyInstance instance;

    private MyInstance(){

    }

    public static MyInstance getInstance(){
        if (instance == null){
            instance = new MyInstance();
        }
        return instance;
    }
}

攻击代码:

import java.lang.reflect.Constructor;

public class Main {

    public static void main(String[] args){

        System.out.println(MyInstance.getInstance());
        try
        {
            Class<MyInstance> classType = MyInstance.class;

            Constructor<MyInstance> constructor = classType.getDeclaredConstructor(null);
            constructor.setAccessible(true);//关键代码,将这个构造函数的权限设置为可进入的
            MyInstance myInstanceHack = constructor.newInstance();
            System.out.println(myInstanceHack);
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }

    }
}

攻击结果:

从结果来看,两个对象的地址是不一样的,那么攻击者就可以利用这个方式,干很多越权的事情。

如何防范呢?

其实,问题所在就是那个构造函数被攻击了,因此,我们只要保护好构造函数,就能基本防御这种攻击

方式一:

利用一个静态变量,保证构造函数只被掉一次

/**
 * 懒汉式单例(简单点),不考虑多线程并发的模型
 */
public class MyInstance {
    private static MyInstance instance;
    private static boolean isUsed;

    private MyInstance(){

        if (isUsed){
            //抛出异常
            throw new RuntimeException();
        }else {
            isUsed = true;
        }



    }

    public static MyInstance getInstance(){
        if (instance == null){
            instance = new MyInstance();
        }
        return instance;
    }
}

方式二:

利用枚举的特性:每个枚举量只会实例化一次,也就是枚举类的单例:

public enum MyInstanceEnum {
    INSTANCE;
    private MyInstance2 myInstance;

    MyInstanceEnum(){
        myInstance = new MyInstance2();
    }

    public MyInstance2 getMyInstance() {
        return myInstance;
    }
}

攻击时报错

总结:

当然,反射被设计出来,肯定不是用来攻击的,它的作用可以很多依赖注入的框架中,比如Spring各种框架,JSON解析等很多方面。(不晓得从哪里看到一句话:人的血液循环是复杂但是有规律的,打针(反射)在中间介入这个循环如果没摸清楚循环规律而乱戳表面看似达到效果,实际会引发其他问题)

目录
相关文章
|
5天前
|
JavaScript API iOS开发
DeepSeek Harness下载、安装、配置一篇搞定(2026整理,送常用插件)
DeepSeek Harness(DSH)是DeepSeek于2026年开源的MIT协议AI Agent框架,支持插件化组装模型、工具、沙箱与UI,兼容主流大模型。本文提供免Node.js的桌面端安装包(Win/macOS),含详细图文教程及热门插件推荐。
2357 15
|
5天前
|
iOS开发 Docker MacOS
【2026实测】Docker Desktop下载、安装、汉化、配置教程(附官网安装包)
Docker Desktop 是 Docker 官方推出的桌面容器管理工具,集成引擎、CLI、图形界面与 Kubernetes,支持 Win/macOS/Linux。2026 最新版 4.88.1 强化 ARM 原生运行、镜像加速及资源可视化,附中文汉化与国内镜像配置指南。
1043 3
|
云安全 安全 网络安全
|
4天前
|
Linux 开发工具 iOS开发
Codex保姆级教程(下载+安装+登录+使用,含所有版本,2026最新)
Codex是OpenAI推出的开源AI编程智能体,本地运行,可理解整个代码库,支持自然语言指令改代码、执行命令、跑测试、修Bug,兼容Win/macOS/Linux。(239字)
|
6天前
|
安全 算法 定位技术
《高性价比人生指南》完整原版:普通人用最少的资源,过好这一生的底层逻辑~How To Live Better
📖《高性价比人生指南》是一份基于实证、拒绝焦虑的生存手册,倡导以“人生时薪”为视角,重新计算时间、金钱与精力的成本与收益。它不承诺逆袭,只教人算清账:省下的钱若耗掉时间便亏;买体验比买物品更值;睡眠是最高杠杆的健康投资;关系贵在情绪价值而非表面热络;学习重在改变行为而非自我安慰。核心理念:用低成本、高回报的微小行动,换取长期的选择权——不是成为谁,而是掌控自己人生的主动权。
|
18天前
|
人工智能 API 开发工具
DeepSeek Harness 神插件:白嫖 13 家大厂模型
`dsh-our-free-model` 是 DeepSeek Harness 神级插件:零配置、零API Key、零账号,聚合13家大厂免费模型(含DeepSeek V4.1 Flash、Kimi K3等),支持本地网关、用量看板与自动降级,真正实现“白嫖即用”。
3198 49
|
12天前
|
JavaScript 安全 前端开发
Nodejs Brotli decoder 代码执行漏洞 (CVE-2026-111497)10629
Node.js发布安全更新修复Brotli解码器高危RCE漏洞(CVE-2026-111497),建议受影响版本用户立即升级。
2115 2
|
10天前
|
人工智能 JSON Linux
【保姆级】ComfyUI部署教程(下载+安装+配置+工作流,2026最新)
ComfyUI 是一款开源节点式AI生成工具,支持图像、视频、音频及3D内容创作。通过拖拽连线组合模型加载、提示词、采样等节点,构建可复用、易修改的工作流,兼容SD1.5、SDXL、Flux、Qwen Image等主流模型。

热门文章

最新文章