---
# System prepended metadata

title: 設定 Keycloak LINE 登入
tags: [chatgpt]

---

# 設定 Keycloak LINE 登入

[TOC]

###### tags: `chatgpt`

---

## 如何在 Keycloak 設定 LINE Login 使其支援 Open ID

以下是在 Keycloak 中設定 LINE Login 以支援 OpenID 的步驟：

1. 登入 Keycloak，選擇要添加 LINE Login 的 Realm，並點選 "Clients" 。

2. 在 "Clients" 頁面中點選 "Create" 以新增一個新的客戶端。

3. 在新的客戶端創建頁面中輸入 "Client ID"，例如 "line-login"，並在 "Client Protocol" 中選擇 "openid-connect"。

4. 設定 "Valid Redirect URIs" 為您要重定向回的 URL。您可以指定多個 URI，每行一個。例如，如果您希望在成功登錄後將用戶重定向到 `https://example.com`，則輸入 **`https://example.com/*`**。

5. 設定 "Base URL" 為您的 LINE Login 服務的基本 URL。例如，如果您在 LINE Login 中的 Channel ID 為 "123456"，則 Base URL 為 **`https://access.line.me`**。

6. 在 "Client Scopes" 中，將 "openid" 添加到 "Assigned Default Client Scopes"。

7. 當您完成上述步驟後，按 "Save" 以創建新的客戶端。

8. 點選 "Credentials" 頁面，將 "Client ID" 和 "Client Secret" 複製到您的應用程式中，以便使用 LINE Login。

9. 現在，您可以使用 LINE Login 作為 OpenID Connect 提供者來驗證用戶。

以上是在 Keycloak 中設定 LINE Login 以支援 OpenID 的步驟。完成上述步驟後，您的應用程式應該可以使用 LINE Login 來驗證用戶，同時也可以從 Keycloak 獲得用戶的 OpenID Connect 資訊。

## 需要提供 JWKS 給 Keycloak 嗎

是的，當您在 Keycloak 中設定使用外部 OpenID Connect 提供者時，通常需要提供該提供者的 JSON Web Key Set (JWKS)。

JWKS 是包含該提供者的公鑰和其他有關密鑰的元數據的 JSON 文件。當您在 Keycloak 中設定使用外部 OpenID Connect 提供者時，Keycloak 會使用該 JWKS 文件驗證用戶令牌和其他加密資料。

若您要使用 LINE Login 作為 OpenID Connect 提供者，您需要提供 LINE Login 的 JWKS 給 Keycloak。要獲取 LINE Login 的 JWKS，您可以在 LINE Login 控制台中找到。在控制台中，點選 "Channel settings"，然後在 "Web settings" 中找到 "JSON Web Key Set (JWKS)"。

複製 JWKS，然後將其粘貼到 Keycloak 中 OpenID Connect 提供者的相應欄位中。完成後，您的 Keycloak 應用程式應該能夠使用 LINE Login 作為 OpenID Connect 提供者來驗證用戶。

## Spring Boot 專案需要哪些 dependencies 還要怎麼寫才能使用上述 Keycloak 跟 LINE Login

為了在 Spring Boot 專案中使用 Keycloak 與 LINE Login，您需要引入以下 Maven 或 Gradle 依賴項：

Maven：

```xml
<!-- Keycloak Spring Boot Adapter -->
<dependency>
    <groupId>org.keycloak</groupId>
    <artifactId>keycloak-spring-boot-starter</artifactId>
    <version>${keycloak.version}</version>
</dependency>

<!-- LINE Login SDK -->
<dependency>
    <groupId>com.linecorp</groupId>
    <artifactId>line-login</artifactId>
    <version>${line.version}</version>
</dependency>
```

在您的 Spring Boot 應用程式中，您需要建立一個 Keycloak 設定檔，並使用 @EnableWebSecurity 註釋啟用 Spring Security。以下是一個基本的 Keycloak 設定檔：

