亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Keycloak 使用自定義協議映射器從數據庫/外部源添加額外聲明

Keycloak 使用自定義協議映射器從數據庫/外部源添加額外聲明

米琪卡哇伊 2021-12-22 15:14:02
我看過這兩篇文章,它們為這個問題提供了解決方案,但它們沒有提供足夠詳細的信息,說明如何為像我這樣的非 Java 開發人員執行此操作:Keycloak 添加來自數據庫/外部源的額外聲明如何在 Keycloak 中注冊自定義 ProtocolMapper?這是他們的解決方案的概述,如果提供更多詳細信息,可以幫助其他人。第一個鏈接的預期過程用戶登錄我的自定義協議映射器被調用,在那里我覆蓋了 transformAccessToken 方法在這里,我將協議映射器所在的客戶端作為服務登錄到 keycloak。這里不要忘記使用另一個客戶端 ID 而不是您正在為其構建協議映射器的客戶端 ID,否則您將進入無限遞歸。我將訪問令牌放入協議映射器中,然后調用應用程序的其余端點來獲取額外的聲明,這是安全的。獲取端點返回的信息并將其添加為額外聲明從第二個鏈接實現它的步驟實現 ProtocolMapper 接口并添加包含對類的引用的文件 “META-INF/services/org.keycloak.protocol.ProtocolMapper”。此時,Keycloak 識別出新的實現。您應該能夠通過管理控制臺對其進行配置。要向令牌添加一些數據,請添加以下接口org.keycloak.protocol.oidc.mappers.OIDCAccessTokenMapper并根據接口實現方法然后添加文件“ META-INF/jboss-deployment-structure.xml ”,內容如下<?xml version="1.0" encoding="UTF-8"?><jboss-deployment-structure>    <deployment>        <dependencies>            <module name="org.keycloak.keycloak-services"/>        </dependencies>    </deployment></jboss-deployment-structure>完成所有這些之后,在對 URL http://:/auth/realms/testrealm/protocol/openid-connect/token 的每個請求時都會調用自定義的 transformAccessToken() 方法閱讀本文后,我有幾個問題:你如何“實施ProtocolMapper”你在哪里添加前面提到的文件?(在我的 Keycloak 安裝文件夾中看不到任何 META-INF/ 目錄)您如何以及在哪里“添加以下接口”自定義的 transformAccessToken() 是什么樣的謝謝大家的時間。如果我錯過了總結他們的答案,請告訴我。
查看完整描述

2 回答

?
慕標5832272

TA貢獻1966條經驗 獲得超4個贊

我希望這個分步指南可以幫助你

我正在使用 Keycloak 4.5.0 - 因為我安裝了這個較新的版本 - 但我不應該有太大的不同。我OIDCProtocolMapper在示例中實現了 a 。

只是總結一下 - 為了其他人的快速概覽 - 每個步驟都在后面更詳細地描述

  1. 您實現了一個基于 CustomProtocolMapper 的類 AbstractOIDCProtocolMapper

  2. 具有名稱的 META-INF/services 文件org.keycloak.protocol.ProtocolMapper必須可用并包含映射器的名稱

  3. jboss-deployment-structure.xml 需要可以使用內置于類中的keycloak

  4. Jar 文件部署在 /opt/jboss/keycloak/standalone/deployments/

好的,現在有更多細節:-)

創建您的自定義映射器

我給你上傳了我的 maven pom.xmlpom ) - 只需將它導入到你的 IDE 中,所有的依賴項都會自動加載。依賴關系只是provided ,稍后將在運行時直接從 keycloak 使用

相關的是keycloak.version屬性 - 當前在版本中加載所有 keycloak 依賴項4.5.0.Final

現在我創建了一個名為CustomOIDCProtocolMapper在這里找到“完整”代碼

它應該擴展AbstractOIDCProtocolMapper并需要實現所有抽象方法。也許你想要一個 SAML 協議映射器然后它是另一個基類 ( AbstractSAMLProtocolMapper)

一個相關的方法是transformAccessToken- 在這里我為 AccessToken 設置了一個額外的聲明。您在這里需要您的邏輯,但是是的-取決于您的數據庫等;-)

服務文件

services 文件對于 keycloak 找到您的自定義實現很重要

將一個文件的文件名 org.keycloak.protocol.ProtocolMapper\src\main\resources\META-INF\services\

在此文件中,您寫入自定義提供程序的名稱 - 因此 keycloak 知道此類可用作協議映射器
在我的示例中,文件內容只是一行

com.stackoverflow.keycloak.custom.CustomOIDCProtocolMapper

部署結構 XML

在您的自定義映射器中,您使用來自 keycloak 的文件。為了使用它們,我們需要通知 jboss 這個依賴。因此jboss-deployment-structure.xml\src\main\resources\META-INF\ Content 中創建一個文件:

<jboss-deployment-structure>

    <deployment>

        <dependencies>

            <module name="org.keycloak.keycloak-services" />

        </dependencies>

    </deployment>

</jboss-deployment-structure>

構建和部署您的擴展

構建您的擴展 ( mvn clean package)的 jar 文件- 并將其jar放入/opt/jboss/keycloak/standalone/deployments/并重新啟動 keycloak

在日志文件中,您應該看到它的部署時間和(希望沒有)錯誤消息

