Spring?Boot中實(shí)現(xiàn)全局Token驗(yàn)證的兩種方式總結(jié)
前言
在 Spring Boot 項(xiàng)目中,Token 驗(yàn)證是保護(hù)接口安全的常見(jiàn)手段。如果每個(gè)接口都單獨(dú)編寫(xiě) Token 驗(yàn)證邏輯,會(huì)導(dǎo)致代碼冗余且難以維護(hù)。為了解決這個(gè)問(wèn)題,可以通過(guò) 攔截器(Interceptor) 或 過(guò)濾器(Filter) 實(shí)現(xiàn)全局 Token 驗(yàn)證,從而統(tǒng)一處理所有接口的驗(yàn)證邏輯。
本文將詳細(xì)介紹如何使用攔截器和過(guò)濾器實(shí)現(xiàn)全局 Token 驗(yàn)證,并提供完整的代碼示例和最佳實(shí)踐。
一、為什么需要全局 Token 驗(yàn)證?
在前后端分離的架構(gòu)中,客戶(hù)端通常通過(guò) Token 進(jìn)行身份驗(yàn)證。如果每個(gè)接口都單獨(dú)驗(yàn)證 Token,會(huì)導(dǎo)致以下問(wèn)題:
- 代碼冗余:每個(gè)接口都需要編寫(xiě)重復(fù)的驗(yàn)證邏輯。
- 維護(hù)困難:當(dāng)驗(yàn)證邏輯需要修改時(shí),需要修改所有相關(guān)接口。
- 容易遺漏:新增接口時(shí)可能會(huì)忘記添加驗(yàn)證邏輯,導(dǎo)致安全漏洞。
通過(guò)全局 Token 驗(yàn)證,可以統(tǒng)一處理所有接口的驗(yàn)證邏輯,提高代碼的復(fù)用性和可維護(hù)性。
二、使用攔截器實(shí)現(xiàn)全局 Token 驗(yàn)證
攔截器是 Spring MVC 提供的一種機(jī)制,可以在請(qǐng)求到達(dá)控制器之前或之后執(zhí)行特定的邏輯。以下是實(shí)現(xiàn)步驟:
1. 創(chuàng)建 Token 驗(yàn)證攔截器
創(chuàng)建一個(gè)攔截器類(lèi),實(shí)現(xiàn) HandlerInterceptor
接口,并在 preHandle
方法中編寫(xiě) Token 驗(yàn)證邏輯。
import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @Component public class TokenInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 從請(qǐng)求頭中獲取 Token String token = request.getHeader("Authorization"); // 驗(yàn)證 Token if (token == null || !isValidToken(token)) { response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); // 401 未授權(quán) response.getWriter().write("Token 無(wú)效或未提供"); return false; // 中斷請(qǐng)求 } return true; // 繼續(xù)執(zhí)行請(qǐng)求 } // 模擬 Token 驗(yàn)證邏輯 private boolean isValidToken(String token) { // 這里可以調(diào)用具體的 Token 驗(yàn)證服務(wù) return "valid-token".equals(token); } }
2. 注冊(cè)攔截器
將攔截器注冊(cè)到 Spring MVC 中,并配置需要攔截的路徑。
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class WebConfig implements WebMvcConfigurer { @Autowired private TokenInterceptor tokenInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { // 攔截所有路徑 registry.addInterceptor(tokenInterceptor) .addPathPatterns("/**") // 攔截所有接口 .excludePathPatterns("/login", "/register"); // 排除不需要攔截的路徑 } }
3. 測(cè)試攔截器
啟動(dòng)項(xiàng)目后,訪(fǎng)問(wèn)任意接口時(shí),如果請(qǐng)求頭中沒(méi)有提供有效的 Token,則會(huì)返回 401 錯(cuò)誤。
三、使用過(guò)濾器實(shí)現(xiàn)全局 Token 驗(yàn)證
過(guò)濾器是 Servlet 提供的一種機(jī)制,可以在請(qǐng)求到達(dá) Spring MVC 之前執(zhí)行邏輯。以下是實(shí)現(xiàn)步驟:
1. 創(chuàng)建 Token 驗(yàn)證過(guò)濾器
創(chuàng)建一個(gè)過(guò)濾器類(lèi),實(shí)現(xiàn) Filter
接口,并在 doFilter
方法中編寫(xiě) Token 驗(yàn)證邏輯。
import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class TokenFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpRequest = (HttpServletRequest) request; HttpServletResponse httpResponse = (HttpServletResponse) response; // 從請(qǐng)求頭中獲取 Token String token = httpRequest.getHeader("Authorization"); // 驗(yàn)證 Token if (token == null || !isValidToken(token)) { httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED); // 401 未授權(quán) httpResponse.getWriter().write("Token 無(wú)效或未提供"); return; // 中斷請(qǐng)求 } chain.doFilter(request, response); // 繼續(xù)執(zhí)行請(qǐng)求 } // 模擬 Token 驗(yàn)證邏輯 private boolean isValidToken(String token) { // 這里可以調(diào)用具體的 Token 驗(yàn)證服務(wù) return "valid-token".equals(token); } }
2. 注冊(cè)過(guò)濾器
將過(guò)濾器注冊(cè)到 Spring Boot 中,并配置需要攔截的路徑。
import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class FilterConfig { @Bean public FilterRegistrationBean<TokenFilter> tokenFilter() { FilterRegistrationBean<TokenFilter> registrationBean = new FilterRegistrationBean<>(); registrationBean.setFilter(new TokenFilter()); registrationBean.addUrlPatterns("/*"); // 攔截所有路徑 registrationBean.setOrder(1); // 設(shè)置過(guò)濾器順序 return registrationBean; } }
3. 測(cè)試過(guò)濾器
啟動(dòng)項(xiàng)目后,訪(fǎng)問(wèn)任意接口時(shí),如果請(qǐng)求頭中沒(méi)有提供有效的 Token,則會(huì)返回 401 錯(cuò)誤。
四、攔截器 vs 過(guò)濾器
1. 攔截器的優(yōu)勢(shì)
- 與 Spring MVC 深度集成,可以訪(fǎng)問(wèn) Spring 的上下文和 Bean。
- 可以精確控制攔截的路徑(通過(guò)
addPathPatterns
和excludePathPatterns
)。 - 適合處理與業(yè)務(wù)邏輯相關(guān)的攔截(如權(quán)限驗(yàn)證、日志記錄)。
2. 過(guò)濾器的優(yōu)勢(shì)
- 更底層,可以攔截所有請(qǐng)求(包括靜態(tài)資源)。
- 適合處理與 Servlet 相關(guān)的邏輯(如編碼設(shè)置、跨域處理)。
3. 選擇建議
- 如果需要在 Spring MVC 的上下文中處理邏輯(如依賴(lài)注入),優(yōu)先使用攔截器。
- 如果需要攔截所有請(qǐng)求(包括靜態(tài)資源),或者需要更底層的控制,優(yōu)先使用過(guò)濾器。
五、全局異常處理
在攔截器或過(guò)濾器中,如果驗(yàn)證失敗,直接返回錯(cuò)誤響應(yīng)可能會(huì)導(dǎo)致客戶(hù)端無(wú)法解析??梢酝ㄟ^(guò)全局異常處理機(jī)制統(tǒng)一返回 JSON 格式的錯(cuò)誤信息。
1. 定義統(tǒng)一響應(yīng)格式
public class ApiResponse { private boolean status; private int code; private String message; // 構(gòu)造方法和 Getter/Setter 省略 }
2. 全局異常處理器
import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestControllerAdvice; @RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(UnauthorizedException.class) @ResponseStatus(HttpStatus.UNAUTHORIZED) public ApiResponse handleUnauthorizedException(UnauthorizedException e) { return new ApiResponse(false, 401, e.getMessage()); } }
3. 在攔截器或過(guò)濾器中拋出異常
if (token == null || !isValidToken(token)) { throw new UnauthorizedException("Token 無(wú)效或未提供"); }
六、總結(jié)
通過(guò)攔截器或過(guò)濾器,可以輕松實(shí)現(xiàn) Spring Boot 項(xiàng)目中所有接口的 Token 驗(yàn)證。以下是兩種方式的對(duì)比:
特性 | 攔截器(Interceptor) | 過(guò)濾器(Filter) |
---|---|---|
集成方式 | Spring MVC 集成 | Servlet 集成 |
攔截范圍 | 只能攔截 Spring MVC 的請(qǐng)求 | 可以攔截所有請(qǐng)求(包括靜態(tài)資源) |
依賴(lài)注入 | 支持 | 不支持 |
適用場(chǎng)景 | 業(yè)務(wù)邏輯相關(guān)的攔截(如權(quán)限驗(yàn)證) | 底層邏輯相關(guān)的攔截(如編碼設(shè)置) |
根據(jù)項(xiàng)目需求選擇合適的方式,并結(jié)合全局異常處理機(jī)制,可以構(gòu)建一個(gè)健壯且易維護(hù)的 Token 驗(yàn)證系統(tǒng)。
到此這篇關(guān)于Spring Boot中實(shí)現(xiàn)全局Token驗(yàn)證兩種方式的文章就介紹到這了,更多相關(guān)SpringBoot全局Token驗(yàn)證方式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
mybatis中實(shí)現(xiàn)枚舉自動(dòng)轉(zhuǎn)換方法詳解
在使用mybatis的時(shí)候經(jīng)常會(huì)遇到枚舉類(lèi)型的轉(zhuǎn)換,下面這篇文章主要給大家介紹了關(guān)于mybatis中實(shí)現(xiàn)枚舉自動(dòng)轉(zhuǎn)換的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起看看吧。2017-08-08SpringBoot?Http遠(yuǎn)程調(diào)用的方法
這篇文章主要為大家詳細(xì)介紹了SpringBoot?Http遠(yuǎn)程調(diào)用的方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-08-08Java使用JNDI連接數(shù)據(jù)庫(kù)的實(shí)現(xiàn)方法
本文主要介紹了Java使用JNDI連接數(shù)據(jù)庫(kù)的實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-12-12Java解析xml文件遇到特殊符號(hào)異常的情況(處理方案)
這篇文章主要介紹了Java解析xml文件遇到特殊符號(hào)&會(huì)出現(xiàn)異常的解決方案,實(shí)現(xiàn)思路很簡(jiǎn)單通過(guò)在讀取xml文件使用SAX解析前讀取reader,具體實(shí)現(xiàn)方法及示例代碼跟隨小編一起看看吧2021-05-05springbooot整合dynamic?datasource數(shù)據(jù)庫(kù)密碼加密方式
這篇文章主要介紹了springbooot整合dynamic?datasource?數(shù)據(jù)庫(kù)密碼加密方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01