前言

还是打算先把内存马学一下,然后在学学java的代码审计,从tomcat架构开始学习。

java web三大件

java web的三大件是Servlet、Filter、Listener。
当tomcat接收到请求的时候,会依次经过Listener-》Filter-》Serlvet

Servlet(执行者)

Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。
Servlet的架构如下图所示:
image.png
简单的聊一下它的作用: 处理具体的业务逻辑(处理客户端的请求)、读写数据库、返回HTML或json数据(响应)。

Servlet的三种创建方式

第一种方法实现Servlet接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import javax.servlet.*;  
import javax.servlet.annotation.WebServlet;
import java.io.IOException;

@WebServlet(urlPatterns = "/demo1")
//第一种方法实现Servlet接口
public class Servletdemo1 implements Servlet {
//初始化,当Servlet第一次被创建的时候执行这个方法,这个方法在整个生命周期中只执行一次。
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("Servlet Create");
}

//Servlet获取初始化的配置信息
@Override
public ServletConfig getServletConfig() {
return null;
}
//对客户端响应的方法,每发送一次请求这个方法就会被执行一次

@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("service run");
}

@Override
public String getServletInfo() {
return "";
}
//当Servlet被销毁时执行改方法
@Override
public void destroy() {

}
public static void main(String[] args) {

}
}

看一下具体的实现。
访问demo01
image.png
image.png
看一下控制台的输出,没刷新一次run一次而Create只执行一次

第二种方法继承GenericServlet 类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import javax.servlet.GenericServlet;  
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import java.io.IOException;

@WebServlet(urlPatterns = "/demo2")
public class Servletdemo2 extends GenericServlet {
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("Servletdemo2");
}
}

image.png
这种方法比较少用

第三种方法继承HttpServlet

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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(urlPatterns = "/demo3")
public class Servletdemo3 extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Servletdemo3 GET");
}

protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{
System.out.println("Servletdemo3 POST");
}



}

image.png
这种方法也是常用的创建Servlet的方法
doxxxx方法就是跟着我们具体的业务逻辑走的

Filter(守门员)

Filter程序实现了特殊接口的Java类,与servlet类似,也是由servlet容器进行调用和执行的。
其主要功能是在HttpServletRequest到达Servlet之前,对其进行拦截和检查,也可以对HttpServletRequest的头和数据进行更改。也会在HttpServletResponse到达客户端之前,对其进行拦截和检查,当然也可以对他的头和数据进行更改。

Filter工作的基本原理

  • 1、Filter 程序是一个实现了特殊接口的 Java 类,与 Servlet 类似,也是由 Servlet 容器进行调用和执行的。
  • 2、当在 web.xml 注册了一个 Filter 来对某个 Servlet 程序进行拦截处理时,它可以决定是否将请求继续传递给 Servlet 程序,以及对请求和响应消息是否进行修改。
  • 3、当 Servlet 容器开始调用某个 Servlet 程序时,如果发现已经注册了一个 Filter 程序来对该 Servlet 进行拦截,那么容器不再直接调用 Servlet 的 service 方法,而是调用 Filter 的 doFilter 方法,再由 doFilter 方法决定是否去激活 service 方法。
  • 4、但在 Filter.doFilter 方法中不能直接调用 Servlet 的 service 方法,而是调用 FilterChain.doFilter 方法来激活目标 Servlet 的 service 方法,FilterChain 对象时通过 Filter.doFilter 方法的参数传递进来的。
  • 5、只要在 Filter.doFilter 方法中调用 FilterChain.doFilter 方法的语句前后增加某些程序代码,这样就可以在 Servlet 进行响应前后实现某些特殊功能。
  • 6、如果在 Filter.doFilter 方法中没有调用 FilterChain.doFilter 方法,则目标 Servlet 的 service 方法不会被执行,这样通过 Filter 就可以阻止某些非法的访问请求。
    总结: Filter访问需要在web.xml里定义路径,然后一般的Fileter中是由一条filterchain组成的,也就是是由多个filter组成的,而service在最后一个Filter中执行。当然如果没有FilterChain的话最终就不会调用到service方法。可以看下图。
    image.png
    如果在Filter之前在添加一个filter,这个filter中有我们写的恶意代码,那么,当我们发送请求的时候,就会提前调用恶意的filter,导致命令的执行。

Filter的创建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import javax.servlet.*;  
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter(urlPatterns = "/demo4")
public class Filterdemo implements Filter {
//初始化
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("init");
}

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//拦截
System.out.println("request go");
//放行,只有有它才能到Servlet
chain.doFilter(request, response);
System.out.println("response go");
}

@Override
public void destroy() { }
}

image.png

Listener(观察者)

