前段时间去杭州面一家公司,提到了servlet线程安全性问题,由于我是应届生,经验不足,以前也没有考虑过这些东西,所以当时直接凭直觉在那么大一片空白处写上了一个连自己都发笑的synchornized,后来才发现,这个关键字也是得分点。哈哈,虽然后来谈薪水的时候被pass了, 但是我压根也没打算进去,主要是那家公司实力不强,而且办公环境超级不好。好了,说了这么的多废话,我就直接今天的笔记把。
servlet安全性问题,其实这在网上有很多资料供参考的,但是我还是要自己写一些东西,毕竟是自己在秋知道路上碰到的。
servlet默认是多线程的,它的生命周期是由Web容器负责的。当用户第一次请求某个servlet的时候,web容器先到web.xml文件中查找该servlet配置,然后找到servlet-class并实例化该servlet。而当当浏览器第二次请求该servlet的时候,web容器将不会再次实例化。即多个线程共同使用该servlet的实例。这就造成了一定的不安全因素,虽然这种不安全发生的概率不是很大,但是防范于未然是web开发中必须考虑到的。
下面为了突出servlet多线程在用户多次请求过程中突出的不安全性问题,给出一个例子。供参考。
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class TestServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
PrintWriter out = null;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.setCharacterEncoding("GBK");
//获取参数
String param= req.getParameter("param");
//获取out实例
out = resp.getWriter();
try {
//让程序等待10秒钟后输出name
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
out.println("您传入的参数为:"+param+"<br>");
}
}
}
web.xml配置
<servlet>
<servlet-name>servlet</servlet-name>
<servlet-class>TestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>servlet</servlet-name>
<url-pattern>/getName.do</url-pattern>
</servlet-mapping>
在这个servlet,我为了能顺利暴露出servlet多线程所存在的漏洞,用了sleep(10000)。下面我通过两个不同类型的请求来说明问题:
一、不同用户请求同一servlet
·用户1请求:Http://10.81.66.173/testApp/getName.do?param=p1
---在10秒钟内,第二个用户再次请求该servlet----
·用户2请求:Http://10.81.66.173/testApp/getName.do?param=p2
---获取的结果是----
·用户1请求的响应为:
(空白)
·用户2请求的响应为:
您传入的参数为:p1
您传入的参数为:p2
二、同一用户在较小的时间间隔离多次请求统一servlet
·浏览器输入:http://10.81.66.173/testApp/getName.do?param=p
·然后拼命地按enter回车,然后等待输出结果:
响应结果为:
您传入的参数为:p
您传入的参数为:p
您传入的参数为:p
您传入的参数为:p
您传入的参数为:p
...略
可见,按了多少次,就显示多少个“您传入的参数为:p”
至于出现该问题的最终原因,网上其实也有解释,那就是java内存模型决定的。下面是我在网上截取的一段话(比我说得好,所以用别人的):
引用
Java的内存模型JMM(Java Memory Model)JMM主要是为了规定了线程和内存之间的一些关系。根据JMM的设计,系统存在一个主内存(Main Memory),Java中所有实例变量都储存在主存中,对于所有线程都是共享的。每条线程都有自己的工作内存(Working Memory),工作内存由缓存和堆栈两部分组成,缓存中保存的是主存中变量的拷贝,缓存可能并不总和主存同步,也就是缓存中变量的修改可能没有立刻写到主存中;堆栈中保存的是线程的局部变量,线程之间无法相互直接访问堆栈中的变量。
那么,既然servlet存在线程安全问题,那么如何设计安全的servlet呢?在这里普遍来就爱那个,有三种方式可以实现。但在实际使用中要酌情考虑。
·实现 SingleThreadModel 接口
public class TestServlet extends HttpServlet implements SingleThreadModel
不过考虑到系统开销问题,这种方法不赞成使用,具体原因我在这里不想多数,大家可以到网上搜一下相关资料。
·使用synchronized同步对共享数据的操作
synchronized(this){
out = resp.getWriter();
try {
//让程序等待10秒钟后输出param
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
out.println("您传入的参数为:"+param+"<br>");
}
这种方法可以使用,但是不建议,毕竟同步会是系统的性能、吞吐量下降很多,而且还会造成多个用户的请求发生阻塞,相比来说,下面的办法更好。
·避免使用实例变量,改为方法内的局部变量
简单的奖printwriter out = null,放在方法内定义即可。
分享到:
相关推荐
浅析互联网金融安全问题及防范策略.pdf
浅析Vista的安全性.rar WIN7注入进程演示
"浅析JavaScript的安全性和执行效率" JavaScript 作为一门广泛应用于 Web 客户端的编程语言,其安全性和执行效率是非常重要的考虑因素。在这个文件中,我们将浅析 JavaScript 的安全性和执行效率,并讨论一些相关的...
进程与线程是操作系统中最基本的概念,它们是程序执行的核心机制。在计算机科学中,进程通常被视为一个独立...深入学习MFC框架中的线程管理机制,可以提升代码的效率和可靠性,同时使程序更加符合并发执行的最佳实践。
智能卡攻击技术浅析与高安全性芯片设计.pdf
浅析高校网络安全管理问题及发展.pdf
浅析计算机网络安全存在问题及其防范措施.pdf
它由Sun Microsystems开发,以其跨平台性、安全性、面向对象特性以及多线程能力著称。在互联网高速发展的背景下,Java因其强大的功能和卓越的安全性,成为了构建网络应用的理想选择。尤其值得一提的是其多线程机制,...
浅析电力通信技术的安全性问题及应对策略.pdf
在多线程编程中,我们需要注意全局解释器锁(GIL),它是Python解释器为了保证线程安全而引入的一个机制,但同时也限制了多线程在CPU密集型任务中的性能,因为GIL使得Python在同一时刻只能有一个线程在执行。...
浅析电子商务安全问题.pdf
浅析两种安全运维管理模式 (2).docx浅析两种安全运维管理模式 (2).docx浅析两种安全运维管理模式 (2).docx浅析两种安全运维管理模式 (2).docx浅析两种安全运维管理模式 (2).docx浅析两种安全运维管理模式 (2).docx...
浅析计算机网络安全问题.pdf
浅析无线网络安全问题.pdf
浅析网络安全技术.pdf浅析网络安全技术.pdf浅析网络安全技术.pdf
浅析计算机安全问题及对策随着Internet 网络急剧扩大和上网用户迅速增加, 网络安全风险变得越来越严重和复杂。如何加强计算机信息安全的技术对策和 管理对策已经引起人们的广泛关注。
浅析水闸工程网络安全问题.pdf
浅析计算机网络安全存在问题及其防范措施 (2).pdf
浅析SQL SERVER的安全性.pdf
为解决这个问题,安卓借助多线程实现既可以进行耗时操作,又可以进行UI界面的刷新。JAVA多线程技术可以使得安卓应用程序更为多姿多彩,同时执行更多任务。JAVA多线程进程是指运行中的应用程序,每一个进程都有自己的...