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

