# 驗證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 任一符合** 就放行
* 兩者都不符合才拒絕
※在真正的專案中,通常會是有條件的符合,而不會是任一符合就放行,範例只是為了簡單,才這樣寫。
:::
### 總結
這個實作提供了一個簡單但實用的安全機制:
* 實作簡單,容易導入
* 適合系統對系統驗證
* 可快速阻擋未授權請求