```java
@Configuration
@EnableWebSecurity
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {

	@Autowired
	public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
		KeycloakAuthenticationProvider keycloakAuthProvider = keycloakAuthenticationProvider();
		keycloakAuthProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
		auth.authenticationProvider(keycloakAuthProvider);
	}

	@Bean
	public KeycloakConfigResolver keycloakConfigResolver() {
		return new KeycloakSpringBootConfigResolver();
	}

	@Bean
	public KeycloakSpringBootProperties keycloakProperties() {
		return new KeycloakSpringBootProperties();
	}

	@Override
	protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
		return new NullAuthenticatedSessionStrategy();
	}

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		super.configure(http);
		http.authorizeRequests()
			.antMatchers("/api/**").authenticated()
			.anyRequest().permitAll();
	}
}
```

上述設定檔使用 Keycloak 提供的 Spring Security Adapter 和 KeycloakSpringBootConfigResolver，並配置了基本的安全策略以保護您的 API。您還需要在 `application.properties` 或 `application.yml` 中提供 Keycloak 和 LINE Login 的相關配置，以及其他必要的設定。以下是一個簡單的應用程式配置範例：

`application.properties`：

```properties
# Keycloak Configuration
keycloak.auth-server-url=https://your-keycloak-server/auth
keycloak.realm=your-realm
keycloak.resource=your-client-id
keycloak.credentials.secret=your-client-secret

# LINE Login Configuration
line.channel-id=your-channel-id
line.channel-secret=your-channel-secret
line.callback-url=your-callback-url
```

完成上述配置後，您應該能夠在 Spring Boot 專案中使用 Keycloak 與 LINE Login 來實現身份驗證

## 聽說 AWS Lambda 執行 Spring 會太肥，那麼將上述套用到 Lambda function 可行嗎

AWS Lambda 適合運行輕量級的短期處理任務，對於需要較長時間執行或需要高效率的應用程式，可能不是最佳選擇。而 Spring 框架本身就較為龐大，需要較大的內存和啟動時間，因此在 AWS Lambda 上執行 Spring 應用程式可能會導致運行效率低下，並增加啟動時間和運行成本。

不過，如果您仍希望在 AWS Lambda 上執行 Spring 應用程式，您可以考慮使用以下策略以提高執行效率和減少成本：

1. 調整 Lambda 函數的內存限制和運行時間，使其符合應用程式的實際需求。過高的內存限制和運行時間會導致不必要的成本增加。

2. 使用 Lambda Layers 將 Spring 框架和應用程式代碼分離。這樣可以減少啟動時間和Lambda函數大小，並且可以更方便地更新應用程式代碼而不需要重新打包和部署整個Lambda函數。

3. 使用 Lambda Provisioned Concurrency 在需要時預先啟動一個或多個 Lambda 實例，以減少啟動時間和提高性能。

4. 使用 AWS API Gateway 或其他服務來處理和緩存用戶請求，以減少 Lambda 函數的負載和成本。

總之，雖然在 AWS Lambda 上執行 Spring 應用程式可能會有一些挑戰和限制，但在適當的情況下，仍然可以通過一些最佳實踐和優化策略來實現高效率和低成本的運行。

## 如何使用 Lambda Layers 將 Spring 框架和應用程式代碼分離

使用 Lambda Layers 可以將 Spring 框架和應用程式代碼分離，以減少 Lambda 函數的大小和啟動時間。以下是如何使用 Lambda Layers 的一般步驟：

1. 創建一個新的 Lambda Layer。您可以在 AWS Lambda 控制台或使用 AWS CLI 創建新的 Lambda Layer。在創建時，您需要指定 Layer 名稱、描述和 ARN（Amazon 資源名稱）等訊息。並準備一個包含 Spring 框架的 JAR 文件。

2. 上傳 Spring 框架的 JAR 文件到新建的 Lambda Layer。

3. 在您的 Spring Boot 專案中，將 Lambda Layer 添加為依賴項。在專案中添加一個依賴項引用您上傳的 Lambda Layer。這可以通過使用 Maven 或 Gradle 進行設置。將此依賴項添加到您的應用程式代碼中，以確保 Lambda Layer 中的 Spring 框架可以在運行時正確載入。

4. 打包和部署您的 Lambda 函數。確保在打包和部署 Lambda 函數時，將依賴於 Lambda Layer 的 Spring 框架打包到函數中，以便在運行時正確載入。

