流程图:
参考:
JAVAEE的核心-Servlet_javaee的核心 csdn-CSDN博客
#解释
Servlet是运行在Web服务器或应用服务器上的程序,它是作为来自Web浏览器或其他HTTP客户端的请求和HTTP服务器上的数据库或应用程序之间的中间层。使用Servlet可以收集来自网页表单的用户输入,呈现来自数据库或者其他源的记录,还可以动态创建网页。本章内容详细讲解了web开发的相关内容以及servlet相关内容的配置使用,是JAVAEE开发的重中之重。
#JavaEE-IDEA开发
安装IDEA,激活后安装开发插件
安装JDK,Tomcat,新建项目并配置
点击新建项目,输入项目名称,自定义项目位置,将tomcat 文件目录丢进去,还有JDK,模板要选web
选择一个servlet依赖库就行
运行成功
#创建和使用Servlet
1、创建一个类继承HttpServlet
创建一个servlet 软件包,将Java代码写进去
快捷键:alt+insert
写入内置方法(init service(doget dopost等) destroy )
先继承一下HttpServlet类,然后点击alt+insert 键,显示出几个内置方法,这时候点击重写方法
重写方法,这里需要init(初始化) doget(接收get请求) dopost(接收post请求) destroy(销毁)
2、web.xml配置Servlet路由
先声明;后写路由
访问/servlet时触发名为servlet的文件,所以一开始写的是命名和文件路径;后面写定义的名字和路由
用xml文件配置访问
3、WebServlet配置Servlet路由
这个只有一句代码就可以搞定,name可以写也可以不写 value是路由
@WebServlet(name = "servletTest",value = "/test")
用webservlet 配置地址访问,如果两个都配置了,是以webservlet 设置的路由访问才能触发
完整Java代码:
package Servlet;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(name = "ServletTest",value = "/test")
public class ServletTest extends HttpServlet {
@Override
public void init() throws ServletException {
System.out.println("init");
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("doGet");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("doPost");
}
}
#Servlet生命周期
访问地址时会先进行初始化,调用init() 方法;然后根据请求类型来执行get方法和post方法
只有在第一次访问页面时会触发init() 方法 ,再次访问页面时只会执行doget方法
当去掉doget方法时,直接访问页面 ,会报方法不允许
用postman发送post请求时,会执行dopost()方法
点击停止运行时,在和服务器断开的时候会调用销毁方法 destroy()
#处理接受和回显
●HttpServletRequest是ServletRequest的子接口
getParameter(name) — String 通过name获得值
getParameterValues — String[ ] 通过name获得多值
●HttpServletResponse是ServletResponse的子接口
setCharacterEncoding() 设置编码格式
setContentType() 设置解析语言
getWriter() 获得一个PrintWriter字符输出流输出数据
PrintWriter 接受符合类型数据
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String name = req.getParameter("name"); // 获取请求参数
resp.setContentType("text/html;charset=utf-8"); // 设置响应类型
PrintWriter out = resp.getWriter(); // 获取响应的输出流
out.println(name); // 输出流,显示在浏览器上
out.close(); // 关闭流
}
当不输入参数时,返回空
输入name=123 时 浏览器中显示123
#JavaEE-过滤器-Filter
Filter被称为过滤器,过滤器实际上就是对Web资源进行拦截,做一些处理后再交给下一个过滤器或Servlet处理,通常都是用来拦截request进行处理的,也可以对返回的 response进行拦截处理。开发人员利用filter技术,可以实现对所有Web资源的管理,例如实现权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。
1、创建过滤器
创建一个软件包放过滤器的代码
2、过滤器内置方法
init doFilter destroy
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("Filter init");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("Filter doFilter");
}
@Override
public void destroy() {
System.out.println("Filter destroy");
}
3、过滤器触发流程 (两种方法一个是在Java代码上面写,第二种是在xml文件中写)
@WebFilter("/xss")
xml文件写入路由关系
<filter>
<filter-name>xss</filter-name>
<filter-class>Filter.FilterTest</filter-class>
</filter>
<filter-mapping>
<filter-name>xss</filter-name>
<url-pattern>/test</url-pattern>
</filter-mapping>
4、过滤器安全场景 (filter内存马)
Payload检测,权限访问控制,红队内存马植入,蓝队清理内存马等
内存马参考:深入浅出内存马(一)
5、案例演示
xss攻击的检测,管理页面的cookie检测
刚打开页面就已经开始初始化了,还没有访问test 就已经开始初始化了
访问test,只执行了filter的dofilter方法,而ServletTest类中的方法都没执行,是因为doFilter方法没有写放行代码或者访问的时候被过滤掉了
在doFilter方法中加上放行代码
filterChain.doFilter(servletRequest, servletResponse); // 放行请求
这里可以看到代码的执行顺序
输入123 也是可以正常输出的
输入js代码也可以正常执行
加入过滤条件 doFilter方法中写入一个判断,如果name包含script 就输出拦截请求,没有就放行
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("Filter doFilter");
HttpServletRequest request = (HttpServletRequest) servletRequest;
String name = request.getParameter("name");
if (!name.contains("script")) {
filterChain.doFilter(servletRequest, servletResponse); // 放行请求
}else{
System.out.println("拦截请求");
servletResponse.getWriter().write("拦截请求");
}
这里输入含刚刚的js语句,语句中包含script 会被拦截,所以就不会执行ServletTest中的doget方法了,已经被filter给过滤掉了,请求不会被放行过去
servlet代码:
package Servlet;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet(name = "servletTest",value = "/test")
public class ServletTest extends HttpServlet {
@Override
public void init() throws ServletException {
System.out.println("init");
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("doGet");
String name = req.getParameter("name"); // 获取请求参数
resp.setContentType("text/html;charset=utf-8"); // 设置响应类型
PrintWriter out = resp.getWriter(); // 获取响应的输出流
out.println(name); // 输出流,显示在浏览器上
out.close(); // 关闭流
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("doPost");
}
@Override
public void destroy() {
System.out.println("destroy");
}
}
Filter 过滤器代码:
package Filter;
import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpServletRequest;
import java.io.IOException;
@WebFilter(filterName = "xss", urlPatterns = "/test")
public class FilterTest implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("Filter init");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("Filter doFilter");
HttpServletRequest request = (HttpServletRequest) servletRequest;
String name = request.getParameter("name");
if (!name.contains("script")) {
filterChain.doFilter(servletRequest, servletResponse); // 放行请求
}else{
System.out.println("拦截请求");
servletResponse.getWriter().write("拦截请求");
}
}
@Override
public void destroy() {
System.out.println("Filter destroy");
}
}
#JavaEE-监听器-Listen
参考:Web应用监听器实战:在线人数统计与事件处理-CSDN博客
-监听ServletContext、HttpSession、ServletRequest等域对象创建和销毁事件
-监听域对象的属性发生修改的事件
-监听在事件发生前、发生后做一些必要的处理
1、创建监听器
创建一个名为Listen的软件包,在软件包里面创建java类
2、监听器内置方法
3、监听器触发流程 和过滤器一样,也是有两种实现,不过监听器不用写访问路径什么的。它是
@WebListener
xml
<listener>
<listener-class>Listen.LisetenTest</listener-class>
</listener>
4、监听器安全场景 (lister内存马)
内存马是用到了反射技术,上面的操作都是要重启服务器才能把新东西弄上去,而内存马可以在网站运行中植入一个lister内存马进去,让它实时生效
代码审计中分析执行逻辑触发操作,红队内存马植入,蓝队清理内存马等
5、案例演示
session存在的监听
当用户第一次访问服务器(且未携带有效的 Session ID)时,服务器(如 Tomcat)会自动创建一个 HttpSession 对象,用于标识这个用户的会话。
F12 查看一下 第一次访问时就会生成一个session值了
这里写了一个删除会话(session),然后服务器又会返回一个新的session值,建立新的会话
Java删除会话代码:
package Servlet;
import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/LisetenTest")
public class ServletSession extends HttpServlet {
@Override
public void init(ServletConfig config) throws ServletException {
System.out.println("ServletSession init");
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("ServletSession doGet");
req.getSession().invalidate(); // 销毁会话,session失效
}
@Override
public void destroy() {
System.out.println("ServletSession destroy");
}
}
lister 监听器代码:
package Listen;
import jakarta.servlet.annotation.WebListener;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpSessionEvent;
import jakarta.servlet.http.HttpSessionListener;
@WebListener
public class LisetenTest implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent se) {
System.out.println("sessionCreated"); // session被创建时执行
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
System.out.println("sessionDestroyed"); // session被销毁时执行
}
}