Spring?Boot中實現(xiàn)全局Token驗證的兩種方式總結(jié)
前言
在 Spring Boot 項目中,Token 驗證是保護接口安全的常見手段。如果每個接口都單獨編寫 Token 驗證邏輯,會導(dǎo)致代碼冗余且難以維護。為了解決這個問題,可以通過 攔截器(Interceptor) 或 過濾器(Filter) 實現(xiàn)全局 Token 驗證,從而統(tǒng)一處理所有接口的驗證邏輯。
本文將詳細介紹如何使用攔截器和過濾器實現(xiàn)全局 Token 驗證,并提供完整的代碼示例和最佳實踐。
一、為什么需要全局 Token 驗證?
在前后端分離的架構(gòu)中,客戶端通常通過 Token 進行身份驗證。如果每個接口都單獨驗證 Token,會導(dǎo)致以下問題:
- 代碼冗余:每個接口都需要編寫重復(fù)的驗證邏輯。
- 維護困難:當驗證邏輯需要修改時,需要修改所有相關(guān)接口。
- 容易遺漏:新增接口時可能會忘記添加驗證邏輯,導(dǎo)致安全漏洞。
通過全局 Token 驗證,可以統(tǒng)一處理所有接口的驗證邏輯,提高代碼的復(fù)用性和可維護性。
二、使用攔截器實現(xiàn)全局 Token 驗證
攔截器是 Spring MVC 提供的一種機制,可以在請求到達控制器之前或之后執(zhí)行特定的邏輯。以下是實現(xiàn)步驟:
1. 創(chuàng)建 Token 驗證攔截器
創(chuàng)建一個攔截器類,實現(xiàn) HandlerInterceptor 接口,并在 preHandle 方法中編寫 Token 驗證邏輯。
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 {
// 從請求頭中獲取 Token
String token = request.getHeader("Authorization");
// 驗證 Token
if (token == null || !isValidToken(token)) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); // 401 未授權(quán)
response.getWriter().write("Token 無效或未提供");
return false; // 中斷請求
}
return true; // 繼續(xù)執(zhí)行請求
}
// 模擬 Token 驗證邏輯
private boolean isValidToken(String token) {
// 這里可以調(diào)用具體的 Token 驗證服務(wù)
return "valid-token".equals(token);
}
}
2. 注冊攔截器
將攔截器注冊到 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. 測試攔截器
啟動項目后,訪問任意接口時,如果請求頭中沒有提供有效的 Token,則會返回 401 錯誤。
三、使用過濾器實現(xiàn)全局 Token 驗證
過濾器是 Servlet 提供的一種機制,可以在請求到達 Spring MVC 之前執(zhí)行邏輯。以下是實現(xiàn)步驟:
1. 創(chuàng)建 Token 驗證過濾器
創(chuàng)建一個過濾器類,實現(xiàn) Filter 接口,并在 doFilter 方法中編寫 Token 驗證邏輯。
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;
// 從請求頭中獲取 Token
String token = httpRequest.getHeader("Authorization");
// 驗證 Token
if (token == null || !isValidToken(token)) {
httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED); // 401 未授權(quán)
httpResponse.getWriter().write("Token 無效或未提供");
return; // 中斷請求
}
chain.doFilter(request, response); // 繼續(xù)執(zhí)行請求
}
// 模擬 Token 驗證邏輯
private boolean isValidToken(String token) {
// 這里可以調(diào)用具體的 Token 驗證服務(wù)
return "valid-token".equals(token);
}
}
2. 注冊過濾器
將過濾器注冊到 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è)置過濾器順序
return registrationBean;
}
}
3. 測試過濾器
啟動項目后,訪問任意接口時,如果請求頭中沒有提供有效的 Token,則會返回 401 錯誤。
四、攔截器 vs 過濾器
1. 攔截器的優(yōu)勢
- 與 Spring MVC 深度集成,可以訪問 Spring 的上下文和 Bean。
- 可以精確控制攔截的路徑(通過
addPathPatterns和excludePathPatterns)。 - 適合處理與業(yè)務(wù)邏輯相關(guān)的攔截(如權(quán)限驗證、日志記錄)。
2. 過濾器的優(yōu)勢
- 更底層,可以攔截所有請求(包括靜態(tài)資源)。
- 適合處理與 Servlet 相關(guān)的邏輯(如編碼設(shè)置、跨域處理)。
3. 選擇建議
- 如果需要在 Spring MVC 的上下文中處理邏輯(如依賴注入),優(yōu)先使用攔截器。
- 如果需要攔截所有請求(包括靜態(tài)資源),或者需要更底層的控制,優(yōu)先使用過濾器。
五、全局異常處理
在攔截器或過濾器中,如果驗證失敗,直接返回錯誤響應(yīng)可能會導(dǎo)致客戶端無法解析??梢酝ㄟ^全局異常處理機制統(tǒng)一返回 JSON 格式的錯誤信息。
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. 在攔截器或過濾器中拋出異常
if (token == null || !isValidToken(token)) {
throw new UnauthorizedException("Token 無效或未提供");
}
六、總結(jié)
通過攔截器或過濾器,可以輕松實現(xiàn) Spring Boot 項目中所有接口的 Token 驗證。以下是兩種方式的對比:
| 特性 | 攔截器(Interceptor) | 過濾器(Filter) |
|---|---|---|
| 集成方式 | Spring MVC 集成 | Servlet 集成 |
| 攔截范圍 | 只能攔截 Spring MVC 的請求 | 可以攔截所有請求(包括靜態(tài)資源) |
| 依賴注入 | 支持 | 不支持 |
| 適用場景 | 業(yè)務(wù)邏輯相關(guān)的攔截(如權(quán)限驗證) | 底層邏輯相關(guān)的攔截(如編碼設(shè)置) |
根據(jù)項目需求選擇合適的方式,并結(jié)合全局異常處理機制,可以構(gòu)建一個健壯且易維護的 Token 驗證系統(tǒng)。
到此這篇關(guān)于Spring Boot中實現(xiàn)全局Token驗證兩種方式的文章就介紹到這了,更多相關(guān)SpringBoot全局Token驗證方式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
mybatis中實現(xiàn)枚舉自動轉(zhuǎn)換方法詳解
在使用mybatis的時候經(jīng)常會遇到枚舉類型的轉(zhuǎn)換,下面這篇文章主要給大家介紹了關(guān)于mybatis中實現(xiàn)枚舉自動轉(zhuǎn)換的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學習或工作具有一定的參考學習價值,需要的朋友們下面來一起看看吧。2017-08-08
Java使用JNDI連接數(shù)據(jù)庫的實現(xiàn)方法
本文主要介紹了Java使用JNDI連接數(shù)據(jù)庫的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-12-12
springbooot整合dynamic?datasource數(shù)據(jù)庫密碼加密方式
這篇文章主要介紹了springbooot整合dynamic?datasource?數(shù)據(jù)庫密碼加密方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-01-01