5. 測試您的 Lambda 函數。確保您的 Lambda 函數可以正確使用 Spring 框架，並在運行時正常運作。

總之，使用 Lambda Layers 可以將 Spring 框架和應用程式代碼分離，減少 Lambda 函數的大小和啟動時間，提高運行效率和降低成本。

## 概念上大致聽得懂，但能具體舉個實例嗎

當您使用 Lambda Layers 將 Spring 框架和應用程式代碼分離時，通常需要遵循以下步驟：

1. 創建一個新的 Lambda Layer。

您可以在 AWS Lambda 控制台或使用 AWS CLI 創建新的 Lambda Layer。在控制台上，您可以通過單擊「Layers」頁面上的「Create Layer」按鈕開始。在 CLI 中，可以使用「aws lambda publish-layer-version」命令創建新的 Lambda Layer。

2. 上傳 Spring 框架的 JAR 文件到新建的 Lambda Layer。
假設您已經下載了 Spring Framework 的 JAR 文件。您需要將此文件上傳到 Lambda Layer。您可以使用 AWS CLI 的「`aws lambda publish-layer-version`」命令上傳 JAR 文件。以下是一個示例命令：

```shell
aws lambda publish-layer-version --layer-name my-spring-layer --zip-file fileb://spring-framework.jar
```

3. 在您的 Spring Boot 專案中，將 Lambda Layer 添加為依賴項。

假設您使用 Maven 作為構建工具。在 Maven 項目的 pom.xml 文件中，添加以下依賴項，以引用 Lambda Layer：

```xml
<dependency>
	<groupId>com.amazonaws</groupId>
	<artifactId>aws-lambda-java-core</artifactId>
	<version>1.2.0</version>
</dependency>
<dependency>
	<groupId>com.amazonaws</groupId>
	<artifactId>aws-lambda-java-events</artifactId>
	<version>2.3.0</version>
</dependency>
<dependency>
	<groupId>my-spring-layer</groupId>
	<artifactId>spring-framework</artifactId>
	<version>1.0.0</version>
	<scope>provided</scope>
</dependency>
```

其中，「`my-spring-layer`」為您創建的 Lambda Layer 名稱。注意，您需要在依賴項的 `scope` 中指定「**`provided`**」，以確保 Lambda Layer 在運行時能夠正確載入。

4. 打包和部署您的 Lambda 函數。

使用 Maven 或 Gradle 將您的應用程式代碼打包成 JAR 文件。使用 AWS CLI 部署 Lambda 函數。以下是一個示例命令：

```shell
aws lambda create-function \
--function-name my-function \
--handler com.example.Handler::handleRequest \
--runtime java11 \
--role arn:aws:iam::123456789012:role/lambda-role \
--layers my-spring-layer-arn \
--zip-file fileb://my-function.jar
```

其中，「`my-spring-layer-arn`」為您創建的 Lambda Layer ARN。注意，您需要在「`--layers`」選項中指定 Lambda Layer。

5. 測試您的 Lambda 函數。

使用 AWS CLI 或其他工具觸發 Lambda 函數，測試您的應用程式代碼是否可以正確使用 Spring 框架。
總之，使用 Lambda Layers 可以將

## 使用 Maven 將您的應用程式代碼打包成 JAR 檔是否意味著會有不同的 Maven 專案

是的，每個 Maven 專案都應該獨立打包成一個 JAR 文件。通常，Maven 專案的結構類似於以下示例：

```
my-project/
  ├── pom.xml
  ├── src/
  │   ├── main/
  │   │   ├── java/
  │   │   │   └── com/
  │   │   │       └── example/
  │   │   │           └── App.java
  │   │   └── resources/
  │   └── test/
  │       ├── java/
  │       │   └── com/
  │       │       └── example/
  │       │           └── AppTest.java
  │       └── resources/
  └── target/
      ├── classes/
      │   └── com/
      │       └── example/
      │           └── App.class
      ├── test-classes/
      │   └── com/
      │       └── example/
      │           └── AppTest.class
      └── my-project-1.0-SNAPSHOT.jar
```

