# 驗證API key & IP白名單 ### 前言   在後端 API 設計中,除了基本的帳號密碼或 Token 驗證外,常見還會搭配 **API Key 驗證** 與 **IP 白名單控管**,用來加強系統的安全性。 * **API Key 驗證**:確保呼叫 API 的來源是合法的系統。 * **IP 白名單**:限制只有特定來源 IP 才能存取服務。 這種設計常見於: * 系統對系統(B2B)串接 * 金流 / 第三方服務 * 內部微服務保護 ### 實作   本範例使用 Spring Boot 的 `OncePerRequestFilter` 來攔截請求,並在進入 Controller 前進行驗證。 #### 1.建立 `AuthenticationFilter`: * 攔截特定路徑(如 `/api`、`/系統名稱前綴`) * 驗證 Header 中的 API Key * 檢查 Client IP 是否在白名單 ```java @Component @Slf4j public class AuthenticationFilter extends OncePerRequestFilter { } ``` #### 2.設定值注入 透過 `@Value` 從設定檔讀取: ```java @Value("${test.api.key}") private String testApiKey; @Value("${test.api.allowlist}") private String testIpAddressAllowlist; ``` 在 `application.properties` 設定檔放入值: ```properties test.api.allowlist=放白名單IP test.api.key=放API KEY ``` #### 3. 過濾邏輯 ```java final boolean shouldCheckPermission = request.getRequestURI().startsWith("/api") || request.getRequestURI().startsWith("/其他路徑"); ``` :::info 只針對特定 API 做保護,避免影響其他公開 API。 ::: #### 4. API Key 驗證 ```java public boolean isAuthorized(String authorization) { if (authorization == null || authorization.isEmpty()) { return false; } return authorization.equals("TEST-API-KEY " + testApiKey); } ``` 📌 Header 格式: ``` Authorization: Test-API-KEY your-api-key ``` #### 5. IP 白名單驗證 ```java private boolean isAllowedIp(String clientIp) { if (testIpAddressAllowlist == null || testIpAddressAllowlist.isEmpty()) { return false; } return testIpAddressAllowlist.equals(clientIp); } ``` 📌 Client IP 取得: ```java String clientIp = getClientIp(request); ``` (通常會處理 `X-Forwarded-For`) #### 6. 驗證判斷 ```java if (shouldCheckPermission && !isAuthorized && !isAllowedIp) { response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); return; } ``` :::info 📌 條件說明: * 只要 **API Key 或 IP 任一符合** 就放行 * 兩者都不符合才拒絕 ※在真正的專案中,通常會是有條件的符合,而不會是任一符合就放行,範例只是為了簡單,才這樣寫。 ::: ### 總結   這個實作提供了一個簡單但實用的安全機制: * 實作簡單,容易導入 * 適合系統對系統驗證 * 可快速阻擋未授權請求