Java Web 开发中的监听器(Listener)就是 Application、Session 和 Request 三大对象创建、销毁或者往其中添加、修改、删除属性时自动执行代码的功能组件。
这里介绍七个个listener,

  • ServletContextListener:用于监听 ServletContext 对象的创建和销毁事件,可以在 ServletContext 对象初始化时执行一些初始化代码,也可以在 ServletContext 对象销毁时执行一些清理代码。
  • ServletContextAttributeListener:用于监听 ServletContext 对象中属性的添加、删除和替换事件,可以在属性添加时执行一些逻辑处理,比如更新配置信息等;在属性删除时执行一些清理操作,比如释放资源等。
  • HttpSessionListener:用于监听 HttpSession 对象的创建和销毁事件,可以在 HttpSession 对象初始化时执行一些初始化代码,也可以在 HttpSession 对象销毁时执行一些清理代码。
  • HttpSessionAttributeListener:用于监听 HttpSession 对象中属性的添加、删除和替换事件,可以在属性添加时执行一些逻辑处理,比如更新用户信息等,在属性删除时执行一些清理操作,比如清空数据等。
  • HttpSessionActivationListener:用于监听 HttpSession 对象的钝化和活化事件,可以在 HttpSession 对象钝化时执行一些清理操作,比如将 Session 中的数据写入硬盘等,在 HttpSession 对象活化时执行一些初始化代码,比如重新读取数据等。
  • ServletRequestListener:用于监听 HttpServletRequest 对象的创建和销毁事件,可以在 HttpServletRequest 对象初始化时执行一些初始化代码,也可以在 HttpServletRequest 对象销毁时执行一些清理代码。
  • ServletRequestAttributeListener:用于监听 HttpServletRequest 对象中属性的添加、删除和替换事件,可以在属性添加时执行一些逻辑处理,比如更新请求参数等,在属性删除时执行一些清理操作,比如释放资源等。
    主要作用就是监听

Tomcat

简介

image.png
这张图就是tomcat的工作原理

tomcat的构成

tomcat包括五大容器和一大连接器,五大容器是Service、Engine、Host、Context、Wrapper、Connector
image.png
上图就是tomcat中的几个组件,接下来我们详细的分析一下。

server组件

server组件在tomcat最外层,所以可以将server实例看成一个tomcat,server实例启动后,会立马对端口进行监听(默认端口是8005)。要注意的是一个server实例只能监听一个端口,这个组件的作用就是对全局进行管理。

service组件

service组件关联着Connector和Engine组件,它负责接受和处理客户端的请求,以及将这些请求传递给Engine组件进行进一步的处理。简单来说,Service组件是Tomcat中对外提供服务的核心组件。(也可以看上上图的红字部分,web服务器是不处理请求的)。

Engine组件

上个组件也提到了,Engine组件就是负责处理客户端的请求,并对这些请求分发到对应的Host和web应用程序(context)进行处理。

Host组件

作用就是当Engine组件接收到来自Connector的请求之后,它会根据请求的主机头信息将请求分发到对应的Host组件。Host组件在进行进一步的处理请求,将其发送到正确的Context(web应用程序)进行处理

Context组件

  1. 管理Servlet实例:Context组件负责管理和维护Servlet实例的生命周期,包括Servlet的装载、初始化、执行和资源回收等。
  2. 提供Web应用环境:Context组件为Web应用提供了运行所需的环境和资源,包括ClassLoader、资源访问对象等。
  3. 处理HTTP请求:当Connector组件接收到HTTP请求后,会通过匹配请求URI的上下文路径来选择相应的Context来处理该请求。然后,Context会根据web.xml文件中定义的servlet映射来选择一个正确的Servlet来处理该请求。

wrapper组件

wrapper组件直接包装了Servlet实例,每个Wrapper组件都对应着一个特定的Servlet,并负责该Servlet的加载、初始化、执行以及资源回收等生命周期管理。

Connector组件

主要负责客户端连接和客户端请求的处理加工。

总结

从一个客户端发送一个简单的请求过来,Connector接收到这个请求会把这个请求翻译成各个组件都能看懂得一个状态,然后回把这请求发送给engine组件,Engine组件对其进行简单得处理之后发送到host组件,host组件在对其进一步处理后发送给Context组件(web应用程序)进行处理,给出响应,大概就是这么一个过程。

Tomcat的类加载机制

在tomcat的类加载机制中,为了保证WebApp的隔离,独立。所以打破了双亲委派机制。每个webapp用一个独有的ClassLoader实例来加载。它首先尝试自己加载,找不到在去找父类,目的是优先加载web应用自己定义的类。

参考

Java内存马系列-01-基础内容学习 | Drunkbaby’s Blog
Listener监听器什么是 Listener? Listener ,监听器,是 Servlet 规范中一种组件,用于监 - 掘金

Tomcat详细讲解(巨详细!!!)-CSDN博客