在這個示例中，有一個名為 `my-project` 的 Maven 專案，該專案包含一個名為 App 的主要 Java 類。使用 Maven 打包時，Maven 會在 `target/` 目錄下生成一個名為 `my-project-1.0-SNAPSHOT.jar` 的 JAR 文件，其中包含所有編譯過的類和資源。

如果您有多個 Maven 專案，每個專案都應該使用 Maven 打包成自己的 JAR 文件。這些 JAR 文件可以作為 Lambda Layers 的一部分使用，也可以單獨部署在其他地方。

## 那麼 Lambda Layer 的 Maven 專案又要怎麼從主專案分離

要將 Lambda Layer 的 Maven 專案從主專案分離出來，您可以使用 Maven 的模組化結構，將 Lambda Layer 的代碼獨立到一個 Maven 模組中。以下是一個示例：

假設您有一個名為 `my-project` 的 Maven 專案，並且想要將一些通用的程式碼打包成 Lambda Layer。您可以建立一個名為 `my-project-layer` 的新的 Maven 模組，該模組包含您要打包的通用程式碼。

`my-project-layer` 模組的 `pom.xml` 檔案需要設定以下設定：

- 將打包類型設定為 `jar`。

- 將 `build` 元素中的 `outputDirectory` 設定為 `target/classes`。

- 在 `dependencies` 元素中，指定任何依賴項，例如您的 Lambda 函數所需的 Spring 框架和其他函數庫。

接著在 `my-project` 主專案的 `pom.xml` 檔案中，使用 Maven 的 `modules` 元素將 `my-project-layer` 模組包含進來。這樣 Maven 在打包主專案時就會一起打包 `my-project-layer` 模組。

以下是示例 `pom.xml` 檔案：

```xml
<project>
	<groupId>com.example</groupId>
	<artifactId>my-project</artifactId>
	<version>1.0.0</version>
	<packaging>jar</packaging>

	<modules>
		<module>my-project-layer</module>
	</modules>

	<dependencies>
		<!-- Define your function dependencies here -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
			<version>5.3.10</version>
		</dependency>
	</dependencies>
</project>
```

這樣，當您使用 Maven 打包 `my-project` 時，`my-project-layer` 模組也會被打包進去。然後，您可以將 `my-project-layer` 模組打包成一個獨立的 Lambda Layer，並將其上傳到 AWS Lambda。在建立 Lambda 函數時，您可以將該 Lambda Layer 與您的函數關聯，以便在執行時使用 Lambda Layer 中的代碼。

## 主專案跟 Lambda 專案跟 Lambda Layer 專案必須放在一個 parent 專案下嗎

不一定需要將主專案、Lambda 專案和 Lambda Layer 專案放在同一個 parent 專案下。這些專案可以獨立建立，只要您能夠在 AWS Lambda 中將它們整合在一起即可。

AWS Lambda 中的函數是以 ZIP 檔案形式上傳的，因此您可以將 Lambda 函數和 Lambda Layer 的 JAR 檔案分開打包，然後在 AWS Lambda 中將它們整合在一起。這樣做可以使您的程式碼更易於管理和維護。

在 AWS Lambda 上設置函數和 Lambda Layer 時，您需要指定它們的 ARN (Amazon Resource Name)。Lambda Layer 的 ARN 可以從 AWS 控制台上找到，或者使用 AWS CLI 或 SDK 檢索。在建立 Lambda 函數時，您可以指定要使用的 Lambda Layer 的 ARN。當 Lambda 函數運行時，它將自動載入所需的 Lambda Layer，以便您可以在 Lambda 函數中使用 Layer 中的任何類和資源。

## 你提到 AWS Lambda 函數是以 ZIP 檔案形式上傳，但其實我想容器化該怎麼調整

如果您想要在容器環境中運行 AWS Lambda 函數，您可以使用 AWS 的容器服務 Amazon ECS 或 Amazon EKS，這兩個服務都可以與 AWS Lambda 進行整合。

首先，您需要將 Lambda 函數的程式碼打包成容器映像檔。可以使用任何支持的容器化工具，例如 Docker，將您的程式碼打包成 Docker 映像檔。然後，您可以將映像檔上傳到 Amazon ECR（Amazon Elastic Container Registry）或其他受支持的容器註冊表中。

