Class ApiKeyAuthenticationFilter
java.lang.Object
org.springframework.web.filter.GenericFilterBean
org.springframework.web.filter.OncePerRequestFilter
io.leandev.appfuse.security.auth.ApiKeyAuthenticationFilter
- All Implemented Interfaces:
jakarta.servlet.Filter, org.springframework.beans.factory.Aware, org.springframework.beans.factory.BeanNameAware, org.springframework.beans.factory.DisposableBean, org.springframework.beans.factory.InitializingBean, org.springframework.context.EnvironmentAware, org.springframework.core.env.EnvironmentCapable, org.springframework.web.context.ServletContextAware
public class ApiKeyAuthenticationFilter
extends org.springframework.web.filter.OncePerRequestFilter
API key 認證 filter(ADR-025 決策五)
供做不了 token exchange 的外部系統以靜態 key 直接呼叫 API。它是同一個服務帳號身分的
第二種憑證呈遞,不是繞過既有機制的旁路——認證成功後放進 SecurityContext 的就是同一個
AuthPrincipal,因而走完全相同的權限鏈;租戶亦由既有的
UserDetailsTenantIdResolver(CompositeTenantIdResolver.withDefaults() 已含)自主體解析,
不需要任何額外接線。
三條刻意的行為
① 無標頭即完全不介入。 不是本 filter 的請求原樣往下走(bearer token 路徑不受影響)。
② 驗證失敗不自己回 401,只是不設認證。 交由 chain 的 anyRequest().authenticated()
與既有的 bearer entry point 統一回應——錯誤形狀因而與其他認證失敗一致,且本 filter 不需要
知道消費端選了哪種錯誤方言。這仍是 fail-closed:不設認證 ≠ 放行。
③ 只接受非互動主體。 真人帳號不得以 api-key 呈遞(與 M2M token 端點的資格判定同一條線)。
撤銷
停用主體(enabled=false)或清除其 key 即刻失效——這正是相對 JWT 的優勢:無需等
token 過期,也不需要黑名單。每個請求都會重新查找與檢查。
組合
jar 不做 autoconfiguration;由消費端在 filter chain 註冊,且預設不註冊(ADR-025 決策五: 未設定即該路徑不存在)。應置於 bearer 驗證之前。
-
Field Summary
FieldsFields inherited from class org.springframework.web.filter.OncePerRequestFilter
ALREADY_FILTERED_SUFFIXFields inherited from class org.springframework.web.filter.GenericFilterBean
logger -
Constructor Summary
ConstructorsConstructorDescriptionApiKeyAuthenticationFilter(ApiKeyPrincipalLookup principalLookup) 以預設標頭(DEFAULT_HEADER)建立ApiKeyAuthenticationFilter(ApiKeyPrincipalLookup principalLookup, String headerName) -
Method Summary
Modifier and TypeMethodDescriptionprotected voiddoFilterInternal(jakarta.servlet.http.HttpServletRequest request, jakarta.servlet.http.HttpServletResponse response, jakarta.servlet.FilterChain filterChain) Methods inherited from class org.springframework.web.filter.OncePerRequestFilter
doFilter, doFilterNestedErrorDispatch, getAlreadyFilteredAttributeName, isAsyncDispatch, isAsyncStarted, shouldNotFilter, shouldNotFilterAsyncDispatch, shouldNotFilterErrorDispatchMethods inherited from class org.springframework.web.filter.GenericFilterBean
addRequiredProperty, afterPropertiesSet, createEnvironment, destroy, getEnvironment, getFilterConfig, getFilterName, getServletContext, init, initBeanWrapper, initFilterBean, setBeanName, setEnvironment, setServletContext
-
Field Details
-
DEFAULT_HEADER
-
-
Constructor Details
-
ApiKeyAuthenticationFilter
以預設標頭(DEFAULT_HEADER)建立- Parameters:
principalLookup- key → 主體的查找 SPI
-
ApiKeyAuthenticationFilter
- Parameters:
principalLookup- key → 主體的查找 SPIheaderName- API key 的請求標頭名(消費端慣例)
-
-
Method Details
-
doFilterInternal
protected void doFilterInternal(jakarta.servlet.http.HttpServletRequest request, jakarta.servlet.http.HttpServletResponse response, jakarta.servlet.FilterChain filterChain) throws jakarta.servlet.ServletException, IOException - Specified by:
doFilterInternalin classorg.springframework.web.filter.OncePerRequestFilter- Throws:
jakarta.servlet.ServletExceptionIOException
-