Springboot登錄驗證的統(tǒng)一攔截處理的實現(xiàn)
在進(jìn)行Springboot項目開發(fā)的時候如何把每次請求都要驗證的用戶進(jìn)行提取攔截統(tǒng)一處理
背景
如果不進(jìn)行統(tǒng)一的攔截處理,其實這是一個非常痛苦的一件事情,因為每次用戶請求你都要去進(jìn)行用戶的信息(用戶信息存儲在session中)的驗證,代碼重復(fù),所以在本篇提供一個解決方案:
定義一個攔截器,把請求都進(jìn)行統(tǒng)一的處理,如果Session中存在用戶的信息那么就放行;如果不存在,那么就直接出現(xiàn)異常報錯未登錄。在這樣的一個方案中其實還存在著一個問題,在業(yè)務(wù)邏輯中我要去獲取用戶的信息,那不又是很麻煩了?這里可以通過ThreadLocal解決。
為什么用ThreadLocal:當(dāng)用戶發(fā)起請求時,會訪問我們像tomcat注冊的端口,任何程序想要運行,都需要有一個線程對當(dāng)前端口號進(jìn)行監(jiān)聽,tomcat也不例外,當(dāng)監(jiān)聽線程知道用戶想要和tomcat連接連接時,那會由監(jiān)聽線程創(chuàng)建socket連接,socket都是成對出現(xiàn)的,用戶通過socket像互相傳遞數(shù)據(jù),當(dāng)tomcat端的socket接受到數(shù)據(jù)后,此時監(jiān)聽線程會從tomcat的線程池中取出一個線程執(zhí)行用戶請求,在我們的服務(wù)部署到tomcat后,線程會找到用戶想要訪問的工程,然后用這個線程轉(zhuǎn)發(fā)到工程中的controller,service,dao中,并且訪問對應(yīng)的DB,在用戶執(zhí)行完請求后,再統(tǒng)一返回,再找到tomcat端的socket,再將數(shù)據(jù)寫回到用戶端的socket,完成請求和響應(yīng)通過以上講解,我們可以得知 每個用戶其實對應(yīng)都是去找tomcat線程池中的一個線程來完成工作的, 使用完成后再進(jìn)行回收,既然每個請求都是獨立的,所以在每個用戶去訪問我們的工程時,我們可以使用threadlocal來做到線程隔離,每個線程操作自己的一份數(shù)據(jù)
定義一個ThreadLocal線程工具類
便于對線程內(nèi)部的值進(jìn)行處理。
public class UserHolder { public static final ThreadLocal<User> userThreadLocal = new ThreadLocal<>(); public static void setValue(User user){ userThreadLocal.set(user); } public static User getValue(){ return userThreadLocal.get(); } public static void clear(){ userThreadLocal.remove(); } }
定義攔截器
public class LoginInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 獲取 session HttpSession session = request.getSession(); // 檢查用戶是否已登錄 if (session.getAttribute("user") == null) { // 用戶未登錄,進(jìn)行相關(guān)處理 throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR); } // 從 session 中獲取用戶數(shù)據(jù) User user = (User) session.getAttribute("user"); // 將用戶數(shù)據(jù)存儲到 ThreadLocal 中,以便在整個請求周期內(nèi)訪問 UserHolder.setValue(user); // 進(jìn)行其他邏輯驗證,根據(jù)需求自行添加 return true; // 允許請求繼續(xù)執(zhí)行 } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { // 在請求處理之后執(zhí)行,可以對 ModelAndView 進(jìn)行修改 } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // 在請求完成之后執(zhí)行,用于資源清理等操作 // 清理 ThreadLocal 中的用戶數(shù)據(jù),防止內(nèi)存泄漏 UserHolder.clear(); } }
讓攔截器生效
通過配置讓攔截器生效
@Configuration public class MvcConfig implements WebMvcConfigurer { public void addInterceptors(InterceptorRegistry registry) { // 添加攔截器 // excludePath 就是排除在外被攔截的路徑 registry.addInterceptor(new LoginInterceptor()) .addPathPatterns("/**") .excludePathPatterns( "/user/login" ); } }
然后就可以啦
測試
測試Controller
@RestController @RequestMapping("/user") public class UserController { @Resource private UserService userService; @PostMapping("/login") public BaseResponse<User> login(HttpSession session){ System.out.println("Hello"); Random random = new Random(new Date().getTime()) ; User user = new User(random.nextLong(), "123","123454","123"); session.setAttribute("user",user); return ResultUtils.success(user); } @GetMapping("/get") public BaseResponse<User> get(){ return ResultUtils.success(UserHolder.getValue()); } }
測試結(jié)果
開始沒有登錄
進(jìn)行登錄
再次獲取get請求就可以了
這里我出現(xiàn)一個問題我一直調(diào)試了很久,md,就是在配置攔截器的時候添加路徑首先把所有路徑進(jìn)行攔截,然后放行/user/login就好,我的這個項目在配置文件中給所有的路徑首先加了一個/api這樣的前綴,然后我在攔截路徑的時候都加了api,這個其實是不用加的,直接上路徑就好了,spring自動會加。
到此這篇關(guān)于Springboot登錄驗證的統(tǒng)一攔截處理的實現(xiàn)的文章就介紹到這了,更多相關(guān)Springboot登錄驗證統(tǒng)一攔截處理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringBoot使用JWT實現(xiàn)登錄驗證的方法示例
- SpringBoot登錄驗證碼實現(xiàn)過程詳解
- SpringBoot Security前后端分離登錄驗證的實現(xiàn)
- Springboot2.1.6集成activiti7出現(xiàn)登錄驗證的實現(xiàn)
- vue+springboot實現(xiàn)登錄驗證碼
- springboot整合shiro實現(xiàn)登錄驗證授權(quán)的過程解析
- SpringBoot登錄驗證token攔截器的實現(xiàn)
- SpringBoot集成JWT實現(xiàn)Token登錄驗證的示例代碼
- SpringBoot中過濾器Filter+JWT令牌實現(xiàn)登錄驗證
相關(guān)文章
JAVA SpringBoot統(tǒng)一日志處理原理詳解
這篇文章主要介紹了SpringBoot的統(tǒng)一日志處理原理,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-09-09netty對proxy protocol代理協(xié)議的支持詳解
這篇文章主要為大家介紹了netty對proxy protoco代理協(xié)議的支持詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07Eolink上傳文件到Java后臺進(jìn)行處理的示例代碼
這篇文章主要介紹了Eolink上傳文件到Java后臺進(jìn)行處理,這里是上傳的excel表格數(shù)據(jù)并轉(zhuǎn)換為java集合對象、然后進(jìn)行業(yè)務(wù)邏輯處理判斷最后保存到數(shù)據(jù)庫?,需要的朋友可以參考下2022-12-12SpringCloud手寫Ribbon實現(xiàn)負(fù)載均衡
這篇文章主要介紹了SpringCloud手寫Ribbon實現(xiàn)負(fù)載均衡的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01Java關(guān)鍵字final的實現(xiàn)原理分析
這篇文章主要介紹了Java關(guān)鍵字final的實現(xiàn)原理分析,在JDK8之前,如果在匿名內(nèi)部類中需要訪問局部變量,那么這個局部變量一定是final修飾的,但final關(guān)鍵字可以省略,需要的朋友可以參考下2024-01-01Java基于Socket實現(xiàn)網(wǎng)絡(luò)編程實例詳解
本文主要給大家介紹的是Java基于Socket實現(xiàn)網(wǎng)絡(luò)編程的實例,并給大家介紹了TCP與UDP傳輸協(xié)議,有需要的小伙伴可以來參考下2016-07-07探索Java中private方法添加@Transactional事務(wù)未生效原因
你又遇到過明明給private方法添加了@Transactional但是事務(wù)依然沒有生效的情況嗎,具體原因本篇文章將詳細(xì)告訴你,有需要的朋友跟著小編往下看吧2021-11-11