Web资源访问的流程
由此可见 客户访问JAVA开发的应用时 会先通过 监听器(Listener)和 过滤器(Filter) 今天简单的了解下这两个模块的开发过程
监听器(Listener)
主要是监听 我们触发了什么行为 并进行反应 下面是一个监听Session的例子
正常创建项目后 目录文件如下
CSession代码
import jakarta.servlet.http.*; import java.io.IOException; @WebServlet("/CS") // 映射到路径 "/CS" public class CSession extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 控制台输出,表示正在创建 Session System.out.println("creat Session"); // 调用 req.getSession() 方法获取或创建 Session // 如果请求中没有 Session,则自动创建新 Session req.getSession(); } }
DSession代码
package com.example.listendemo1.Servlet; import jakarta.servlet.ServletException; import jakarta.servlet.annotation.WebServlet; import jakarta.servlet.http.*; import java.io.IOException; @WebServlet("/DS") // 映射到路径 "/DS" public class DSession extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 控制台输出日志,表示正在销毁 Session System.out.println("kill Session"); // 获取当前 Session 并立即使其失效 // invalidate() 方法会销毁 Session,清除所有存储的属性 req.getSession().invalidate(); } }
以上两个代码操作为 访问路径(/CS|/DS)后对Session进行创建(删除)操作
ListenSession代码
package com.example.listendemo1.Listener; import jakarta.servlet.annotation.WebListener; import jakarta.servlet.http.HttpSessionEvent; import jakarta.servlet.http.HttpSessionListener; @WebListener public class ListenSession implements HttpSessionListener { @Override public void sessionCreated(HttpSessionEvent se) { // 输出 Session 创建日志(控制台) System.out.println("Session created in Listen Session"); } @Override public void sessionDestroyed(HttpSessionEvent se) { // 输出 Session 销毁日志(控制台) System.out.println("Session destroyed in Listen Session"); } }
监听器(Listener)运行情况
在没有操作时就会产生默认操作
创建Session
删除Session 监听器监听到了该动作
过滤器(Filter)
路径如下
TextServlet代码
package com.example.filterdemo1.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("/text") // 定义Servlet访问路径 public class TextServlet extends HttpServlet { //处理HTTP GET请求 @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 从请求中获取名为"code"的参数值 String code = req.getParameter("code"); // 获取响应输出流(自动设置text/html内容类型) PrintWriter out = resp.getWriter(); // 将参数值写入响应 out.println(code); // 刷新并关闭输出流 out.flush(); out.close(); } }
XssFilter代码
package com.example.filterdemo1.filter; import jakarta.servlet.*; import jakarta.servlet.annotation.WebFilter; import jakarta.servlet.http.HttpServletRequest; import java.io.IOException; @WebFilter("/text") // 只过滤/text路径的请求 public class XssFilter implements Filter { // 过滤器初始化方法(容器启动时执行一次) @Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println("XssFilter first"); // 初始化日志 } // 过滤器销毁方法(容器关闭时执行) @Override public void destroy() { System.out.println("XssFilter end"); // 销毁日志 } // 过滤处理方法(每次请求时执行) @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("XssFilter now"); // 处理请求日志 // 类型转换获取HttpServletRequest HttpServletRequest requset = (HttpServletRequest) servletRequest; // 获取请求参数code的值 String code = requset.getParameter("code"); // 检查是否不包含<script>标签 if (!code.contains("<script>")) { // 安全请求,放行 filterChain.doFilter(servletRequest, servletResponse); } else { // 检测到潜在XSS攻击 System.out.println("XssFilter fight!!"); // 攻击日志 // 注意:这里只是记录日志,实际应该阻止请求继续处理 } } }
测试代码运行如下:
预启动
添加代码--text?code=<script>alert(1)</script> 正常执行可以在页面弹出1
显示受到了攻击
正常情况是这个样子--text?code=123
第二个例子:/admin
AdminServlet代码
package com.example.filterdemo1.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; //管理员后台Servlet @WebServlet("/admin") // 定义Servlet访问路径为/admin public class AdminServlet extends HttpServlet { // 处理HTTP GET请求 @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 控制台输出欢迎信息 System.out.println("Welcome to Admin Servlet"); } }
AdminFiler代码
package com.example.filterdemo1.filter; import jakarta.servlet.*; import jakarta.servlet.annotation.WebFilter; import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServletRequest; import java.io.IOException; // 管理员权限过滤器 // 作用路径:/admin @WebFilter("/admin") // 过滤所有访问/admin路径的请求 public class AdminFilter implements Filter { // 过滤器初始化方法(容器启动时执行一次) @Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println("XssFilter first"); // 初始化日志 } // 过滤器销毁方法(容器关闭时执行) @Override public void destroy() { System.out.println("XssFilter end"); // 销毁日志 } /** * 过滤处理方法(每次访问/admin时执行) * 通过检查Cookie验证管理员权限 */ @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { // 转换请求对象以获取Cookie HttpServletRequest requset = (HttpServletRequest) servletRequest; // 获取请求中的所有Cookie Cookie[] cookies = requset.getCookies(); // 遍历所有Cookie for (Cookie c : cookies) { String cName = c.getName(); // 获取Cookie名称 String cValue = c.getValue(); // 获取Cookie值 // 打印Cookie信息(调试用) System.out.println(cName); System.out.println(cValue); // 检查是否为管理员Cookie if (cName.equals("username") && cValue.equals("admin")) { // 验证通过,放行请求 filterChain.doFilter(servletRequest, servletResponse); return; // 找到有效Cookie后立即返回 } else { // 非管理员Cookie System.out.println("NO ADMIN"); } } } }
实验结果如下:
会打印出Cookie值 因为是循环输出 Cookie都会被输出 admin认证成功 第二个password也会输出 但是没有对password进行判断 所有会输出NO ADMIN