程序员面试系列之Java单例模式的攻击与防御
我写的程序员面试系列
Java面试系列-webapp文件夹和WebContent文件夹的区别?
程序员面试系列:Spring MVC能响应HTTP请求的原因?
Java程序员面试系列-什么是Java Marker Interface(标记接口)
JavaScript面试系列:JavaScript设计模式之桥接模式和懒加载
使用JavaScript ES6的新特性计算Fibonacci(非波拉契数列)
单例模式在很多Java程序员的眼中,应该是设计模式里最简单的一种了。那么单例模式可能会被攻击,您听说过么?
说到“单例模式被攻击”这个话题,大家最容易想到的可能就是通过序列化/反序列化来攻击单例模式,因为一个对象实例序列化再反序列化后,得到的新的对象虽然各字段内容和原字段一致,然而对象地址和原始对象地址相比已经发生了变化,因此它们是两个不同的对象。
上面的结论完全正确,然而除了序列化/反序列化,单例模式还可能遭受另一种方式的攻击,即反射攻击(Reflection attack)。
看一个具体例子:
public class JerrySingleton {
private String name;
private JerrySingleton(){
name = "Jerry";
}
private static class SingletonHolder{
private static final JerrySingleton INSTANCE = new JerrySingleton();
}
public static JerrySingleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
上面是一个饿汉式单例。
然而我只需要将这个单例类JerrySingleton的构造函数通过反射设置成可以访问Accessible,然后就能通过反射调用该构造函数,进而生成新的对象实例。这样就破坏了单例模式。
Class<?> classType = JerrySingleton.class;
Constructor<?> c = classType.getDeclaredConstructor(null);
c.setAccessible(true);
JerrySingleton e1 = (JerrySingleton)c.newInstance();
JerrySingleton e2 = JerrySingleton.getInstance();
System.out.println(e1 == e2);
第6行代码会打印false。
针对这种攻击,一种可行的防御措施是在单例类的构造函数内定义一个布尔变量,初始化为false。当构造函数执行后,该变量被置为true。如果接下来构造函数再次被执行,则人为抛出异常,避免构造函数重复执行。
public class JerrySingletonImproved {
private static boolean flag = false;
private JerrySingletonImproved(){
synchronized(JerrySingletonImproved.class) {
if(flag == false) {
flag = !flag;
}
else {
throw new RuntimeException("Singleton violated");
}
}
}
}
这种防御措施无法从根本上杜绝Singleton被攻击,因为攻击者仍旧可以通过反射来修改布尔变量flag的值,从而绕过这个检查。
最理想的不会受到攻击的单例模式实现是借助Java里枚举类Enumeration的特性:
这种实现类型的单例模式的消费代码:
System.out.println("Name:" + JerrySingletonAnotherApproach.INSTANCE.getName());
如果攻击者通过前面介绍的反射代码对这种实现方式的单例进行攻击,JDK会抛出NoSuchMethodException异常:
Exception in thread "main" java.lang.NoSuchMethodException: singleton.JerrySingletonAnotherApproach.<init>()
at java.lang.Class.getConstructor0(Class.java:3082)
at java.lang.Class.getDeclaredConstructor(Class.java:2178)
at singleton.SingletonAttack.test3(SingletonAttack.java:31)
at singleton.SingletonAttack.main(SingletonAttack.java:43)
究其原因,是因为现在我们是通过Java枚举方式实现的单例,枚举类没有传统意义上的构造函数,因此对这种反射攻击免疫。
要获取更多Jerry的原创技术文章,请关注公众号"汪子熙"或者扫描下面二维码:
程序员面试系列之Java单例模式的攻击与防御的更多相关文章
- 寻找下一个结点 牛客网 程序员面试金典 C++ java Python
寻找下一个结点 牛客网 程序员面试金典 C++ java Python 题目描述 请设计一个算法,寻找二叉树中指定结点的下一个结点(即中序遍历的后继). 给定树的根结点指针TreeNode* root ...
- 碰撞的蚂蚁 牛客网 程序员面试金典 C++ Java Python
碰撞的蚂蚁 牛客网 程序员面试金典 C++ Java Python 题目描述 在n个顶点的多边形上有n只蚂蚁,这些蚂蚁同时开始沿着多边形的边爬行,请求出这些蚂蚁相撞的概率.(这里的相撞是指存在任意两只 ...
- 检查是否是BST 牛客网 程序员面试金典 C++ java Python
检查是否是BST 牛客网 程序员面试金典 C++ java Python 题目描述 请实现一个函数,检查一棵二叉树是否为二叉查找树. 给定树的根结点指针TreeNode* root,请返回一个boo ...
- Java程序员面试宝典1 ---Java基础部分(该博文为原创,转载请注明出处)
(该博文为原创,转载请注明出处 http://www.cnblogs.com/luyijoy/ by白手伊凡) 1. 基本概念 1) Java为解释性语言,运行过程:程序源 ...
- java程序员面试宝典之——Java 基础部分(1~10)
基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语法,集合的语法,io 的语法,虚拟机方面的语法. 1.一个".java"源文件中是否可以包 ...
- JAVA程序员面试宝典
程序员面试之葵花宝典 面向对象的特征有哪些方面 1. 抽象:抽象就是忽略一个主题中与当前目标2. 无关的那些方面,3. 以便更充分地注意与当前目标4. 有关的方面.抽象并不5. 打算了解全部问题 ...
- Java程序员面试之葵花宝典
程序员面试之葵花宝典 1.面向对象的特征有哪些方面 抽象:抽象就是忽略一个主题中与当前目标 无关的那些方面, 以便更充分地注意与当前目标有关的方面.抽象并不打算了解全部问题,而 只是选择其中的一部 ...
- 两年Java程序员面试经验分享,从简历制作到面试总结!
前言 工作两年左右,实习一年左右,正式工作一年左右,其实挺尴尬的,高不成低不就.因此在面试许多公司,找到了目前最适合自己的公司之后.于是做一个关于面试的总结.希望能够给那些依旧在找工作的同学提供帮助. ...
- 《JAVA 程序员面试宝典(第四版)》读书笔记之前言
工作五年了一直在小的软件公司混,总感觉自己的专业知识没有太大的提升.当然了中间也换了一两家公司,面试的公司就很多家,总感觉正规的软件公司(无论大小)对于基础知识的考核都非常重视,而不管你说你之前服务过 ...
随机推荐
- http的安全方法和幂等性
最近在研究http,看到http的安全方法和幂等性部分,不太明白,尤其是"post方法是非幂等的"不理解,进过查资料,找到以下两篇有价值的文章,特转过来! 理解HTTP幂等性 转自 ...
- 网易短信接口集成 nodejs 版
/* name:网易短信服务集成nodejs版: author:zeq time:20180607 test: // checkValidCode('157****6954','284561').th ...
- vue之安装配置
直接上图
- bzoj1025 [SCOI2009]游戏——因数DP
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1025 这篇博客写得真好呢:https://www.cnblogs.com/phile/p/4 ...
- 微信小程序服务类目大坑:特殊行业服务类目所需资质材料
作为一个技术开发人员,遇到特殊行业服务类目所需资质材料,只能叫苦连天了,妈的,这个不是技术可以解决的问题,如果技术可以解决的问题都不是问题. 百牛信息技术bainiu.ltd整理发布于博客园 特殊行业 ...
- Makefile的引入及规则
ARM裸机1期加强版视频课程配套WiKi第9课第5节_Makefile的引入及规则. 文字不能完全替代视频,所以如果你看了这些文章不太懂,建议购买视频进一步学习. 视频购买地址:100ask.taob ...
- Intelidea右键新建选项没有Java class选项
Intelidea创建好项目之后,右键新建Java class的时候发现没有改选项,只有以下几个选项 把sec目录设为源码目录,首先打开Project Structure
- 输出文章段落首行空格缩进在IE和chrome显示不一致的问题
一般的编辑文章时,首行都缩进两格,而执行的操作则是一个tab键或者四个空格键,在html代码中体现的往往都是4个 然而我在输出时却发现了同样的html代码,在IE上显示的是缩进了一个字符,在chrom ...
- 用"\v"=="v"判断是IE浏览器和非IE
其实就是利用各浏览器对转义字符"\v"的理解在ie浏览器中,"\v"没有转义,得到的结果为"v"而在其他浏览器中"\v" ...
- easyui 动态添加标签页,总结
步骤 1:创建 Tabs <div style="margin-bottom:10px"> <a href="#" class="e ...