SpringBoot攔截器(Interceptor)自定義實現(xiàn)登錄鑒權(quán)功能
引言
在 Web 項目中,登錄鑒權(quán)是最核心的安全機制:
接口必須校驗用戶是否登錄、是否擁有權(quán)限,未登錄則直接攔截,禁止訪問。
SpringBoot 提供的 HandlerInterceptor 攔截器,是實現(xiàn)登錄校驗、日志記錄、接口限流最優(yōu)雅的方案。
本篇文章將介紹原理、自定義攔截器、登錄校驗實戰(zhàn)、放行白名單、全局異常處理。
一、什么是攔截器?作用是什么?
攔截器(Interceptor):在請求進(jìn)入 Controller 之前/之后/渲染完成 進(jìn)行攔截處理。
核心用途:
- 登錄狀態(tài)校驗
- 權(quán)限校驗
- 接口日志記錄
- 防重復(fù)提交
- 性能監(jiān)控
特點:
- 只攔截 Controller 請求
- 不攔截靜態(tài)資源(可配置)
- 可中斷請求,直接返回結(jié)果
- 全局統(tǒng)一控制,代碼干凈
二、攔截器核心 API
實現(xiàn) HandlerInterceptor 接口,重寫 3 個方法:
publicinterfaceHandlerInterceptor{
// 1. 請求進(jìn)入Controller之前執(zhí)行(鑒權(quán)寫這里)
defaultbooleanpreHandle(HttpServletRequest request,HttpServletResponse response,Object handler)throwsException{
returntrue;// true=放行 false=攔截
}
// 2. Controller執(zhí)行完畢,渲染頁面之前執(zhí)行
defaultvoidpostHandle(...)throwsException{}
// 3. 整個請求完全結(jié)束后執(zhí)行(清理資源)
defaultvoidafterCompletion(...)throwsException{}
}登錄鑒權(quán)只需要 preHandle
三、自定義登錄攔截器
創(chuàng)建 LoginInterceptor.java:
importlombok.extern.slf4j.Slf4j;
importorg.springframework.web.servlet.HandlerInterceptor;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
/**
* 登錄攔截器:校驗是否登錄
*/
@Slf4j
publicclassLoginInterceptorimplementsHandlerInterceptor{
// 進(jìn)入Controller前執(zhí)行:核心校驗邏輯
@Override
publicbooleanpreHandle(HttpServletRequest request,HttpServletResponse response,Object handler)throwsException{
// 1. 獲取前端傳遞的 Token / Session
String token = request.getHeader("token");
log.info("當(dāng)前請求token:{}", token);
// 2. 判斷是否登錄(真實項目:查詢Redis/數(shù)據(jù)庫)
if(token ==null|| token.isEmpty()){
log.error("用戶未登錄,請求被攔截");
// 攔截,返回未登錄提示
response.setContentType("application/json;charset=utf-8");
response.getWriter().write("{\"code\":401,\"msg\":\"未登錄,請先登錄\",\"data\":null}");
returnfalse;
}
// 3. 登錄有效,放行
returntrue;
}
}四、注冊攔截器 + 配置白名單
創(chuàng)建 WebConfig.java:
實現(xiàn) WebMvcConfigurer,注冊攔截器并設(shè)置放行接口(登錄、注冊、放行接口)。
importorg.springframework.context.annotation.Configuration;
importorg.springframework.web.servlet.config.annotation.InterceptorRegistry;
importorg.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
*Web 配置:注冊攔截器
*/
@Configuration
publicclassWebConfigimplementsWebMvcConfigurer{
@Override
publicvoidaddInterceptors(InterceptorRegistry registry){
registry.addInterceptor(newLoginInterceptor())
.addPathPatterns("/**")// 攔截所有請求
.excludePathPatterns(// 放行白名單
"/user/login",// 登錄接口
"/user/register",// 注冊接口
"/swagger/**",// 接口文檔
"/v3/api-docs/**"
);
}
}? 配置完成,所有接口都會自動校驗登錄
五、配合統(tǒng)一返回結(jié)構(gòu)
攔截器中直接返回 Result 格式:
response.setContentType("application/json;charset=utf-8");
Result result =Result.fail(401,"未登錄,請先登錄");
response.getWriter().write(newObjectMapper().writeValueAsString(result));
returnfalse;返回格式:
{
"code":401,
"msg":"未登錄,請先登錄",
"data":null
}六、登錄校驗邏輯
真實項目中,登錄邏輯一般是:
- 前端登錄成功,后端生成 Token
- Token 存入 Redis(設(shè)置過期時間)
- 前端每次請求在 請求頭 header 攜帶 token
- 攔截器獲取 token,查詢 Redis 是否有效
- 有效放行,無效攔截
完整版攔截器
1@Slf4j
2publicclassLoginInterceptorimplementsHandlerInterceptor{
3
4@Autowired
5privateRedisTemplate<String,Object> redisTemplate;
6
7@Override
8publicbooleanpreHandle(HttpServletRequest request,HttpServletResponse response,Object handler)throwsException{
9String token = request.getHeader("token");
10
11// 1. 無token
12if(token ==null|| token.isBlank()){
13returnresponseFail(response,"未登錄,請先登錄");
14}
15
16// 2. 校驗Redis
17Object user = redisTemplate.opsForValue().get("login:token:"+ token);
18if(user ==null){
19returnresponseFail(response,"登錄已過期,請重新登錄");
20}
21
22// 3. 放行
23returntrue;
24}
25
26// 統(tǒng)一返回錯誤
27privatebooleanresponseFail(HttpServletResponse response,String msg)throwsException{
28 response.setContentType("application/json;charset=utf-8");
29Result<?> result =Result.fail(401, msg);
30 response.getWriter().write(newObjectMapper().writeValueAsString(result));
31returnfalse;
32}
33}七、攔截器常見高級用法
1. 獲取當(dāng)前請求接口信息
HandlerMethod handlerMethod =(HandlerMethod) handler; String methodName = handlerMethod.getMethod().getName(); String className = handlerMethod.getBean().getClass().getName();
2. 放行靜態(tài)資源
.excludePathPatterns("/static/**","/img/**","/css/**","/js/**")3. 多攔截器順序
registry.addInterceptor(A).order(1); registry.addInterceptor(B).order(2);
數(shù)字越小,越先執(zhí)行。
八、攔截器 VS 過濾器 Filter
| 組件 | 技術(shù) | 作用范圍 | 適用場景 |
|---|---|---|---|
| 攔截器 Interceptor | Spring | 只攔截Controller | 登錄、權(quán)限、日志 |
| 過濾器 Filter | Servlet | 所有請求 | 編碼、跨域、限流 |
登錄鑒權(quán)優(yōu)先用攔截器!
九、總結(jié)
- 實現(xiàn) HandlerInterceptor
- preHandle 寫登錄校驗
- WebConfig 注冊 + 白名單
- 返回 401 未登錄
- 配合 Redis 實現(xiàn)真實登錄鑒權(quán)
以上就是SpringBoot攔截器(Interceptor)自定義實現(xiàn)登錄鑒權(quán)功能的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot攔截器實現(xiàn)登錄鑒權(quán)的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Spring?Cloud?+?Nacos?+?Seata整合過程(分布式事務(wù)解決方案)
Seata 是一款開源的分布式事務(wù)解決方案,致力于在微服務(wù)架構(gòu)下提供高性能和簡單易用的分布式事務(wù)服務(wù),這篇文章主要介紹了Spring?Cloud?+?Nacos?+?Seata整合過程(分布式事務(wù)解決方案),需要的朋友可以參考下2022-03-03
Java枚舉(Enum)從基礎(chǔ)到高級應(yīng)用詳解
文章詳細(xì)介紹了Java枚舉(enum)的概念、基礎(chǔ)語法、內(nèi)置方法及高級用法,強調(diào)了枚舉在提高代碼類型安全性、可讀性和維護(hù)性方面的優(yōu)勢,文中還列舉了添加字段、方法和實現(xiàn)接口等高級用法,并提供了命名規(guī)范、不可變性、異常處理等最佳實踐建議,需要的朋友可以參考下2026-05-05
細(xì)說Springcloud eureka的幾種主動下線服務(wù)的方式
這篇文章主要介紹了細(xì)說Springcloud eureka的幾種主動下線服務(wù)的方式,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-09-09
springboot 多數(shù)據(jù)源的實現(xiàn)(最簡單的整合方式)
這篇文章主要介紹了springboot 多數(shù)據(jù)源的實現(xiàn)(最簡單的整合方式),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11
Java7之forkjoin簡介_動力節(jié)點Java學(xué)院整理
Java7引入了Fork Join的概念,來更好的支持并行運算。接下來通過本文給大家分享Java7之forkjoin簡介,感興趣的朋友一起看看吧2017-06-06

