Web資源訪問的流程
由此可見 客戶訪問JAVA開發的應用時 會先通過 監聽器(Listener)和 過濾器(Filter) 今天簡單的了解下這兩個模塊的開發過程
監聽器(Listener)
主要是監聽 我們觸發了什么行為 并進行反應 下面是一個監聽Session的例子
正常創建項目后 目錄文件如下
CSession代碼
import jakarta.servlet.http.*; import java.io.IOException;@WebServlet("/CS") // 映射到路徑 "/CS" public class CSession extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 控制臺輸出,表示正在創建 SessionSystem.out.println("creat Session");// 調用 req.getSession() 方法獲取或創建 Session// 如果請求中沒有 Session,則自動創建新 Sessionreq.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 {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 控制臺輸出日志,表示正在銷毀 SessionSystem.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 {@Overridepublic void sessionCreated(HttpSessionEvent se) {// 輸出 Session 創建日志(控制臺)System.out.println("Session created in Listen Session");}@Overridepublic 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請求@Overrideprotected 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 {// 過濾器初始化方法(容器啟動時執行一次)@Overridepublic void init(FilterConfig filterConfig) throws ServletException {System.out.println("XssFilter first"); // 初始化日志}// 過濾器銷毀方法(容器關閉時執行)@Overridepublic void destroy() {System.out.println("XssFilter end"); // 銷毀日志}// 過濾處理方法(每次請求時執行)@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,FilterChain filterChain) throws IOException, ServletException {System.out.println("XssFilter now"); // 處理請求日志// 類型轉換獲取HttpServletRequestHttpServletRequest 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請求@Overrideprotected 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 {// 過濾器初始化方法(容器啟動時執行一次)@Overridepublic void init(FilterConfig filterConfig) throws ServletException {System.out.println("XssFilter first"); // 初始化日志}// 過濾器銷毀方法(容器關閉時執行)@Overridepublic void destroy() {System.out.println("XssFilter end"); // 銷毀日志}/*** 過濾處理方法(每次訪問/admin時執行)* 通過檢查Cookie驗證管理員權限*/@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,FilterChain filterChain) throws IOException, ServletException {// 轉換請求對象以獲取CookieHttpServletRequest requset = (HttpServletRequest) servletRequest;// 獲取請求中的所有CookieCookie[] cookies = requset.getCookies();// 遍歷所有Cookiefor (Cookie c : cookies) {String cName = c.getName(); // 獲取Cookie名稱String cValue = c.getValue(); // 獲取Cookie值// 打印Cookie信息(調試用)System.out.println(cName);System.out.println(cValue);// 檢查是否為管理員Cookieif (cName.equals("username") && cValue.equals("admin")) {// 驗證通過,放行請求filterChain.doFilter(servletRequest, servletResponse);return; // 找到有效Cookie后立即返回} else {// 非管理員CookieSystem.out.println("NO ADMIN");}}} }
實驗結果如下:
會打印出Cookie值 因為是循環輸出 Cookie都會被輸出 admin認證成功 第二個password也會輸出 但是沒有對password進行判斷 所有會輸出NO ADMIN