Java利用過濾器實(shí)現(xiàn)完善登錄功能
1、問題引入
我們已經(jīng)完成了后臺(tái)系統(tǒng)的登錄功能開發(fā),但是目前還存在一個(gè)問題,就是用戶如果不登錄,直接訪問系統(tǒng)首頁(yè)面,照樣可以正常訪問。
很明顯,上面這種情況并不合理,我們希望看到的效果應(yīng)該是,只有登錄成功后才可以訪問系統(tǒng)中的頁(yè)面,如果沒有登錄, 訪問系統(tǒng)中的任何界面都直接跳轉(zhuǎn)到登錄頁(yè)面。
2、解決思路
使用 過濾器或者攔截器來(lái)實(shí)現(xiàn),在過濾器、攔截器中攔截前端發(fā)起的請(qǐng)求,判斷用戶是否已經(jīng)完成登錄,如果沒有登錄則返回提示信息,跳轉(zhuǎn)到登錄頁(yè)面,那我這篇博客選擇的是過濾器來(lái)實(shí)現(xiàn)這個(gè)效果。
過濾器具體的處理邏輯如下:
A. 獲取本次請(qǐng)求的URI
B. 判斷本次請(qǐng)求, 是否需要登錄, 才可以訪問
C. 如果不需要,則直接放行
D. 判斷登錄狀態(tài),如果已登錄,則直接放行
E. 如果未登錄, 則返回未登錄結(jié)果
如果未登錄,我們需要給前端返回什么樣的結(jié)果呢? 這個(gè)時(shí)候, 可以去看看前端代碼是如何處理的,大家可以先看看我這里的前端是如何處理的。(每個(gè)前端處理方式都不一樣,隨機(jī)應(yīng)變)
這個(gè)是我們前端的攔截器,這個(gè)攔截器就是用來(lái)攔截我們服務(wù)端給頁(yè)面上的響應(yīng)的,一旦我們后端給前端響應(yīng)之后,它就會(huì)執(zhí)行下面的代碼進(jìn)行判斷。
大家也可以看到它里面的if判斷 ,如果我們后端給前端返回的數(shù)據(jù)是
res.data.code = 0 && res.data.msg='NOTLOGIN'
那它就會(huì)自動(dòng)跳到登錄界面。
3、代碼實(shí)現(xiàn)
3.1 定義登錄校驗(yàn)過濾器
首先我們創(chuàng)建一個(gè)過濾器 LoginCheckFilter 并實(shí)現(xiàn) Filter 接口, 在doFilter方法中完成校驗(yàn)的邏輯。
/** * @description: 檢查用戶是否已經(jīng)完成登錄 * @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 :用于將一個(gè)類聲明為過濾器,filterName 指定過濾器的名稱,urlPatterns :需要攔截的請(qǐng)求路徑
首先我們要獲取到 request 和 response 和請(qǐng)求路徑,這三位后面都會(huì)用到。
現(xiàn)在我們獲取到了請(qǐng)求路徑,就可以去判斷哪些請(qǐng)求路徑是需要進(jìn)行處理的,因?yàn)樵陧?xiàng)目實(shí)際開發(fā)中,我們的項(xiàng)目中有些地方是不需要登錄也能進(jìn)行訪問的,比如淘寶和京東的首頁(yè),大家不登陸也能訪問吧,所以我們要將這些路徑定義出來(lái),如果用戶訪問的是這些路徑,那么我們就直接放行,就不處理了。
上面就是我定義不需要攔截的請(qǐng)求路徑,相信大家看到了最后兩個(gè)路徑有些不一樣,這里呢我們用的是通配符的方式。
通配符規(guī)則:
符號(hào) | 含義 |
---|---|
? | 匹配一個(gè)字符 |
* | 匹配0個(gè)或多個(gè)字符 |
** | 匹配0個(gè)或多個(gè)目錄/字符 |
但是現(xiàn)在有一個(gè)問題,比如我現(xiàn)在請(qǐng)求的是/backend/index.html ,這對(duì)不上呀!那該如何去匹配呢?
這個(gè)時(shí)候我們就要認(rèn)識(shí)一個(gè)新的對(duì)象 AntPathMatcher 。
現(xiàn)在我們通過這個(gè)路徑匹配器,匹配一下這個(gè)請(qǐng)求過來(lái)的路徑是否能匹配上我們定義不需要攔截的請(qǐng)求路徑里的任意一項(xiàng)。
這里我們封裝一個(gè)方法用來(lái)判斷本次請(qǐng)求是否需要處理。
這樣我們?cè)谏厦嬲{(diào)用,然后判斷一下是否需要處理,如果不需要處理,那就直接放行即可。
反之就是需要判斷是否需要登錄,那我們?nèi)绾闻袛嘤脩羰欠竦卿浤??因?yàn)槲沂堑卿浀臅r(shí)候?qū)⒂脩舻男畔⒋娴絪ession 里的 ,那這里我就是 從session 里 獲取登錄用戶,如果能獲取出來(lái),就代表用戶已經(jīng)登錄。
如果用戶沒有登錄我們就需要通過輸出流方式向客戶端頁(yè)面響應(yīng)數(shù)據(jù)。
完整代碼 :
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: 檢查用戶是否已經(jīng)完成登錄 * @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("攔截到請(qǐng)求,{}", requestURI); //2、判斷本次請(qǐng)求是否需要處理 //定義不需要處理的請(qǐng)求路徑 String[] urls = new String[]{ "/employee/login", "/employee/logout", "/backend/**", "/front/**" }; boolean check = check(urls, requestURI); //3、如果不需要處理,則直接放行 if (check) { log.info("本次請(qǐng)求{}不需要處理", requestURI); filterChain.doFilter(request, response); return; } //4、判斷登錄狀態(tài),如果已登錄,則直接放行 if (request.getSession().getAttribute("employee") != null) { log.info("用戶已登錄,用戶id為:{}", request.getSession().getAttribute("employee")); filterChain.doFilter(request, response); return; } log.info("用戶未登錄"); //5、如果未登錄則返回未登錄結(jié)果,通過輸出流方式向客戶端頁(yè)面響應(yīng)數(shù)據(jù) 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 開啟組件掃描
需要在啟動(dòng)類上, 加上Servlet組件掃描的注解, 來(lái)掃描過濾器配置的@WebFilter注解, 掃描上之后, 過濾器在運(yùn)行時(shí)就生效了。
到此這篇關(guān)于Java利用過濾器實(shí)現(xiàn)完善登錄功能的文章就介紹到這了,更多相關(guān)Java過濾器 登錄內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java時(shí)間復(fù)雜度、空間復(fù)雜度的深入詳解
對(duì)于一個(gè)算法,其時(shí)間復(fù)雜度和空間復(fù)雜度往往是相互影響的,當(dāng)追求一個(gè)較好的時(shí)間復(fù)雜度時(shí),可能會(huì)使空間復(fù)雜度的性能變差,即可能導(dǎo)致占用較多的存儲(chǔ)空間,這篇文章主要給大家介紹了關(guān)于Java時(shí)間復(fù)雜度、空間復(fù)雜度的相關(guān)資料,需要的朋友可以參考下2021-11-11Java+element實(shí)現(xiàn)excel的導(dǎo)入和導(dǎo)出
本文主要介紹了Java+element實(shí)現(xiàn)excel的導(dǎo)入和導(dǎo)出,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-04-04Java實(shí)現(xiàn)一個(gè)簡(jiǎn)單的線程池代碼示例
線程池是管理線程的一個(gè)池子,通過阻塞隊(duì)列管理任務(wù),主要參數(shù)包括corePoolSize、maximumPoolSize、keepAliveTime等,這篇文章主要介紹了Java實(shí)現(xiàn)一個(gè)簡(jiǎn)單的線程池的相關(guān)資料,需要的朋友可以參考下2024-09-09Spring?IOC容器基于XML外部屬性文件的Bean管理
這篇文章主要為大家介紹了Spring?IOC容器Bean管理XML外部屬性文件,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05springBoot的事件機(jī)制GenericApplicationListener用法解析
這篇文章主要介紹了springBoot的事件機(jī)制GenericApplicationListener用法解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值的相關(guān)資料2019-09-09