首頁 > 軟體

Java利用過濾器實現完善登入功能

2022-09-20 22:03:08

1、問題引入

我們已經完成了後臺系統的登入功能開發,但是目前還存在一個問題,就是使用者如果不登入,直接存取系統首頁面,照樣可以正常存取。

很明顯,上面這種情況並不合理,我們希望看到的效果應該是,只有登入成功後才可以存取系統中的頁面,如果沒有登入, 存取系統中的任何介面都直接跳轉到登入頁面。

2、解決思路

使用 過濾器或者攔截器來實現,在過濾器、攔截器中攔截前端發起的請求,判斷使用者是否已經完成登入,如果沒有登入則返回提示資訊,跳轉到登入頁面,那我這篇部落格選擇的是過濾器來實現這個效果。

過濾器具體的處理邏輯如下:

A. 獲取本次請求的URI

B. 判斷本次請求, 是否需要登入, 才可以存取

C. 如果不需要,則直接放行

D. 判斷登入狀態,如果已登入,則直接放行

E. 如果未登入, 則返回未登入結果

如果未登入,我們需要給前端返回什麼樣的結果呢? 這個時候, 可以去看看前端程式碼是如何處理的,大家可以先看看我這裡的前端是如何處理的。(每個前端處理方式都不一樣,隨機應變)

這個是我們前端的攔截器,這個攔截器就是用來攔截我們伺服器端給頁面上的響應的,一旦我們後端給前端響應之後,它就會執行下面的程式碼進行判斷。

大家也可以看到它裡面的if判斷 ,如果我們後端給前端返回的資料是

res.data.code = 0 && res.data.msg='NOTLOGIN'

那它就會自動跳到登入介面。

3、程式碼實現

3.1 定義登入校驗過濾器

首先我們建立一個過濾器 LoginCheckFilter 並實現 Filter 介面, 在doFilter方法中完成校驗的邏輯。

/**
 * @description: 檢查使用者是否已經完成登入
 * @author: Jie
 * @date: 2022/8/10 9:48
 **/
@WebFilter(filterName = "loginCheckFilter", urlPatterns = "/*")
@Slf4j
public class LoginCheckFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
       
    }
}

注:

@WebFilter :用於將一個類宣告為過濾器,filterName 指定過濾器的名稱,urlPatterns :需要攔截的請求路徑

首先我們要獲取到 request 和 response 和請求路徑,這三位後面都會用到。

現在我們獲取到了請求路徑,就可以去判斷哪些請求路徑是需要進行處理的,因為在專案實際開發中,我們的專案中有些地方是不需要登入也能進行存取的,比如淘寶和京東的首頁,大家不登陸也能存取吧,所以我們要將這些路徑定義出來,如果使用者存取的是這些路徑,那麼我們就直接放行,就不處理了。

上面就是我定義不需要攔截的請求路徑,相信大家看到了最後兩個路徑有些不一樣,這裡呢我們用的是萬用字元的方式。

萬用字元規則:

符號含義
?匹配一個字元
*匹配0個或多個字元
**匹配0個或多個目錄/字元

但是現在有一個問題,比如我現在請求的是/backend/index.html ,這對不上呀!那該如何去匹配呢?

這個時候我們就要認識一個新的物件 AntPathMatcher 。

現在我們通過這個路徑匹配器,匹配一下這個請求過來的路徑是否能匹配上我們定義不需要攔截的請求路徑裡的任意一項。

這裡我們封裝一個方法用來判斷本次請求是否需要處理。

這樣我們在上面呼叫,然後判斷一下是否需要處理,如果不需要處理,那就直接放行即可。

反之就是需要判斷是否需要登入,那我們如何判斷使用者是否登入呢?因為我是登入的時候將使用者的資訊存到session 裡的 ,那這裡我就是 從session 裡 獲取登入使用者,如果能獲取出來,就代表使用者已經登入。

如果使用者沒有登入我們就需要通過輸出流方式向用戶端頁面響應資料。

完整程式碼 :

package com.jie.reggjie.filter;
 
import cn.hutool.core.text.AntPathMatcher;
import com.alibaba.fastjson.JSON;
import com.jie.reggjie.common.R;
import lombok.extern.slf4j.Slf4j;
 
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
 
/**
 * @description: 檢查使用者是否已經完成登入
 * @author: Jie
 * @date: 2022/8/10 9:48
 **/
@WebFilter(filterName = "loginCheckFilter", urlPatterns = "/*")
@Slf4j
public class LoginCheckFilter implements Filter {
 
    /**
     * 路徑匹配器,支援萬用字元
     */
    public static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();
 
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        String requestURI = request.getRequestURI();
        log.info("攔截到請求,{}", requestURI);
 
        //2、判斷本次請求是否需要處理
        //定義不需要處理的請求路徑
        String[] urls = new String[]{
                "/employee/login",
                "/employee/logout",
                "/backend/**",
                "/front/**"
        };
        boolean check = check(urls, requestURI);
 
        //3、如果不需要處理,則直接放行
        if (check) {
            log.info("本次請求{}不需要處理", requestURI);
            filterChain.doFilter(request, response);
            return;
        }
 
        //4、判斷登入狀態,如果已登入,則直接放行
        if (request.getSession().getAttribute("employee") != null) {
            log.info("使用者已登入,使用者id為:{}", request.getSession().getAttribute("employee"));
            filterChain.doFilter(request, response);
            return;
        }
        log.info("使用者未登入");
        //5、如果未登入則返回未登入結果,通過輸出流方式向用戶端頁面響應資料
        response.getWriter().write(JSON.toJSONString(R.error("NOTLOGIN")));
        return;
    }
 
    public boolean check(String[] urls, String requestURI) {
        for (String url : urls) {
            boolean match = PATH_MATCHER.match(url, requestURI);
            if (match) {
                return true;
            }
        }
        return false;
    }
}

3.2 開啟元件掃描

需要在啟動類上, 加上Servlet元件掃描的註解, 來掃描過濾器設定的@WebFilter註解, 掃描上之後, 過濾器在執行時就生效了。

到此這篇關於Java利用過濾器實現完善登入功能的文章就介紹到這了,更多相關Java過濾器 登入內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com