之前遇到过很多次Servlet的安全问题了,学习Y4师傅的文章。
package com.feng.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/thread")
public class ThreadServlet extends HttpServlet {
public boolean isAdmin;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
isAdmin = true;
if (req.getParameter("cmd").contains("calc")){
isAdmin = false;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (isAdmin&&req.getParameter("cmd").contains("calc")){
resp.getWriter().println("ok");
Runtime.getRuntime().exec("calc");
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
看似不可能,其实确实可以的(加了Thread.sleep(1000);
是为了产生延迟,更容易造成calc
)。
Servlet实际上是一个单件,当我们第一次请求某个Servlet时,Servlet容器将会根据web.xml配置文件或者是注解实例化这个Servlet类,之后如果又有新的客户端请求该Servlet时,则一般不会再实例化该Servlet类
所以对于Servlet来说,多人访问的时候,其实访问的是一个Servlet的实例,对于Servlet的成员变量的修改存在线程问题,导致了calc
的执行。
实现这个接口之后Servlet
的service
将只能被一个线程执行。
但是问题是会话属性和静态变量仍然可以被多线程的多请求同时访问,所以对于会话属性和静态变量的访问无法保证安全
Java多线程中的东西了,不提了。
最好还是避免对Servlet
中成员变量的访问,使用synchronized
在高并发的时候也会影响性能。