接下來，您需要創建一個 Amazon ECS 或 Amazon EKS 叢集，以及一個 Lambda 管理員帳戶和角色。然後，您可以使用 AWS CLI 或 AWS 管理控制台將 Lambda 函數部署到 Amazon ECS 或 Amazon EKS 叢集中。您需要指定容器映像檔的位置以及其他運行時選項。

最後，您可以在 Amazon ECS 或 Amazon EKS 中運行 Lambda 函數。AWS Lambda 將自動管理您的容器，包括容器的編排、生命週期管理和監視。您可以使用 AWS CloudWatch 監視和管理您的 Lambda 函數，以確保它們正常運行。

需要注意的是，AWS Lambda 和容器服務 Amazon ECS 或 Amazon EKS 之間有些差異。AWS Lambda 是一種“事件驅動”服務，可以自動處理輸入事件並調用您的 Lambda 函數。相反，Amazon ECS 和 Amazon EKS 是一種容器編排服務，可以管理和維護您的容器，但需要您自己處理輸入事件。

## 我會把 Docker image 上到 ECR 沒錯，但沒打算用 ECS 甚至 EKS

如果您不想使用 Amazon ECS 或 Amazon EKS，您也可以將 Lambda 函數部署到自己的容器環境中。您可以使用 AWS CLI 或 AWS 管理控制台將 Lambda 函數打包成 ZIP 檔案，然後將其放置在容器中。

在您的容器中，您需要安裝 AWS Lambda 客戶端以與 Lambda 服務進行通信。您可以使用 AWS SDK 中的 AWS Lambda 客戶端，也可以直接使用 Lambda 函數的 HTTP API。

要運行 Lambda 函數，您需要使用 AWS Lambda 管理員帳戶和角色，並將其授權以執行您的 Lambda 函數。您可以在容器啟動時使用 IAM 角色或提供 AWS 訪問密鑰來授權 Lambda 函數。

需要注意的是，使用容器運行 Lambda 函數與使用 Lambda 函數服務有所不同。AWS Lambda 是一種無需管理伺服器和基礎架構即可運行代碼的服務，而使用容器運行 Lambda 函數需要您自己管理和維護基礎架構。如果您打算在生產環境中使用容器運行 Lambda 函數，請確保您有足夠的容量和可用性，以及適當的監視和管理工具。

## 既然要將 Lambda 函數部署到 ECR 的容器環境，為何還要將 Lambda 函數打包成 ZIP 檔案

打包成 ZIP 檔案主要是為了方便 Lambda 函數的部署和管理。AWS Lambda 支援使用 ZIP 檔案打包您的 Lambda 函數代碼，您可以使用 AWS CLI 或 AWS 管理控制台將 ZIP 檔案上傳到 Lambda 服務上。Lambda 服務會自動解壓縮 ZIP 檔案，將 Lambda 函數代碼放置在適當的位置，然後啟動 Lambda 函數。

將 Lambda 函數打包成 ZIP 檔案也讓您可以在本地端使用 Lambda 執行環境進行測試和調試。您可以在本地端打包 ZIP 檔案，然後使用 AWS CLI 的 invoke 命令或 AWS 管理控制台的測試功能來執行 Lambda 函數。

如果您要將 Lambda 函數部署到容器環境中，您可以在 `Dockerfile` 中將 ZIP 檔案複製到容器中，並在容器啟動時解壓縮 ZIP 檔案並啟動 Lambda 函數。這樣可以確保 Lambda 函數的代碼與其依賴項都被包含在容器中，並且可以正常運行。

總之，打包成 ZIP 檔案可以讓您更輕鬆地管理 Lambda 函數的部署和調試，並且可以確保 Lambda 函數的代碼與依賴項被正確地打包和部署到容器中。

## 不，我就是不想打包成 ZIP

如果您不想將 Lambda 函數打包成 ZIP 檔案，您可以使用 AWS Lambda 的另一種部署方式：使用容器映像部署 Lambda 函數。

要使用容器映像部署 Lambda 函數，您需要先創建一個 Docker 映像，其中包含 Lambda 函數的代碼和依賴項。然後，您可以在 AWS Lambda 控制台上選擇使用容器映像部署 Lambda 函數，指定您創建的 Docker 映像的位置（如 Amazon ECR 或 Docker Hub）。