現在你可以使用你的映射器 - 在我的例子中,我可以在 keycloak admin ui 中創建一個映射器并Stackoverflow Custom Protocol Mapper從下拉列表中選擇

就像信息一樣 - 這不是 keycloak 完全官方支持的 - 所以接口可能會在以后的版本中改變

我希望這是可以理解的,并且您將能夠成功實現自己的映射器

編輯:導出的 eclipse 文件結構zip


查看完整回答
反對 回復 2021-12-22
?
拉莫斯之舞

TA貢獻1820條經驗 獲得超10個贊

我正在使用自定義協議映射器1將經過身份驗證的GraphQL 查詢3發送到外部系統,并將 JSON 響應數據放入用戶的訪問令牌 (JWT) 中。它目前與 Keycloak 10 一起運行。

==> 你可以在這個存儲庫中找到完整的代碼。

(1) 自定義協議映射器

正如其他人所指出的,您的項目至少需要 3 個文件。

  1. 實現AbstractOIDCProtocolMapper及其方法setClaim(以及其他方法)的Java 類。

  2. 一個jboss-deployment-structure.xml包含用于部署的依賴文件。

  3. 一個org.keycloak.protocol.ProtocolMapper包含自定義協議映射器的全名的文件。

這是文件夾結構:

$ tree src/ -A

src/

└── main

    ├── java

    │   └── com

    │       └── thohol

    │           └── keycloak

    │               └── JsonGraphQlRemoteClaim.java

    └── resources

        └── META-INF

            ├── jboss-deployment-structure.xml

            └── services

                └── org.keycloak.protocol.ProtocolMapper

(2) 認證遠程請求

如果遠程端點需要身份驗證,我們可以從 Keycloak 獲取訪問令牌。完整的流程如下(尤其是步驟 3-6):

  1. 用戶向 Keycloak 發送身份驗證請求(即“登錄”)。該請求是針對特定的 Keycloak 客戶端發出的,例如login-client。

  2. 由于login-client配置為使用自定義協議映射器,因此在處理用戶的身份驗證請求時會執行其代碼。

  3. 自定義協議映射器向 Keycloak 發送第二個身份驗證請求。該請求是針對第二個Keycloak 客戶端(例如,remote-claims-client)使用client_credentials(客戶端 ID + 秘密)進行的。

  4. 自定義協議映射器接收客戶端的訪問令牌remote-claims-client。

  5. 自定義協議映射器向遠程端點發送請求。一個Authorization: Bearer <access token>標頭被添加到請求標頭中。

  6. 遠程端點接收請求并驗證 JWT 令牌。在許多情況下,應該進一步限制訪問。例如,只允許為相應的remote-claims-client.

  7. 遠程端點返回自定義遠程聲明數據。

  8. 自定義協議映射器接收自定義遠程聲明數據并將其放入用戶的訪問令牌中。

  9. Keycloak 向用戶返回帶有自定義聲明的訪問令牌。

步驟 3/4 可以在 Java 中實現為一個簡單的 HTTP POST 請求(省略錯誤處理?。?/p>

// Call remote service

HttpClient httpClient = HttpClient.newHttpClient();

URIBuilder uriBuilder = new URIBuilder(keycloakAuthUrl);

URI uri = uriBuilder.build();


HttpRequest.Builder builder = HttpRequest.newBuilder().uri(uri);

String queryBody = "grant_type=client_credentials&client_id=remote-claims-client&client_secret=dfebc62a-e8d7-4ab3-9196-258ddb5684ab";

builder.POST(HttpRequest.BodyPublishers.ofString(queryBody));


// Build headers

builder.header(HttpHeaders.CONTENT_TYPE , MediaType.APPLICATION_FORM_URLENCODED);


// Call

HttpResponse<String> response = httpClient.send(builder.build(), HttpResponse.BodyHandlers.ofString());


// Process Response

JsonNode json = return new ObjectMapper().readTree(response.body());

String accessToken = json.findValue("access_token").asText();

(3) 使用GraphQL Queries進行外部請求

GraphQL 查詢本質上是一個 HTTP POST 請求,body類似于


{

    "query": "query HeroName($episode: Episode) {

        hero(episode: $episode) {

            name

        }

    }",

    "variables": {

        "episode" : "JEDI"

    }

}

這可以從 Java 發送,如(省略錯誤處理!):


HttpClient httpClient = HttpClient.newHttpClient();

URIBuilder uriBuilder = new URIBuilder(remoteUrl);

URI uri = uriBuilder.build();


HttpRequest.Builder builder = HttpRequest.newBuilder().uri(uri);

String queryBody = "{

    \"query\": \"query HeroName($episode: Episode) {

        hero(episode: $episode) {

            name

        }

    }\",

    \"variables\": {

        \"episode\" : \"JEDI\"

    }

}";

builder.POST(HttpRequest.BodyPublishers.ofString(queryBody));


// Build headers

builder.header(HttpHeaders.CONTENT_TYPE , MediaType.APPLICATION_JSON);

builder.header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken);


// Call

HttpResponse<String> response = httpClient.send(builder.build(), HttpResponse.BodyHandlers.ofString());


// Process Response and add to token

JsonNode json = return new ObjectMapper().readTree(response.body());

clientSessionCtx.setAttribute("custom_claims", json);


查看完整回答
反對 回復 2021-12-22
  • 2 回答
  • 0 關注
  • 636 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號