<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-authz-client</artifactId>
<version>26.0.2</version>
</dependency>
</dependencies>
根據您的需求,資源伺服器應該能夠遠端管理資源,甚至以程式化的方式檢查權限。如果您使用 Java,可以使用授權用戶端 API 存取 Keycloak 授權服務。
它適用於想要存取伺服器提供的不同端點(例如 Token 端點、資源和權限管理端點)的資源伺服器。
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-authz-client</artifactId>
<version>26.0.2</version>
</dependency>
</dependencies>
用戶端設定定義在 keycloak.json
檔案中,如下所示
{
"realm": "hello-world-authz",
"auth-server-url" : "https://127.0.0.1:8080",
"resource" : "hello-world-authz-service",
"credentials": {
"secret": "secret"
}
}
realm(必要)
領域的名稱。
auth-server-url(必要)
Keycloak 伺服器的基本 URL。所有其他 Keycloak 頁面和 REST 服務端點都由此衍生而來。它通常採用 https://host:port 的形式。
resource(必要)
應用程式的 client-id。每個應用程式都有一個 client-id,用於識別應用程式。
credentials(必要)
指定應用程式的憑證。這是一個物件表示法,其中鍵是憑證類型,值是憑證類型的值。詳細資訊請參閱專門的章節。
設定檔通常位於應用程式的類別路徑中,這是用戶端嘗試尋找
檔案的預設位置。keycloak.json
假設您的類別路徑中有
檔案,您可以建立一個新的 keycloak.json
實例,如下所示AuthzClient
// create a new instance based on the configuration defined in a keycloak.json located in your classpath
AuthzClient authzClient = AuthzClient.create();
以下範例說明如何取得使用者權限
// create a new instance based on the configuration defined in keycloak.json
AuthzClient authzClient = AuthzClient.create();
// create an authorization request
AuthorizationRequest request = new AuthorizationRequest();
// send the entitlement request to the server in order to
// obtain an RPT with all permissions granted to the user
AuthorizationResponse response = authzClient.authorization("alice", "alice").authorize(request);
String rpt = response.getToken();
System.out.println("You got an RPT: " + rpt);
// now you can use the RPT to access protected resources on the resource server
以下範例說明如何取得一組或多個資源的使用者權限
// create a new instance based on the configuration defined in keycloak.json
AuthzClient authzClient = AuthzClient.create();
// create an authorization request
AuthorizationRequest request = new AuthorizationRequest();
// add permissions to the request based on the resources and scopes you want to check access
request.addPermission("Default Resource");
// send the entitlement request to the server in order to
// obtain an RPT with permissions for a single resource
AuthorizationResponse response = authzClient.authorization("alice", "alice").authorize(request);
String rpt = response.getToken();
System.out.println("You got an RPT: " + rpt);
// now you can use the RPT to access protected resources on the resource server
// create a new instance based on the configuration defined in keycloak.json
AuthzClient authzClient = AuthzClient.create();
// create a new resource representation with the information we want
ResourceRepresentation newResource = new ResourceRepresentation();
newResource.setName("New Resource");
newResource.setType("urn:hello-world-authz:resources:example");
newResource.addScope(new ScopeRepresentation("urn:hello-world-authz:scopes:view"));
ProtectedResource resourceClient = authzClient.protection().resource();
ResourceRepresentation existingResource = resourceClient.findByName(newResource.getName());
if (existingResource != null) {
resourceClient.delete(existingResource.getId());
}
// create the resource on the server
ResourceRepresentation response = resourceClient.create(newResource);
String resourceId = response.getId();
// query the resource using its newly generated id
ResourceRepresentation resource = resourceClient.findById(resourceId);
System.out.println(resource);
// create a new instance based on the configuration defined in keycloak.json
AuthzClient authzClient = AuthzClient.create();
// send the authorization request to the server in order to
// obtain an RPT with all permissions granted to the user
AuthorizationResponse response = authzClient.authorization("alice", "alice").authorize();
String rpt = response.getToken();
// introspect the token
TokenIntrospectionResponse requestingPartyToken = authzClient.protection().introspectRequestingPartyToken(rpt);
System.out.println("Token status is: " + requestingPartyToken.getActive());
System.out.println("Permissions granted by the server: ");
for (Permission granted : requestingPartyToken.getPermissions()) {
System.out.println(granted);
}
當授權用戶端需要傳送後端通道請求時,它需要向 Keycloak 伺服器驗證。預設情況下,有三種方法可以驗證用戶端:用戶端 ID 和用戶端密碼、使用簽署的 JWT 進行用戶端驗證,或使用用戶端密碼使用簽署的 JWT 進行用戶端驗證。
這是 OAuth2 規範中描述的傳統方法。用戶端有一個密碼,需要讓用戶端和 Keycloak 伺服器都知道。您可以在 Keycloak 管理主控台中為特定用戶端產生密碼,然後將此密碼貼到應用程式端的 keycloak.json
檔案中
"credentials": {
"secret": "19666a4f-32dd-4049-b082-684c74115f28"
}
這基於 RFC7523 規範。它的運作方式如下
用戶端必須具有私鑰和憑證。對於授權用戶端,這可以通過傳統的 keystore
檔案取得,該檔案可以在用戶端應用程式的類別路徑中,或在檔案系統的某個位置取得。
在驗證期間,用戶端會產生一個 JWT 權杖,並使用其私鑰簽署該權杖,並在特定請求中的 client_assertion
參數中傳送給 Keycloak。
Keycloak 必須具有用戶端的公鑰或憑證,以便它可以驗證 JWT 上的簽名。在 Keycloak 中,您需要為您的用戶端設定用戶端憑證。首先,在管理主控台中的 憑證
索引標籤中,選擇 簽署的 JWT
作為驗證用戶端的方法。然後,您可以在 金鑰
索引標籤中選擇以下其中一種方法
設定 JWKS URL,Keycloak 可以從該 URL 下載用戶端的公鑰。此選項是最靈活的,因為用戶端可以隨時輪換其金鑰,而 Keycloak 總是根據需要下載新金鑰,而無需變更設定。換句話說,當 Keycloak 看到由未知的 kid
(金鑰 ID)簽署的權杖時,它會下載新金鑰。但是,您需要注意將公鑰以 JWKS 格式公開到某處,以供伺服器使用。
上傳用戶端的公鑰或憑證,可以採用 PEM 格式、JWK 格式或從金鑰儲存區上傳。使用此選項時,公鑰是硬式編碼的,當用戶端產生新的金鑰對時必須變更。如果您沒有自己的金鑰儲存區,甚至可以從 Keycloak 管理主控台產生您自己的金鑰儲存區。使用授權用戶端時,此選項最容易。
若要設定此方法,您需要在 keycloak.json
檔案中編寫如下程式碼
"credentials": {
"jwt": {
"client-keystore-file": "classpath:keystore-client.jks",
"client-keystore-type": "JKS",
"client-keystore-password": "storepass",
"client-key-password": "keypass",
"client-key-alias": "clientkey",
"token-expiration": 10
}
}
透過此設定,金鑰儲存區檔案 keystore-client.jks
必須可在使用授權用戶端的應用程式的類別路徑中取得。如果您不使用字首 classpath:
,您可以指向執行用戶端應用程式的檔案系統上的任何檔案。
這與使用簽署的 JWT 進行用戶端驗證相同,只是使用了用戶端密碼而不是私鑰和憑證。
用戶端有一個密碼,需要讓使用授權用戶端的應用程式和 Keycloak 伺服器都知道。在管理主控台中的 憑證
索引標籤中,選擇 使用用戶端密碼簽署的 JWT
作為驗證用戶端的方法,然後將此密碼貼到應用程式端的 keycloak.json
檔案中
"credentials": {
"secret-jwt": {
"secret": "19666a4f-32dd-4049-b082-684c74115f28",
"algorithm": "HS512"
}
}
「algorithm」欄位指定使用用戶端密碼簽署的 JWT 的演算法。它必須是以下值之一:HS256、HS384 和 HS512。詳情請參閱JSON Web 演算法 (JWA)。
此「algorithm」欄位是可選的;如果 keycloak.json
檔案中不存在「algorithm」欄位,則會自動套用 HS256。
您也可以新增您自己的用戶端驗證方法。您需要同時實作用戶端和伺服器端提供者。有關詳細資訊,請參閱 伺服器開發人員指南中的 驗證 SPI
章節。