在運行時，Lambda 函數容器會從您指定的容器映像中啟動，並在 Lambda 服務管理下運行。Lambda 服務會負責管理容器的生命週期，包括啟動和停止容器，並確保 Lambda 函數的佈署、縮放和安全性。

需要注意的是，使用容器映像部署 Lambda 函數需要您具有 Docker 和容器編排技術（如 Kubernetes 或 Amazon ECS）的知識，因為您需要創建和管理 Docker 映像以及容器的部署和維護。此外，容器映像部署 Lambda 函數可能需要更長的啟動時間和更高的啟動成本，因為需要將整個容器映像從存儲庫中下載到運行時環境中。

## 這就是我想知道的，若使用容器映像部署 Lambda 函數，我還能使用 Lambda Layer 嗎

是的，您仍然可以在使用容器映像部署 Lambda 函數時使用 Lambda Layer。

您可以在 `Dockerfile` 中將 Lambda Layer 包含在您的映像中。在 Dockerfile 中，您可以使用 `ADD` 命令將 Lambda Layer 壓縮檔案添加到您的 Docker 映像中。

以下是一個簡單的範例 `Dockerfile`，其中包含 Lambda 函數的代碼和一個名為 `my-lambda-layer.zip` 的 Lambda Layer：

```dockerfile
FROM amazonlinux:latest

# 安裝依賴項和運行時
RUN yum install -y java-11-amazon-corretto-headless

# 複製 Lambda 函數代碼
ADD my-lambda-function.jar /var/task/

# 添加 Lambda Layer
ADD my-lambda-layer.zip /opt/

# 設定環境變數
ENV LAMBDA_TASK_ROOT=/var/task
ENV LAMBDA_RUNTIME_DIR=/var/runtime
ENV PATH=$PATH:/var/runtime:/var/task:/opt

# 定義容器入口點
CMD [ "my-lambda-function.handler" ]
```

在這個例子中，我們將 `my-lambda-layer.zip` 添加到 Docker 映像的 `/opt/` 目錄下。然後，我們在 `CMD` 中指定 Lambda 函數的入口點為 `my-lambda-function.handler`。

使用這種方法，您可以將 Lambda Layer 和 Lambda 函數代碼一起打包到 Docker 映像中，並使用容器映像部署 Lambda 函數。

## `CMD` 中指定 Lambda 函數的入口點為 `my-lambda-function.handler`，這裡看起來怪怪的，不太像是 Spring Boot 的產物

您是對的，這是一個與 Spring Boot 無關的例子。在 Spring Boot 應用程序中，您需要使用 `org.springframework.boot.loader.JarLauncher` 作為您的入口點。

以下是一個修改後的 `Dockerfile` 範例，展示如何在容器中使用 Lambda Layer 和 Spring Boot 應用程序：

```dockerfile
FROM amazonlinux:latest

# 安裝依賴項和運行時
RUN yum install -y java-11-amazon-corretto-headless

# 複製 Spring Boot JAR
ADD my-spring-boot-app.jar /var/task/

# 添加 Lambda Layer
ADD my-lambda-layer.zip /opt/

# 設定環境變數
ENV LAMBDA_TASK_ROOT=/var/task
ENV LAMBDA_RUNTIME_DIR=/var/runtime
ENV PATH=$PATH:/var/runtime:/var/task:/opt

# 定義容器入口點
CMD ["java", "-Djava.awt.headless=true", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/var/task/my-spring-boot-app.jar"]
```

在這個例子中，我們將 `my-spring-boot-app.jar` 添加到 Docker 映像的 `/var/task/` 目錄下。然後，我們在 `CMD` 中使用 `java` 命令運行 Spring Boot 應用程序。

這裡需要注意的是，我們在 `CMD` 中指定的是 Spring Boot 應用程序的 `my-spring-boot-app.jar` 文件，而不是 Lambda 函數的入口點。

此外，如果您的 Spring Boot 應用程序需要其他的環境變數或參數，您需要根據您的需求進行設置。例如，如果您需要使用外部配置文件，可以在 `CMD` 中添加 `--spring.config.location=file:/path/to/your/config/file` 參數。
