

AWS Mainframe Modernization Service （受管執行期環境體驗） 不再開放給新客戶使用。對於與 AWS Mainframe Modernization Service （受管執行期環境體驗） 類似的功能，探索 AWS Mainframe Modernization Service （自我管理體驗）。現有客戶可以繼續正常使用該服務。如需詳細資訊，請參閱[AWS 大型主機現代化可用性變更](https://docs.aws.amazon.com/m2/latest/userguide/mainframe-modernization-availability-change.html)。

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 設定 Gapwalk 應用程式的安全性
<a name="ba-runtime-security"></a>

下列主題說明如何保護 Gapwalk 應用程式。

您有責任提供正確的組態，以確保使用適用於大型主機架構的 AWS Transform 是安全的。

預設會停用所有與安全相關的功能。若要啟用身分驗證 （以及 CSRF、XSS、CSP 等），請將 `gapwalk-application.security` 設定為 `enabled`，並將 `gapwalk-application.security.identity`設定為 `oauth`。

**Topics**
+ [設定 Gapwalk 應用程式的 URI 可存取性](ba-runtime-filteringURIs.md)
+ [設定 Gapwalk 應用程式的身分驗證](ba-runtime-auth.md)
+ [設定大型主機執行期 AWS 轉換的速率限制](ba-runtime-rate-limiting.md)

# 設定 Gapwalk 應用程式的 URI 可存取性
<a name="ba-runtime-filteringURIs"></a>

本主題說明如何設定 Gapwalk 應用程式的 URIs 篩選。此功能不需要身分提供者 (IdP)。

若要封鎖 URIs 清單，請將以下兩行新增至現代化應用程式的 ，以您想要封鎖`application-main.yml`的 URIs 取代 *URI-1*、*URI-2* 等。

```
gapwalk-application.security.filterURIs: enabled
gapwalk-application.security.blockedURIs: URI-1, URI-2, URI-3
```

# 設定 Gapwalk 應用程式的身分驗證
<a name="ba-runtime-auth"></a>

若要為您的 Gapwalk 應用程式設定 OAuth2 身分驗證，您需要設定身分提供者 (IdP)，並將其與您的應用程式整合。本指南涵蓋使用 Amazon Cognito 或 Keycloak 作為 IdP 的步驟。使用 Amazon Cognito，您可以使用 Cognito 使用者集區詳細資訊更新應用程式的組態檔案。使用 Keycloak，您可以根據使用者指派的角色來控制對應用程式 APIs 和資源的存取。

**Topics**
+ [使用 Amazon Cognito 設定 Gapwalk OAuth2 身分驗證](ba-runtime-auth-cognito.md)
+ [使用 Keycloak 設定 Gapwalk OAuth2 身分驗證](ba-runtime-auth-keycloak.md)

# 使用 Amazon Cognito 設定 Gapwalk OAuth2 身分驗證
<a name="ba-runtime-auth-cognito"></a>

本主題說明如何使用 Amazon Cognito 做為身分提供者 (IdP)，為 Gapwalk 應用程式設定 OAuth2 身分驗證。

## 先決條件
<a name="ba-runtime-auth-cognito-prereq"></a>

在本教學課程中，我們將使用 Amazon Cognito 作為 IdP，並使用 PlanetDemo 作為現代化專案。

您可以使用任何其他外部身分提供者。ClientRegistration 資訊必須從您的 IdP 取得，且為 Gapwalk 身分驗證的必要項目。如需詳細資訊，請參閱 [Amazon Cognito 開發人員指南](https://docs.aws.amazon.com/cognito/latest/developerguide/)。

**ClientRegistration 資訊：**

client-id  
ClientRegistration 的 ID。在我們的範例中，它會是 PlanetsDemo。

client-secret  
您的用戶端秘密。

授權端點  
授權伺服器的授權端點 URI。

字符端點  
授權伺服器的字符端點 URI。

jwks 端點  
用來取得 JSON Web 金鑰 (JWK) 的 URI，其中包含驗證授權伺服器發出之 JSON Web 簽章的金鑰。

重新導向 URI  
如果授予存取權，授權伺服器重新導向最終使用者的 URI。

## Amazon Cognito 設定
<a name="cog-setup"></a>

首先，我們將建立和設定 Amazon Cognito 使用者集區和使用者，我們將將其與部署的 Gapwalk 應用程式搭配使用，用於測試目的。

**注意**  
如果您使用的是另一個 IdP，您可以略過此步驟。

**建立使用者集區**

1. 前往 中的 Amazon Cognito AWS 管理主控台 ，並使用您的 AWS 登入資料進行驗證。

1. 選擇 **User Pools** (使用者集區)。

1. 選擇 **Create a user pool (建立使用者集區)**。

1. 在**設定登入體驗**中，保留 **Cognito 使用者集區**預設提供者類型。您可以選擇一或多個 **Cognito 使用者集區登入選項**；現在，請選擇**使用者名稱**，然後選擇**下一步**。  
![\[alt_text\]](http://docs.aws.amazon.com/zh_tw/m2/latest/userguide/images/cog-auth-provider.png)

1. 在**設定安全需求**中，選擇**無 MFA**，保留預設值並停用**多重要素驗證**，然後選擇**下一步**。  
![\[alt_text\]](http://docs.aws.amazon.com/zh_tw/m2/latest/userguide/images/cog-sec-requirements.png)

1. 做為安全措施，請停用**啟用自我註冊**，然後選擇**下一步**。  
![\[alt_text\]](http://docs.aws.amazon.com/zh_tw/m2/latest/userguide/images/cog-config-sign-up.png)

1. 選擇**使用 Cognito 傳送電子郵件**，然後選擇**下一步**。  
![\[alt_text\]](http://docs.aws.amazon.com/zh_tw/m2/latest/userguide/images/cog-email.png)

1. 在**整合您的應用程式**中，指定使用者集區的名稱。在**託管身分驗證頁面**中，選擇**使用 Cognito 託管 UI**。  
![\[alt_text\]](http://docs.aws.amazon.com/zh_tw/m2/latest/userguide/images/cog-domain.png)

1. 為了簡化，在**網域**中，選擇**使用 Cognito 網域**，然後輸入網域字首，例如 `https://planetsdemo`。示範應用程式必須新增為用戶端。

   1. 在**初始應用程式用戶端**中，選擇**機密用戶端**。輸入應用程式用戶端名稱，例如 **planetsdemo**，然後選擇**產生用戶端秘密**。

   1. 在**允許的回呼 URL** 中，輸入 URL 以在身分驗證後將使用者重新導向至 。URL 必須以 結尾`/login/oauth2/code/cognito`。例如，對於我們的應用程式和後端 Gapwalk 和 BAC 應用程式：

      ```
      http://localhost:8080/bac
            http://localhost:8080/bac/login/oauth2/code/cognito
            http://localhost:8080/gapwalk-application
            http://localhost:8080/gapwalk-application/login/oauth2/code/cognito
            http://localhost:8080/planetsdemo
            http://localhost:8080/planetsdemo/login/oauth2/code/cognito
      ```

      您可以稍後編輯 URL。  
![\[alt_text\]](http://docs.aws.amazon.com/zh_tw/m2/latest/userguide/images/cog-urls.png)

   1. 在**允許的登出 URLs** 中，輸入您希望 Amazon Cognito 在應用程式將使用者登出時重新導向至的登出頁面 URL。例如，對於後端 Gapwalk 和 BAC 應用程式：

      ```
      http://localhost:8080/bac/logout
      http://localhost:8080/gapwalk-application/logout
      http://localhost:8080/planetsdemo/logout
      ```

      您可以稍後編輯 URL。

   1. 在**進階應用程式用戶端設定**和**屬性讀取和寫入許可**區段中保留預設值。

   1. 選擇**下一步**。

1. 在**檢閱和建立**中，驗證您的選擇，然後選擇**建立使用者集區**。

如需詳細資訊，請參閱[建立使用者集區](https://docs.aws.amazon.com/cognito/latest/developerguide/tutorial-create-user-pool.html)。

**使用者建立**

由於自我註冊已停用，請建立 Amazon Cognito 使用者。在 中導覽至 Amazon Cognito AWS 管理主控台。選擇您建立的使用者集區，然後在**使用者**中選擇**建立使用者**。

在**使用者資訊**中，選擇**傳送電子郵件邀請**、輸入使用者名稱和電子郵件地址，然後選擇**產生密碼**。選擇 **Create user** (建立使用者)。

**角色建立**

在**群組**索引標籤中，建立 3 個群組 (SUPER\$1ADMIN、ADMIN 和 USER)，並將您的使用者與其中一或多個群組建立關聯。這些角色稍後會由 Gapwalk 應用程式映射至 ROLE\$1SUPER\$1ADMIN、ROLE\$1ADMIN 和 ROLE\$1USER，以便能夠存取一些受限的 API REST 呼叫。

應用程式實作階層式scope-to-role映射，可與多個 OAuth2 身分提供者搭配使用。當 Cognito 發出的 JWT 權杖用於資源伺服器授權時，權杖中定義的範圍會自動對應至對應的角色。

## 將 Amazon Cognito 整合到 Gapwalk 應用程式
<a name="integrate-cognito"></a>

現在您的 Amazon Cognito 使用者集區和使用者已準備好，請移至現代化應用程式的 `application-main.yml` 檔案，並新增下列程式碼：

```
gapwalk-application.security: enabled
gapwalk-application.security.identity: oauth
gapwalk-application.security.issuerUri: https://cognito-idp.<region-id>.amazonaws.com/<pool-id>
gapwalk-application.security.domainName: <your-cognito-domain>

spring:
  security:
    oauth2:
      client:
        registration:
          cognito:
            client-id: <client-id>
            client-name: <client-name>
            client-secret: <client-secret>
            provider: cognito
            authorization-grant-type: authorization_code
            scope: openid
            redirect-uri: "<redirect-uri>"
        provider:
          cognito:
            issuer-uri: ${gapwalk-application.security.issuerUri}
            authorization-uri: ${gapwalk-application.security.domainName}/oauth2/authorize
            jwk-set-uri: ${gapwalk-application.security.issuerUri}/.well-known/jwks.json
            token-uri: ${gapwalk-application.security.domainName}/oauth2/token
            user-name-attribute: username
      resourceserver:
        jwt:
          jwk-set-uri: ${gapwalk-application.security.issuerUri}/.well-known/jwks.json
```

依照說明取代下列預留位置：

1. 前往 中的 Amazon Cognito AWS 管理主控台 ，並使用您的 AWS 登入資料進行驗證。

1. 選擇**使用者集**區，然後選擇您建立的使用者集區。您可以在使用者*集區 ID 中找到您的 pool-*id。 ****

1. 選擇您可以在其中找到*your-cognito-domain* **的應用程式整合**，然後前往**應用程式用戶端和分析**，然後選擇您的應用程式。

1. 在**應用程式用戶端：yourApp** 中，您可以找到 *client-name* 、 *client-id* 和 *client-secret* (**顯示用戶端秘密**)。

1. *region-id* 對應至您建立 Amazon Cognito 使用者和使用者集區的 AWS 區域 ID。範例：`eu-west-3`。

1. 針對 *redirect-uri*，輸入您為**允許回呼 URL** 指定的 URI。在我們的範例中，它是 `http://localhost:8080/planetsdemo/login/oauth2/code/cognito`。

您現在可以部署您的 Gapwalk 應用程式，並使用先前建立的使用者來登入您的應用程式。

# 使用 Keycloak 設定 Gapwalk OAuth2 身分驗證
<a name="ba-runtime-auth-keycloak"></a>

本主題說明如何使用 Keycloak 做為身分提供者 (IdP)，為 Gapwalk 應用程式設定 OAuth2 身分驗證。在本教學課程中，我們使用 Keycloak 24.0.0。

## 先決條件
<a name="ba-runtime-auth-keycloak-prereq"></a>
+ [Keycloak](https://www.keycloak.org/)
+ Gapwalk 應用程式

## Keycloak 設定
<a name="keycloak-setup"></a>

1. 前往 Web 瀏覽器中的 Keycloak 儀表板。預設登入資料為 admin/admin。前往左上角導覽列，並建立名稱為 的領域**demo**，如下圖所示。  
![\[alt_text\]](http://docs.aws.amazon.com/zh_tw/m2/latest/userguide/images/ba-runtime-auth-keycloak_2.png)

1. 建立名稱為 的用戶端**app-demo**。  
![\[User interface for creating a new client in an authentication management system.\]](http://docs.aws.amazon.com/zh_tw/m2/latest/userguide/images/ba-runtime-auth-keycloak_3.jpg)

   `localhost:8080` 將 取代為您 Gapwalk 應用程式的地址  
![\[alt_text\]](http://docs.aws.amazon.com/zh_tw/m2/latest/userguide/images/ba-runtime-auth-keycloak_4.png)  
![\[alt_text\]](http://docs.aws.amazon.com/zh_tw/m2/latest/userguide/images/ba-runtime-auth-keycloak_5.png)

1. 若要取得您的用戶端秘密，請選擇**用戶端**，然後選擇**應用程式示範**，然後選擇**登入**資料。  
![\[alt_text\]](http://docs.aws.amazon.com/zh_tw/m2/latest/userguide/images/ba-runtime-auth-keycloak_6.jpg)

1. 選擇**用戶端**，然後選擇**用戶端範圍**，然後選擇**新增預先定義的映射器**。選擇**領域角色**。  
![\[alt_text\]](http://docs.aws.amazon.com/zh_tw/m2/latest/userguide/images/ba-runtime-auth-keycloak_7.jpg)

1. 使用下圖所示的組態編輯您的領域角色。  
![\[alt_text\]](http://docs.aws.amazon.com/zh_tw/m2/latest/userguide/images/ba-runtime-auth-keycloak_8.jpg)

1. 記住定義的**權杖宣告名稱**。在 `gapwalk-application.security.claimGroupName` 屬性的 Gapwalk 設定定義中，您將需要此值。  
![\[alt_text\]](http://docs.aws.amazon.com/zh_tw/m2/latest/userguide/images/ba-runtime-auth-keycloak_9.jpg)

1. 選擇 **Realms 角色**，並建立 3 個角色：**SUPER\$1ADMIN**、 **ADMIN**和 **USER**。這些角色稍後會由 Gapwalk 應用程式映射至 `ROLE_ADMIN`、 `ROLE_SUPER_ADMIN`和 ，以便能夠存取一些受限`ROLE_USER`的 API REST 呼叫。  
![\[alt_text\]](http://docs.aws.amazon.com/zh_tw/m2/latest/userguide/images/ba-runtime-auth-keycloak_10.jpg)

## 將 Keycloak 整合到 Gapwalk 應用程式
<a name="gapwalk-setup"></a>

編輯 `application-main.yml`，如下所示：

```
gapwalk-application.security: enabled
gapwalk-application.security.identity: oauth
gapwalk-application.security.issuerUri: http://<KEYCLOAK_SERVER_HOSTNAME>/realms/<YOUR_REALM_NAME>
gapwalk-application.security.claimGroupName: "keycloak:groups"

gapwalk-application.security.userAttributeName: "preferred_username"
# Use "username" for cognito, 
#     "preferred_username" for keycloak
#      or any other string

spring:
  security:
    oauth2:
      client:
        registration:
          demo:
            client-id: <YOUR_CLIENT_ID>
            client-name: Demo App
            client-secret: <YOUR_CLIENT_SECRET>
            provider: keycloak
            authorization-grant-type: authorization_code
            scope: openid
            redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}"
        provider:
          keycloak:
            issuer-uri: ${gapwalk-application.security.issuerUri}
            authorization-uri: ${gapwalk-application.security.issuerUri}/protocol/openid-connect/auth
            jwk-set-uri: ${gapwalk-application.security.issuerUri}/protocol/openid-connect/certs
            token-uri: ${gapwalk-application.security.issuerUri}/protocol/openid-connect/token
            user-name-attribute: ${gapwalk-application.security.userAttributeName}
      resourceserver:
        jwt:
          jwk-set-uri: ${gapwalk-application.security.issuerUri}/protocol/openid-connect/certs
```

將 *<KEYCLOAK\$1SERVER\$1HOSTNAME>*、*<YOUR\$1REALM\$1NAME>*、*<YOUR\$1CLIENT\$1ID>* 和 *<YOUR\$1CLIENT\$1SECRET>* 取代為您的 Keycloak 伺服器主機名稱、您的領域名稱、您的用戶端 ID 和您的用戶端密碼。

# 設定大型主機執行期 AWS 轉換的速率限制
<a name="ba-runtime-rate-limiting"></a>

AWS 大型主機執行期的轉換包含內建速率限制功能，可保護 gapwalk 應用程式免於過度請求和潛在的濫用。速率限制系統使用權杖儲存貯體演算法來提供高載容量和持續速率限制。

**Topics**
+ [速率限制概觀](#ba-runtime-rate-limiting-overview)
+ [組態屬性](#ba-runtime-rate-limiting-config)
+ [啟用速率限制](#ba-runtime-rate-limiting-enable)
+ [用戶端識別](#ba-runtime-rate-limiting-client-id)
+ [速率限制標頭](#ba-runtime-rate-limiting-headers)
+ [記憶體管理](#ba-runtime-rate-limiting-memory)

## 速率限制概觀
<a name="ba-runtime-rate-limiting-overview"></a>

速率限制系統提供下列功能：

**權杖儲存貯體演算法**  
+ 允許爆量流量達到設定的爆量容量
+ 根據每分鐘請求，以穩定速率補充字符
+ 提供順暢的速率限制，而不會封鎖合法流量峰值

**用戶端識別**  
+ 使用代理支援依 IP 地址識別用戶端
+ 支援 X-Forwarded-For 和 X-Real-IP 標頭
+ 處理負載平衡器和反向代理案例

**自動記憶體管理**  
+ 自動清除過期的速率限制儲存貯體
+ 可設定的清除間隔和到期時間
+ 防止長時間執行應用程式中的記憶體流失

**HTTP 整合**  
+ 超過限制時傳回 HTTP 429 （太多請求）
+ 在回應中包含標準速率限制標頭
+ 提供用戶端的重試後資訊

## 組態屬性
<a name="ba-runtime-rate-limiting-config"></a>

在 `application-main.yaml` 檔案中設定速率限制：

```
gapwalk:
  ratelimiting:
    enabled: true                                        # Enable/disable rate limiting
    requestsPerMinute: 1000                              # Sustained rate limit per minute
    burstCapacity: 1500                                  # Maximum burst requests allowed
    includeHeaders: true                                 # Include X-RateLimit-* headers
    cleanupIntervalMinutes: 5                            # Cleanup interval for expired buckets
    bucketExpiryHours: 1                                 # Hours after which unused buckets expire
    errorMessage: "Too many requests. Try again later."  # Custom error message
    whitelistIps: ""                                     # Comma-separated IPs to bypass limiting
    perEndpointLimiting: false                           # Apply limits per endpoint (not implemented)
```

### 屬性描述
<a name="ba-runtime-rate-limiting-config-properties"></a>

**已啟用**  
主要切換以啟用或停用速率限制功能。預設：`false`

**requestsPerMinute**  
允許持續速率限制的每分鐘請求數。這表示字符重新填充率。預設：`1000`

**burstCapacity**  
在套用速率限制之前，爆量中允許的請求數量上限。應高於 `requestsPerMinute`以允許流量尖峰。預設：`1500`

**includeHeaders**  
是否要在 HTTP 回應中包含標準速率限制標頭 (`X-RateLimit-Limit`、`X-RateLimit-Remaining`、`X-RateLimit-Reset`)。預設：`true`

**cleanupIntervalMinutes**  
自動清除過期速率限制儲存貯體之間的間隔，以分鐘為單位。有助於防止記憶體洩漏。預設：`5`

**bucketExpiryHours**  
未使用的費率限制儲存貯體視為過期且符合清除資格的時數。預設：`1`

**errorMessage**  
超過速率限制時，在 JSON 回應中傳回的自訂錯誤訊息。預設：`"Too many requests. Try again later."`

**whitelistIps**  
以逗號分隔的 IP 地址清單，完全略過速率限制。適用於運作狀態檢查或信任的系統。預設：`empty`

**perEndpointLimiting**  
是否針對每個端點套用個別的速率限制，而不是僅針對每個用戶端套用個別的速率限制。目前未實作。預設：`false`

## 啟用速率限制
<a name="ba-runtime-rate-limiting-enable"></a>

若要使用預設設定啟用速率限制：

```
gapwalk:
  ratelimiting:
    enabled: true
```

## 用戶端識別
<a name="ba-runtime-rate-limiting-client-id"></a>

速率限制系統會使用下列優先順序來識別用戶端：

1. **X-Forwarded-For 標頭** （如果以逗號分隔，則為第一個 IP)

1. **X-Real-IP 標頭**

1. 來自 HTTP 請求的**遠端地址** 

這可確保應用程式落後時適當的用戶端識別：
+ 負載平衡器
+ 反向代理
+ CDNs
+ API 閘道

### 用戶端識別範例
<a name="ba-runtime-rate-limiting-client-id-example"></a>

```
# Direct connection
Client IP: 192.168.1.100

# Behind load balancer with X-Forwarded-For
X-Forwarded-For: 203.0.113.45, 192.168.1.100
Client IP: 203.0.113.45 (first IP used)

# Behind reverse proxy with X-Real-IP
X-Real-IP: 203.0.113.45
Client IP: 203.0.113.45
```

## 速率限制標頭
<a name="ba-runtime-rate-limiting-headers"></a>

啟用 `includeHeaders` 時，下列標頭會新增至 HTTP 回應：

**X-RateLimit-Limit**  
用戶端的速率限制上限 （每分鐘請求數）

**X-RateLimit-Remaining**  
目前速率限制時段中剩餘的請求數量

**X-RateLimit-Reset**  
速率限制時段重設的時間 (Unix 時間戳記）

### 回應標頭範例
<a name="ba-runtime-rate-limiting-headers-example"></a>

```
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 847
X-RateLimit-Reset: 1640995200
```

### 超出速率限制的回應
<a name="ba-runtime-rate-limiting-headers-exceeded"></a>

超過速率限制時，系統會傳回：

**HTTP 狀態**  
429 太多請求

**內容類型**  
application/json

**重試後**  
重試前要等待的秒數

```
{
  "error": "Rate limit exceeded",
  "message": "Too many requests. Try again later.",
  "retryAfter": 60,
  "timestamp": 1640995140000
}
```

## 記憶體管理
<a name="ba-runtime-rate-limiting-memory"></a>

速率限制系統會自動管理記憶體，以防止長時間執行的應用程式發生洩漏：

**自動清除**  
+ 每分鐘執行`cleanupIntervalMinutes`一次
+ 移除未使用的儲存貯體數`bucketExpiryHours`小時
+ 記錄用於監控的清除活動

**記憶體效率**  
+ 使用並行資料結構確保執行緒安全
+ 建立延遲儲存貯體 （僅在需要時）
+ 有效率的字符儲存貯體實作

### 監控清除活動
<a name="ba-runtime-rate-limiting-memory-monitoring"></a>

檢查清除訊息的日誌：

```
INFO  RateLimitingService - Cleaned up 15 expired rate limiting buckets
```