<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      登錄校驗---Filter過濾器

      過濾器(Filter)

      • 概念: Filter 過濾器,是 JavaWeb 三大組件(Servlet、Filter、Listener)之一。
      • 過濾器可以把對資源的請求攔截下來,從而實現一些特殊的功能。
      • 過濾器一般完成一些通用的操作,比如: 登錄校驗、統一編碼處理、敏感字符處理等。

      img

      代碼演示

      步驟

      自定義Filter:繼承Filter并且重寫其方法(主要重寫doFilter()

      配置Filter:配置@WebFilter(urlPatterns = ("/*"))以及攔截路徑,并且在啟動類添加注解@ServletComponentScan開啟Servlet組件支持

      @WebFilter(urlPatterns = ("/*"))
      public class DemoFilter implements Filter {
          @Override
          public void init(FilterConfig filterConfig) throws ServletException {
              System.out.println("init 初始化攔截器...");
          }
      
          @Override
          public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
              System.out.println("攔截到了請求...放行前");
              // 放行
              filterChain.doFilter(servletRequest, servletResponse);
              System.out.println("攔截到了請求...放行后");
      
          }
      
          @Override
          public void destroy() {
              System.out.println("destroy方法執行...");
          }
      }
      

      方法介紹

      init():初始化方法,Web 服務器啟動,創建Filter時調用,只調用一次

      doFilter():攔截到了請求,并執行該方法,可多次調用,注意關鍵的實現filterChain.doFilter()以及攔截前后的邏輯實現

      destroy():銷毀方法,服務器關閉執行,只調用一次

      攔截路徑設置

      攔截路徑 urlPatterns值 含義
      攔截具體路徑 /login 只有訪問 /login 路徑時,才會被攔截
      目錄攔截 /emps/* 訪問/emps下的所有資源,都會被攔截
      攔截所有 /* 訪問所有資源,都會被攔截

      過濾器鏈

      一個web應用中,可以配置多個過濾器,這多個過濾器就形成了一個過濾器鏈。

      執行順序: 注解配置的Filter,優先級是按照過濾器類名(字符串A, B, C, ....)的自然排序。

      img

      擴展知識點(doFilter()

      通過校驗請求認證頭(authHeader)所攜帶的token去校驗,我在Postman中使用的是Bearer Token身份校驗,Bearer Token 在請求頭中以 Bearer 關鍵字加上令牌本身的形式發送,格式通常為Authorization: Bearer <token>。詳細可看Apifox--什么是Bearer Token

      img

      代碼展示 --- doFilter()

      @Override
      public void doFilter(ServletRequest request, ServletResponse response, 
                           FilterChain chain) throws IOException, ServletException {
      
          HttpServletRequest httpRequest = (HttpServletRequest) request;
          HttpServletResponse httpResponse = (HttpServletResponse) response;
      
          // 設置響應頭
          setupResponseHeaders(httpResponse);
      
          // 處理預檢請求
          if ("OPTIONS".equalsIgnoreCase(httpRequest.getMethod())) {
              httpResponse.setStatus(HttpServletResponse.SC_OK);
              return;
          }
      
          // 獲取請求路徑
          String requestPath = httpRequest.getRequestURI();
          String contextPath = httpRequest.getContextPath();
          String path = requestPath.substring(contextPath.length());
      
          // 檢查是否為排除路徑
          if (isExcludePath(path)) {
              chain.doFilter(request, response);
              return;
          }
      
          // 獲取認證頭部
          String authHeader = httpRequest.getHeader(AUTH_HEADER);
      
          // 檢查認證頭是否存在且格式正確
          if (authHeader == null || !authHeader.startsWith(BEARER_PREFIX)) {
              sendUnauthorizedResponse(httpResponse, "請先登錄");
              return;
          }
      
          // 提取 JWT 令牌
          String jwtToken = authHeader.substring(BEARER_PREFIX.length()).trim();
      
          try {
              // 驗證 JWT 令牌
              if (!JwtUtils.validateToken(jwtToken)) {
                  sendUnauthorizedResponse(httpResponse, "令牌無效或已過期");
                  return;
              }
      
              // 從 JWT 中解析用戶信息
              Long userId = JwtUtils.getUserIdFromToken(jwtToken);
              String userAccount = JwtUtils.getUserAccountFromToken(jwtToken);
              String userName = JwtUtils.getUserNameFromToken(jwtToken);
      
              // 將用戶信息放入請求屬性,供后續使用
              httpRequest.setAttribute("id", userId);
              httpRequest.setAttribute("userAccount", userAccount);
              httpRequest.setAttribute("userName", userName);
      
              System.out.println("JWT認證成功 - 用戶ID: " + userId + ", 賬號: " + userAccount);
      
              // 繼續過濾器鏈
              chain.doFilter(request, response);
      
          } catch (Exception e) {
              sendUnauthorizedResponse(httpResponse, "令牌解析失敗: " + e.getMessage());
          }
      }
      

      封裝方法

      在執行過濾器中,除了校驗令牌,我們還要做其他的工作

      1)排除不需要認證的路徑

      檢查是否為排除路徑(不需要認證的路徑):比如登錄、注冊等等

      // 排除認證的路徑
      private static final String[] EXCLUDE_PATHS = {
          "/user/login",
          "/user/register",
          "/doc.html",
          "/webjars/",
          "/swagger-resources",
          "/v2/api-docs"
      };
      /**
           * 檢查是否為排除路徑(不需要認證的路徑)
           */
      private boolean isExcludePath(String path) {
      for (String excludePath : EXCLUDE_PATHS) {
          if (path.startsWith(excludePath)) {
              return true;
          }
      }
      return false;
      

      2)設置響應頭

      主要處理CORS(跨域資源共享)配置和字符編碼

      /**
           * 設置響應頭
           */
      private void setupResponseHeaders(HttpServletResponse response) {
          response.setHeader("Access-Control-Allow-Origin", "*");
          response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
          response.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type, X-Requested-With");
          response.setHeader("Access-Control-Max-Age", "3600");
          response.setCharacterEncoding("UTF-8");
          response.setContentType("application/json;charset=UTF-8");
      }
      

      作用:

      Access-Control-Allow-Origin: "*"

      • 允許所有域名訪問你的 API
      • 如果是生產環境,建議改為具體域名:"http://your-frontend.com"

      Access-Control-Allow-Methods: "GET, POST, PUT, DELETE, OPTIONS"

      • 允許前端使用這些 HTTP 方法

      Access-Control-Allow-Headers: "Authorization, Content-Type, X-Requested-With"

      • 允許前端發送這些自定義請求頭
      • 特別重要:包含了 Authorization,這樣前端才能發送 JWT Token

      Access-Control-Max-Age: "3600"

      • 預檢請求緩存時間(1小時),減少重復的 OPTIONS 請求

      什么是 OPTIONS 請求

      OPTIONS 是 HTTP 方法之一,用于獲取目標資源支持的通信選項。在 CORS 中,瀏覽器會自動發送 OPTIONS請求來檢查是否允許跨域訪問。

      什么時候會發送 OPTIONS 請求

      觸發條件

      跨域請求(域名、端口、協議不同)

      非簡單請求(滿足以下任一條件):

      簡單請求(不會觸發 OPTIONS):

      GET /api/data HTTP/1.1
      Host: api.example.com
      Origin: https://frontend.com
      

      非簡單請求(會觸發 OPTIONS):
      自定義請求頭

      POST /api/user HTTP/1.1
      Host: localhost:8080
      Origin: http://localhost:3000
      Authorization: Bearer token123  # 自定義頭
      X-Custom-Header: value         # 自定義頭
      

      非簡單 Content-Type

      POST /api/user HTTP/1.1
      Content-Type: application/json  # 非簡單 Content-Type
      

      非簡單 HTTP 方法

      PUT /api/user/1 HTTP/1.1
      PATCH /api/user/1 HTTP/1.1
      DELETE /api/user/1 HTTP/1.1
      

      3)發送未認證錯誤響應

      /**
           * 發送未認證錯誤響應
           */
      private void sendUnauthorizedResponse(HttpServletResponse response, String message) throws IOException {
          response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
          String jsonResponse = String.format(
              "{\"code\": 401, \"message\": \"%s\", \"data\": null, \"description\": \"未授權訪問\"}",
              message
          );
          response.getWriter().write(jsonResponse);
      }
      

      end

      posted @ 2025-10-13 23:39  Lantz12  閱讀(10)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 99精品国产中文字幕| 国产91小视频在线观看| 一区二区传媒有限公司| 国产综合一区二区三区麻豆| av色蜜桃一区二区三区| 免费无码AV一区二区波多野结衣| 亚洲av第一区二区三区| 久久天天躁狠狠躁夜夜2020老熟妇| 色AV专区无码影音先锋| 亚洲国产成人资源在线| 国产精品白丝久久AV网站| 动漫精品中文字幕无码| 国产精品一码在线播放| 国产一区二区三区高清视频| 免费国产高清在线精品一区| 韩国三级网一区二区三区| 草草浮力影院| 免费无遮挡无码永久视频| 免费播放一区二区三区| 91福利国产午夜亚洲精品| 蜜臀精品视频一区二区三区| 国内精品久久久久影院薰衣草| 九九热精彩视频在线免费| 日本三级香港三级三级人妇久| 欧美午夜小视频| 国内不卡一区二区三区| 亚洲综合久久精品哦夜夜嗨| 波多野结衣一区二区三区高清| 久久精品夜色噜噜亚洲av| 精品中文字幕人妻一二| 亚洲日本VA午夜在线电影| 国产精品扒开腿做爽爽爽a片唱戏| 一本无码在线观看| 国产黄色看三级三级三级| 精品日韩亚洲av无码| 国产精品人伦一区二区三| 亚洲日本va午夜中文字幕久久| 色综合人人超人人超级国碰| 真实单亲乱l仑对白视频| 国产蜜臀久久av一区二区| 99国产精品永久免费视频|