Keycloak 授权


Red Hat build of Quarkus 3.20

Red Hat Customer Content Services

摘要

本指南详细介绍了高级 Keycloak 授权功能,清除安全策略配置、动态资源访问管理以及外部身份提供程序的集成。它还提供在现代应用环境中实施和微调基于角色的和基于属性的访问控制机制的综合步骤。

向红帽构建的 Quarkus 文档提供反馈

要报告错误或改进文档,请登录您的红帽 JIRA 帐户并提交问题。如果您没有红帽 JIRA 帐户,系统会提示您创建一个帐户。

流程

  1. 单击以下链接 来创建 ticket
  2. Summary 中输入有关此问题的简单描述。
  3. 描述中提供问题或增强功能的详细描述。请包括有问题的文档 URL。
  4. Submit 创建问题并将其路由到适当的文档团队。

了解如何使用 Keycloak Authorization Services 在 Quarkus 应用程序中启用 bearer 令牌授权来保护对受保护的资源的访问。

1.1. 概述

Keycloak Authorization 扩展 quarkus-keycloak-authorization 扩展了 OpenID Connect 扩展 quarkus-oidc 以提供高级授权功能。它具有一个策略强制器,可动态管理对安全资源的访问。访问取决于 Keycloak 中定义的权限,支持灵活和动态资源型访问控制(RBAC)。

只有在环境中启用了 Keycloak 和 Keycloak 授权服务来处理授权决策时,才使用 quarkus-keycloak-authorization 扩展。

如果不使用 Keycloak,或者在没有 Keycloak 授权服务的情况下配置 Keycloak,请使用 quarkus-oidc 扩展。

它如何工作

quarkus-keycloak-authorization 扩展可集中在 Keycloak 中的授权职责,增强安全性并简化应用程序维护:

  • 它使用 quarkus-oidc 扩展来验证 bearer 令牌。
  • 它将验证的令牌发送到 Keycloak 授权服务。
  • 它允许 Keycloak 使用资源名称、标识符或 URI 等属性动态评估基于资源的权限。

通过外部化授权决策,您可以:

  • 在不修改应用程序代码的情况下实施各种访问控制策略。
  • 随着安全需求的变化,降低重新部署需求。

兼容性

此扩展仅与 Quarkus OIDC 服务应用程序 兼容。它使用动态授权策略补充明确的机制,如基于角色的访问控制。

主要功能

  • 集中式管理 :为 Keycloak 委派授权决策,实现跨应用程序的一致性安全策略。
  • 动态权限 :使用资源属性动态定义访问控制。
  • 简化维护 :减少访问策略更改时更新和重新部署应用程序的需要。

设置

在使用此扩展前,请确保以下内容:

  1. Keycloak 授权服务在 Keycloak 实例中被启用。
  2. 您的 Quarkus 应用程序包括 quarkus-keycloak-authorization 扩展。

具体步骤请查看 OIDC Bearer 令牌身份验证指南

其他资源

要了解更多有关 Keycloak 授权服务和策略执行者的信息,请访问官方文档: Keycloak Authorization Services 文档

1.2. 先决条件

要完成本指南,您需要:

1.3. 架构

本例演示了一个简单的微服务设置,它有两个受保护的端点:

  • /api/users/me
  • /api/admin

基于令牌的访问控制

使用 bearer 令牌控制对这些端点的访问。要获取访问权限,必须满足以下条件:

  • 有效的令牌 :令牌必须具有正确的签名、有效的过期日期和相应的受众。
  • 信任 :微服务必须信任发布 Keycloak 服务器。

Keycloak 服务器发布的 bearer 令牌充当:

  • 用户标识符 :指示签发令牌的主题(用户)。
  • 客户端引用 :根据 OAuth 2.0 授权服务器标准,标识代表用户的客户端应用程序。

端点和访问策略

对于 /api/users/me

  • 访问策略 :打开具有有效 bearer 令牌和用户角色 的用户
  • 响应 :以从令牌派生的 JSON 对象返回用户详情。

    响应示例

    {
      "user": {
        "id": "1234",
        "username": "johndoe",
        "email": "johndoe@example.com"
      }
    }

对于 /api/admin

  • 访问策略 :限制具有有效 bearer 令牌和 admin 角色的用户。

分离的授权

本例重点介绍了使用基于角色的访问控制(RBAC)策略来保护资源。关键点包括:

  • 策略灵活性 : Keycloak 支持各种策略类型,如基于属性的和自定义策略,启用精细的控制。
  • 分离的应用程序逻辑 :授权策略完全由 Keycloak 管理,使您的应用程序可以专注于其核心功能。

1.4. 解决方案

我们建议您按照下一小节中的说明进行操作,并逐步创建应用程序步骤。但是,您可以进入已完成的示例。

克隆 Git 存储库: git clone https://github.com/quarkusio/quarkus-quickstarts.git -b 3.20,或下载 存档

解决方案位于 security-keycloak-authorization-quickstart 目录中

1.5. 创建项目

要开始,使用以下命令创建一个新项目:

  • 使用 Quarkus CLI:

    quarkus create app org.acme:security-keycloak-authorization-quickstart \
        --extension='oidc,keycloak-authorization,rest-jackson' \
        --no-code
    cd security-keycloak-authorization-quickstart

    要创建 Gradle 项目,请添加-- gradle or --gradle-kotlin-dsl 选项。

    有关如何安装和使用 Quarkus CLI 的更多信息,请参阅 Quarkus CLI 指南。

  • 使用 Maven:

    mvn com.redhat.quarkus.platform:quarkus-maven-plugin:3.20.1:create \
        -DprojectGroupId=org.acme \
        -DprojectArtifactId=security-keycloak-authorization-quickstart \
        -Dextensions='oidc,keycloak-authorization,rest-jackson' \
        -DnoCode
    cd security-keycloak-authorization-quickstart

    要创建 Gradle 项目,请添加 -DbuildTool=gradle or -DbuildTool=gradle-kotlin-dsl 选项。

对于 Windows 用户:

  • 如果使用 cmd,(不要使用反向斜杠 \ 并将所有内容放在同一行中)
  • 如果使用 Powershell,则双引号中的 wrap -D 参数,如 "-DprojectArtifactId=security-keycloak-authorization-quickstart"

此命令生成带有 keycloak-authorization 扩展的新项目。扩展将 Keycloak 适配器集成到您的 Quarkus 应用程序中,提供必要的功能来与 Keycloak 服务器交互并执行 bearer 令牌授权。

为现有项目添加扩展

如果您已经有一个现有的 Quarkus 项目,您可以在项目的基本目录中运行以下命令来添加 oidckeycloak-authorization 扩展:

  • 使用 Quarkus CLI:

    quarkus extension add oidc,keycloak-authorization
  • 使用 Maven:

    ./mvnw quarkus:add-extension -Dextensions='oidc,keycloak-authorization'
  • 使用 Gradle:

    ./gradlew addExtension --extensions='oidc,keycloak-authorization'

这个命令在构建文件中添加以下依赖项:

  • 使用 Maven:

    <dependency>
        <groupId>io.quarkus</groupId>
        <artifactId>quarkus-oidc</artifactId>
    </dependency>
    <dependency>
        <groupId>io.quarkus</groupId>
        <artifactId>quarkus-keycloak-authorization</artifactId>
    </dependency>
  • 使用 Gradle:

    implementation("io.quarkus:quarkus-oidc")
    implementation("io.quarkus:quarkus-keycloak-authorization")

实现 /api/users/me 端点

首先实施 /api/users/me 端点。以下代码定义了提供用户详情的 Jakarta REST 资源:

package org.acme.security.keycloak.authorization;

import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;

import org.jboss.resteasy.reactive.NoCache;

import io.quarkus.security.identity.SecurityIdentity;

@Path("/api/users")
public class UsersResource {

    @Inject
    SecurityIdentity identity;

    @GET
    @Path("/me")
    @NoCache
    public User me() {
        return new User(identity);
    }

    public static class User {

        private final String userName;

        User(SecurityIdentity identity) {
            this.userName = identity.getPrincipal().getName();
        }

        public String getUserName() {
            return userName;
        }
    }
}

实现 /api/admin 端点

接下来,定义 /api/admin 端点。以下代码代表了使用身份验证保护的简单 Jakarta REST 资源:

package org.acme.security.keycloak.authorization;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;

import io.quarkus.security.Authenticated;

@Path("/api/admin")
@Authenticated
public class AdminResource {

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String admin() {
        return "granted";
    }
}

使用 Keycloak 的基于角色的访问控制

请注意,没有定义 @RolesAllowed 等显式注释来强制执行资源的访问控制。相反,keycloak-authorization 扩展会动态映射 Keycloak 中受保护的资源的 URI。

访问控制管理如下:

  • Keycloak 根据每个请求的策略评估权限。
  • 扩展强制执行这些权限,根据 Keycloak 中定义的角色或策略授予或拒绝访问。

这会把访问控制逻辑与应用程序代码分离,从而更轻松地在 Keycloak 中管理和更新访问策略。

1.6. 配置应用程序

您可以使用 OpenID Connect 扩展通过 application.properties 文件配置适配器设置,通常位于 src/main/resources 目录中。例如:

# OIDC Configuration
%prod.quarkus.oidc.auth-server-url=https://localhost:8543/realms/quarkus 
1

quarkus.oidc.client-id=backend-service 
2

quarkus.oidc.credentials.secret=secret 
3

quarkus.oidc.tls.verification=none 
4


# Enable Policy Enforcement
quarkus.keycloak.policy-enforcer.enable=true 
5


# Import the realm file with Dev Services for Keycloak
# Note: This property is effective only in dev mode, not in JVM or native modes
quarkus.keycloak.devservices.realm-path=quarkus-realm.json 
6
1
指定 Keycloak 服务器的 URL 和用于身份验证的域。
2
在 Keycloak 域中标识客户端应用程序。
3
定义用于使用 Keycloak 服务器进行身份验证的客户端 secret。
4
为开发目的禁用 TLS 验证,不建议在生产环境中使用。
5
启用 Keycloak 策略强制器根据定义的权限管理访问控制。
6
配置 Dev Services 以导入指定的域文件,只在 dev 模式中有效,而不在 JVM 或原生模式中有效。
注意

%prod. 配置集前缀添加到 quarkus.oidc.auth-server-url 可确保 Keycloak 的 Dev Services 会自动在开发模式下启动容器。如需了解更多详细信息,请参阅 在 Dev 模式中运行应用程序 部分。

注意

默认情况下,使用 quarkus-oidc 扩展的应用程序被视为 服务类型 应用程序。但是,扩展还支持在以下情况下 web-app 类型应用程序:

  • 授权代码授权流期间返回的访问令牌必须是角色的来源(quarkus.oidc.roles.source=accesstoken)。
  • 注: 对于 web-app 类型应用程序,默认检查 ID 令牌角色。

1.7. 启动并配置 Keycloak 服务器

注意

当您以 dev 模式运行应用程序时,不要启动 Keycloak 服务器。Keycloak 的 dev Services 启动一个容器。如需更多信息,请参阅在 Dev 模式中运行应用程序 部分。

要启动 Keycloak 服务器,请使用以下 Docker 命令:

docker run --name keycloak \
  -e KC_BOOTSTRAP_ADMIN_USERNAME=admin \
  -e KC_BOOTSTRAP_ADMIN_PASSWORD=admin \
  -p 8543:8443 \
  -v "$(pwd)"/config/keycloak-keystore.jks:/etc/keycloak-keystore.jks \
  quay.io/keycloak/keycloak:{keycloak.version} \ 
1

  start --hostname-strict=false --https-key-store-file=/etc/keycloak-keystore.jks 
2
1
对于 keycloak.version,请确保版本为 26.1.3 或更高版本。
2
对于 Keycloak 密钥存储,请使用位于 quarkus-quickstarts/security-keycloak-authorization-quickstart/configkeycloak-keystore.jks 文件。

访问 Keycloak 服务器

  1. 打开浏览器并导航到 https://localhost:8543
  2. 使用以下凭证登录到 Keycloak 管理控制台:

    • Username: admin
    • Password:admin

导入域配置

要创建新域,请导入 realm 配置文件。有关创建域的详细步骤,请参阅 Keycloak 文档: 创建新域

导入域后,您可以查看资源权限:

Keycloak 授权权限

资源权限中的 Keycloak 角色

资源访问权限直接在 Keycloak 中配置,这消除了应用程序代码中 @RolesAllowed 注解的需求。此方法集中了 Keycloak 中的访问控制管理,简化了应用程序维护和安全更新。

1.8. 以 dev 模式运行应用程序

要在开发模式下运行应用程序,请使用以下命令:

  • 使用 Quarkus CLI:

    quarkus dev
  • 使用 Maven:

    ./mvnw quarkus:dev
  • 使用 Gradle:

    ./gradlew --console=plain quarkusDev

Dev Services for Keycloak 启动 Keycloak 容器,并导入 quarkus-realm.json 配置文件。

打开位于 /q/dev-uiDev UI,再单击 Dev UI 中的 OpenID Connect 卡上的 Provider: Keycloak 链接。

与 Dev UI 交互

  1. 打开位于 /q/dev-uiDev UI
  2. 点 Dev UI 中的 OpenID Connect 卡中的 Provider: Keycloak 链接。

测试用户权限

当提示登录到 OpenID Connect Dev UI 提供的 单个页面 应用程序时,请执行以下操作:

  1. alice 身份(密码: alice)登录,其只有 用户权限 来访问 /api/users/me 资源:

    1. 访问 /api/admin,它返回 403
    2. 访问 /api/users/me,它返回 200
  2. 注销并以 admin 身份(password: admin),其具有 Admin 权限 来访问 /api/admin 资源和 User Permission 以访问 /api/users/me 资源:

    1. 访问 /api/admin,它返回 200
    2. 访问 /api/users/me,它返回 200

自定义 Keycloak 域

如果您在没有导入域文件(如 quarkus-realm.json )的情况下为 Keycloak 启动 Dev Services,请创建一个没有 Keycloak 授权策略的默认 quarkus 域:

  1. 在 Dev UI 中,从 OpenID Connect 卡中选择 Keycloak Admin 链接。
  2. 登录到 Keycloak 管理控制台。用户名和密码都是 admin
  3. 按照 Keycloak Authorization Services 文档中的 说明在 quarkus 域中启用授权策略。

Keycloak Admin 链接在 Dev UI 中容易找到:

Dev UI OpenID Connect 卡

添加自定义 JavaScript 策略

如果您的应用程序使用配置了 JAR 归档中的 JavaScript 策略的 Keycloak 授权,则 Keycloak 的 Dev 服务可以将此存档传输到 Keycloak 容器。使用 application.properties 中的以下属性来配置传输:

# Alias the policies archive
quarkus.keycloak.devservices.resource-aliases.policies=/policies.jar 
1

# Map the policies archive to a specific location in the container
quarkus.keycloak.devservices.resource-mappings.policies=/opt/keycloak/providers/policies.jar 
2
1
/ policies.jar classpath 资源创建一个策略别名。策略存档也可以位于文件系统中。
2
将策略存档映射到 Keycloak 容器中的 /opt/keycloak/providers/policies.jar 位置。

1.9. 在 JVM 模式下运行应用程序

在以 dev 模式探索应用后,您可以在 JVM 模式中将其作为标准 Java 应用程序运行。

编译应用程序:

  • 使用 Quarkus CLI:

    quarkus build
  • 使用 Maven:

    ./mvnw install
  • 使用 Gradle:

    ./gradlew build

运行应用程序:

java -jar target/quarkus-app/quarkus-run.jar

1.10. 以原生模式运行应用程序

您可以将此演示编译为原生代码,不需要修改。

原生编译消除了在生产环境中 JVM 的需求,因为生成的二进制文件包含运行时并针对最少资源使用量进行了优化。

编译需要更长的时间,并默认禁用。要构建应用程序,请启用 native 配置集。

构建原生二进制文件:

  • 使用 Quarkus CLI:

    quarkus build --native
  • 使用 Maven:

    ./mvnw install -Dnative
  • 使用 Gradle:

    ./gradlew build -Dquarkus.native.enabled=true

片刻后,运行原生二进制文件:

./target/security-keycloak-authorization-quickstart-runner

1.11. 测试应用程序

有关在开发模式 中测试应用程序的说明,请参阅前面的以 Dev 模式运行 应用程序。

您可以使用 curl 来测试在 JVM 或原生模式下运行的应用。

获取访问令牌

应用使用 bearer 令牌授权。要访问其资源,首先从 Keycloak 服务器获取访问令牌:

export access_token=$(\
    curl --insecure -X POST https://localhost:8543/realms/quarkus/protocol/openid-connect/token \
    --user backend-service:secret \
    -H 'content-type: application/x-www-form-urlencoded' \
    -d 'username=alice&password=alice&grant_type=password' | jq --raw-output '.access_token' \
 )
注意

如果 quarkus.oidc.authentication.user-info-required 属性设置为 true,则应用要求访问令牌用于请求 UserInfo。在这种情况下,您必须将 scope=openid 查询参数添加到令牌授权请求中,例如:

export access_token=$(\
    curl --insecure -X POST http://localhost:8180/realms/quarkus/protocol/openid-connect/token \
    --user backend-service:secret \
    -H 'content-type: application/x-www-form-urlencoded' \
    -d 'username=alice&password=alice&grant_type=password&scope=openid' | jq --raw-output '.access_token' \
 )

前面的示例获取用户 alice 的访问令牌。

访问 /api/users/me 端点

具有有效访问令牌的任何用户可以访问 http://localhost:8080/api/users/me 端点,该端点会返回 JSON 有效负载,其中包含用户详情:

curl -v -X GET \
  http://localhost:8080/api/users/me \
  -H "Authorization: Bearer "$access_token

访问 /api/admin 端点

http://localhost:8080/api/admin 端点仅限于具有 admin 角色的用户。如果您尝试使用之前发布的访问令牌访问此端点,服务器会返回 403 Forbidden 响应:

curl -v -X GET \
  http://localhost:8080/api/admin \
  -H "Authorization: Bearer "$access_token

获取管理员访问令牌

要访问 admin 端点,请为 admin 用户获取访问令牌:

export access_token=$(\
    curl --insecure -X POST https://localhost:8543/realms/quarkus/protocol/openid-connect/token \
    --user backend-service:secret \
    -H 'content-type: application/x-www-form-urlencoded' \
    -d 'username=admin&password=admin&grant_type=password' | jq --raw-output '.access_token' \
 )

1.12. 注入授权客户端

您可以使用 Keycloak 授权客户端 Java API 进行高级任务,如管理资源并直接从 Keycloak 获取权限。要启用此功能,请将 AuthzClient 实例注入到 Bean 中:

public class ProtectedResource {
    @Inject
    AuthzClient authzClient;
}
注意

如果要直接使用 AuthzClient,请设置 quarkus.keycloak.policy-enforcer.enable=true ;否则,没有 bean 可用于注入。

注意

要直接使用 AuthzClient,请设置 quarkus.keycloak.policy-enforcer.enable=true。否则,没有可用于注入的 bean。

1.13. 映射受保护的资源

默认情况下,扩展会按需从 Keycloak 获取资源,使用其 URI 来识别和映射需要保护的应用程序资源。

要禁用按需获取并在启动时预加载资源,请配置以下属性:

quarkus.keycloak.policy-enforcer.lazy-load-paths=false

在启动过程中,从 Keycloak 加载资源所需的时间取决于资源数量,这可能会影响应用程序的初始负载时间。

1.14. 有关配置受保护的资源的更多信息

在默认配置中,Keycloak 管理角色,并决定谁可以访问哪些路由。

要使用 @RolesAllowed 注释或 application.properties 文件配置受保护的路由,请检查 OpenID Connect (OIDC) Bearer 令牌身份验证web 端点 指南的授权。如需了解更多详细信息,请参阅 Quarkus 安全概述

1.15. 访问公共资源

要允许在没有应用 quarkus-keycloak-authorization 策略的情况下访问公共资源,请在 application.properties 文件中定义 allow HTTP 策略。如需更多信息,请参阅 Web 端点授权 指南。

使用类似以下内容的配置时,您不需要禁用对 Keycloak 授权策略的策略检查:

quarkus.keycloak.policy-enforcer.paths.1.paths=/api/public
quarkus.keycloak.policy-enforcer.paths.1.enforcement-mode=DISABLED

要限制对匿名用户公共资源的访问,请定义一个 enforcing Keycloak 授权策略:

quarkus.keycloak.policy-enforcer.paths.1.paths=/api/public-enforcing
quarkus.keycloak.policy-enforcer.paths.1.enforcement-mode=ENFORCING

只有默认租户配置在控制对公共资源的匿名访问时才适用。

1.16. 以编程方式检查权限范围

除了资源权限外,您还可以定义方法范围。范围通常代表对资源执行的操作。您可以使用方法范围创建强制 Keycloak 授权策略。例如:

# path policy with enforced scope 'read' for method 'GET'
quarkus.keycloak.policy-enforcer.paths.1.name=Scope Permission Resource
quarkus.keycloak.policy-enforcer.paths.1.paths=/api/protected/standard-way
quarkus.keycloak.policy-enforcer.paths.1.methods.get.method=GET
quarkus.keycloak.policy-enforcer.paths.1.methods.get.scopes=read 
1


# path policies without scope
quarkus.keycloak.policy-enforcer.paths.2.name=Scope Permission Resource
quarkus.keycloak.policy-enforcer.paths.2.paths=/api/protected/programmatic-way,/api/protected/annotation-way
1
用户必须具有资源权限 范围资源和 范围 读取

Keycloak 策略 Enforcer 保护 /api/protected/standard-way 请求路径,不再需要注解,如 @RolesAllowed。然而,在某些情况下,您可能需要执行编程检查。

您可以通过将 SecurityIdentity 实例注入 Bean 来达到此目的,如下例所示。或者,您可以通过使用 @PermissionsAllowed 注解资源方法来获得相同的结果。以下示例演示了三种资源方法,每个资源都需要相同的 读取 范围:

import java.security.BasicPermission;
import java.util.List;

import jakarta.inject.Inject;
import jakarta.ws.rs.ForbiddenException;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;

import org.keycloak.representations.idm.authorization.Permission;

import io.quarkus.security.PermissionsAllowed;
import io.quarkus.security.identity.SecurityIdentity;
import io.smallrye.mutiny.Uni;

@Path("/api/protected")
public class ProtectedResource {

    @Inject
    SecurityIdentity identity;

    @GET
    @Path("/standard-way")
    public Uni<List<Permission>> standardWay() { 
1

        return Uni.createFrom().item(identity.<List<Permission>> getAttribute("permissions"));
    }

    @GET
    @Path("/programmatic-way")
    public Uni<List<Permission>> programmaticWay() {
        var requiredPermission = new BasicPermission("Scope Permission Resource") {
            @Override
            public String getActions() {
                return "read";
            }
        };
        return identity.checkPermission(requiredPermission).onItem() 
2

                .transform(granted -> {
                    if (granted) {
                        return identity.getAttribute("permissions");
                    }
                    throw new ForbiddenException();
                });
    }

    @PermissionsAllowed("Scope Permission Resource:read") 
3

    @GET
    @Path("/annotation-way")
    public Uni<List<Permission>> annotationWay() {
        return Uni.createFrom().item(identity.<List<Permission>> getAttribute("permissions"));
    }
}
1
/standard-way 子路径需要资源权限和 读取 范围,具体取决于 application.properties 文件中设置的配置。
2
默认情况下,/programmatic-way 子路径只检查 Scope Permission Resource 权限。但是,您可以使用 SecurityIdentity#checkPermission 来强制实施额外的约束,如范围要求。
3
/annotation-way@PermissionsAllowed 注释限制对具有 Scope Permission Resource 权限以及 读取 范围的请求的访问。如需更多信息,请参阅 安全 授权指南中的使用注解 授权部分。

1.17. 多租户

您可以为每个租户设置策略强制器配置,类似于如何使用 OpenID Connect (OIDC)多租户 进行。例如:

quarkus.keycloak.policy-enforcer.enable=true

# Default Tenant
quarkus.oidc.auth-server-url=${keycloak.url:replaced-by-test-resource}/realms/quarkus
quarkus.oidc.client-id=quarkus-app
quarkus.oidc.credentials.secret=secret

quarkus.keycloak.policy-enforcer.enforcement-mode=PERMISSIVE
quarkus.keycloak.policy-enforcer.paths.1.name=Permission Resource
quarkus.keycloak.policy-enforcer.paths.1.paths=/api/permission
quarkus.keycloak.policy-enforcer.paths.1.claim-information-point.claims.static-claim=static-claim

# Service Tenant

quarkus.oidc.service-tenant.auth-server-url=${keycloak.url:replaced-by-test-resource}/realms/quarkus
quarkus.oidc.service-tenant.client-id=quarkus-app
quarkus.oidc.service-tenant.credentials.secret=secret

quarkus.keycloak.service-tenant.policy-enforcer.enforcement-mode=PERMISSIVE
quarkus.keycloak.service-tenant.policy-enforcer.paths.1.name=Permission Resource Service
quarkus.keycloak.service-tenant.policy-enforcer.paths.1.paths=/api/permission
quarkus.keycloak.service-tenant.policy-enforcer.paths.1.claim-information-point.claims.static-claim=static-claim


# WebApp Tenant

quarkus.oidc.webapp-tenant.auth-server-url=${keycloak.url:replaced-by-test-resource}/realms/quarkus
quarkus.oidc.webapp-tenant.client-id=quarkus-app
quarkus.oidc.webapp-tenant.credentials.secret=secret
quarkus.oidc.webapp-tenant.application-type=web-app
quarkus.oidc.webapp-tenant.roles.source=accesstoken

quarkus.keycloak.webapp-tenant.policy-enforcer.enforcement-mode=PERMISSIVE
quarkus.keycloak.webapp-tenant.policy-enforcer.paths.1.name=Permission Resource WebApp
quarkus.keycloak.webapp-tenant.policy-enforcer.paths.1.paths=/api/permission
quarkus.keycloak.webapp-tenant.policy-enforcer.paths.1.claim-information-point.claims.static-claim=static-claim

1.18. 动态租户配置解析

要在避免配置文件中的过度条目时创建多个租户配置,您可以使用 io.quarkus.keycloak.pep.TenantPolicyConfigResolver 接口在运行时以编程方式定义它们。

package org.acme.security.keycloak.authorization;

import java.util.Map;

import jakarta.enterprise.context.ApplicationScoped;

import io.quarkus.keycloak.pep.TenantPolicyConfigResolver;
import io.quarkus.keycloak.pep.runtime.KeycloakPolicyEnforcerConfig;
import io.quarkus.keycloak.pep.runtime.KeycloakPolicyEnforcerTenantConfig;
import io.quarkus.oidc.OidcRequestContext;
import io.quarkus.oidc.OidcTenantConfig;
import io.smallrye.mutiny.Uni;
import io.vertx.ext.web.RoutingContext;

@ApplicationScoped
public class CustomTenantPolicyConfigResolver implements TenantPolicyConfigResolver {

    private final KeycloakPolicyEnforcerTenantConfig enhancedTenantConfig;
    private final KeycloakPolicyEnforcerTenantConfig newTenantConfig;

    public CustomTenantPolicyConfigResolver(KeycloakPolicyEnforcerConfig enforcerConfig) {
        this.enhancedTenantConfig = KeycloakPolicyEnforcerTenantConfig.builder(config) 
1

            .paths("/enhanced-config")
            .permissionName("Permission Name")
            .get("read-scope")
            .build();
        this.newTenantConfig = KeycloakPolicyEnforcerTenantConfig.builder() 
2

            .paths("/new-config")
            .claimInformationPoint(Map.of("claims", Map.of("grant", "{request.parameter['grant']}")))
            .build();
    }

    @Override
    public Uni<KeycloakPolicyEnforcerTenantConfig> resolve(RoutingContext routingContext, OidcTenantConfig tenantConfig,
                                                OidcRequestContext<KeycloakPolicyEnforcerTenantConfig> requestContext) {
        String path = routingContext.normalizedPath();
        String tenantId = tenantConfig.tenantId.orElse(null);
        if ("enhanced-config-tenant".equals(tenantId) && path.equals("/enhanced-config")) {
            return Uni.createFrom().item(enhancedTenantConfig);
        } else if ("new-config-tenant".equals(tenantId) && path.equals("/new-config")) {
            return Uni.createFrom().item(newTenantConfig);
        }
        return Uni.createFrom().nullItem(); 
3

    }
}
1
在默认租户配置中定义或更新 /enhanced-config 路径。
2
/new-config 路径添加到租户配置,包括以编程方式填充的自定义声明和值。
3
回退到 application.properties 文件或其他 SmallRye Config 源中定义的默认静态租户配置解析。

1.19. 配置参考

此配置遵循官方 Keycloak 策略强制配置指南。有关各种配置选项的详细信息,请参阅以下文档:

build 时修复的 - 配置属性在构建时修复 - 所有其他配置属性在运行时可覆盖

Expand

配置属性

Type

default

build time quarkus.keycloak.policy-enforcer.enable

启用策略强制。

环境变量: QUARKUS_KEYCLOAK_POLICY_ENFORCER_ENABLE

布尔值

false

quarkus.keycloak.connection-pool-size

适配器将对 Keycloak 服务器进行单独的 HTTP 调用,以便将访问代码转换为访问令牌。此配置选项定义与 Keycloak 服务器应池的连接数量

环境变量: QUARKUS_KEYCLOAK_CONNECTION_POOL_SIZE

int

20

quarkus.keycloak.policy-enforcer.enforcement-mode

指定如何强制实施策略。

环境变量: QUARKUS_KEYCLOAK_POLICY_ENFORCER_ENFORCEMENT_MODE

permissive,enforcing,disabled

enforcing

quarkus.keycloak.policy-enforcer.path-cache.max-entries

定义应在缓存中保存的条目限制

环境变量: QUARKUS_KEYCLOAK_POLICY_ENFORCER_PATH_CACHE_MAX_ENTRIES

int

1000

quarkus.keycloak.policy-enforcer.path-cache.lifespan

定义条目应过期的时间(毫秒)

环境变量: QUARKUS_KEYCLOAK_POLICY_ENFORCER_PATH_CACHE_LIFESPAN

long

30000

quarkus.keycloak.policy-enforcer.lazy-load-paths

指定适配器应如何获取与应用程序中路径关联的资源的服务器。如果为 true,策略强制器将通过请求的路径相应地获取资源

环境变量: QUARKUS_KEYCLOAK_POLICY_ENFORCER_LAZY_LOAD_PATHS

布尔值

true

quarkus.keycloak.policy-enforcer.claim-information-point."complex-config"

复杂配置。

环境变量: QUARKUS_KEYCLOAK_POLICY_ENFORCER_CLAIM_INFORMATION_POINT__COMPLEX_CONFIG_

Map<String,Map<String,Map<String,String>>>

 

quarkus.keycloak.policy-enforcer.claim-information-point."simple-config"

简单配置。

环境变量: QUARKUS_KEYCLOAK_POLICY_ENFORCER_CLAIM_INFORMATION_POINT__SIMPLE_CONFIG_

Map<String,Map<String,String>>

 

quarkus.keycloak.policy-enforcer.http-method-as-scope

指定范围应如何映射到 HTTP 方法。如果设置为 true,策略 enforcer 将使用当前请求中的 HTTP 方法来检查是否应授予访问权限

环境变量: QUARKUS_KEYCLOAK_POLICY_ENFORCER_HTTP_METHOD_AS_SCOPE

布尔值

false

quarkus.keycloak.policy-enforcer.paths."paths".name

要与给定路径关联的服务器上的资源名称

环境变量: QUARKUS_KEYCLOAK_POLICY_ENFORCER_PATHS__PATHS__NAME

string

 

quarkus.keycloak.policy-enforcer.paths."paths".paths

应该由策略强制器保护的 HTTP 请求路径

环境变量: QUARKUS_KEYCLOAK_POLICY_ENFORCER_PATHS__PATHS__PATHS

字符串列表

 

quarkus.keycloak.policy-enforcer.paths."paths".methods."methods".methods".methods"

HTTP 方法的名称

环境变量: QUARKUS_KEYCLOAK_POLICY_ENFORCER_PATHS__PATHS__METHODS__METHODS__METHOD

string

所需的 HEKETI Required

quarkus.keycloak.policy-enforcer.paths."paths".methods."methods".scopes"

与方法关联的范围的字符串数组

环境变量: QUARKUS_KEYCLOAK_POLICY_ENFORCER_PATHS__PATHS__METHODS__METHODS__SCOPES

字符串列表

所需的 HEKETI Required

quarkus.keycloak.policy-enforcer.paths."paths".methods."methods".scopes-enforcement-mode

引用与方法关联的范围的强制模式的字符串

环境变量: QUARKUS_KEYCLOAK_POLICY_ENFORCER_PATHS__PATHS__METHODS__METHODS__SCOPES_ENFORCEMENT_MODE

所有任何禁用

all

quarkus.keycloak.policy-enforcer.paths."paths".enforcement-mode

指定如何强制实施策略

环境变量: QUARKUS_KEYCLOAK_POLICY_ENFORCER_PATHS__PATHS__ENFORCEMENT_MODE

permissive,enforcing,disabled

enforcing

quarkus.keycloak.policy-enforcer.paths."paths".claim-information-point."complex-config"

复杂配置。

环境变量: QUARKUS_KEYCLOAK_POLICY_ENFORCER_PATHS__PATHS__CLAIM_INFORMATION_POINT__COMPLEX_CONFIG_

Map<String,Map<String,Map<String,String>>>

 

quarkus.keycloak.policy-enforcer.paths."paths".claim-information-point."simple-config"

简单配置。

环境变量: QUARKUS_KEYCLOAK_POLICY_ENFORCER_PATHS__PATHS__CLAIM_INFORMATION_POINT__SIMPLE_CONFIG_

Map<String,Map<String,String>>

 

Additional named tenants

Type

default

quarkus.keycloak."tenant".connection-pool-size

适配器将对 Keycloak 服务器进行单独的 HTTP 调用,以便将访问代码转换为访问令牌。此配置选项定义与 Keycloak 服务器应池的连接数量

环境变量: QUARKUS_KEYCLOAK_TENANT__CONNECTION_POOL_SIZE

int

20

quarkus.keycloak."tenant".policy-enforcer.enforcement-mode

指定如何强制实施策略。

环境变量: QUARKUS_KEYCLOAK_TENANT__POLICY_ENFORCER_ENFORCEMENT_MODE

permissive,enforcing,disabled

enforcing

quarkus.keycloak."tenant".policy-enforcer.paths."paths".

要与给定路径关联的服务器上的资源名称

环境变量: QUARKUS_KEYCLOAK_TENANT__POLICY_ENFORCER_PATHS_PATHS_NAME

string

 

quarkus.keycloak."tenant".policy-enforcer.paths."paths".paths

应该由策略强制器保护的 HTTP 请求路径

环境变量: QUARKUS_KEYCLOAK_TENANT__POLICY_ENFORCER_PATHS__PATHS_PATHS

字符串列表

 

quarkus.keycloak."tenant".policy-enforcer.paths."paths".methods."methods".methods"

HTTP 方法的名称

环境变量: QUARKUS_KEYCLOAK_TENANT__POLICY_ENFORCER_PATHS__PATHS__METHODS__METHODS__METHOD

string

所需的 HEKETI Required

quarkus.keycloak."tenant".policy-enforcer.paths."paths."methods."methods".scopes

与方法关联的范围的字符串数组

环境变量: QUARKUS_KEYCLOAK_TENANT__POLICY_ENFORCER_PATHS__PATHS__METHODS__METHODS__SCOPES

字符串列表

所需的 HEKETI Required

quarkus.keycloak."tenant".policy-enforcer.paths."paths".methods."methods".scopes-enforcement-mode

引用与方法关联的范围的强制模式的字符串

环境变量: QUARKUS_KEYCLOAK_TENANT__POLICY_ENFORCER_PATHS__PATHS__METHODS__METHODS__SCOPES_ENFORCEMENT_MODE

所有任何禁用

all

quarkus.keycloak."tenant".policy-enforcer.paths."paths".enforcement-mode

指定如何强制实施策略

环境变量: QUARKUS_KEYCLOAK_TENANT__POLICY_ENFORCER_PATHS__PATHS__ENFORCEMENT_MODE

permissive,enforcing,disabled

enforcing

quarkus.keycloak."tenant".policy-enforcer.paths."paths".claim-information-point."complex-config"

复杂配置。

环境变量: QUARKUS_KEYCLOAK_TENANT__POLICY_ENFORCER_PATHS__PATHS__CLAIM_INFORMATION_POINT_COMPLEX_CONFIG_

Map<String,Map<String,Map<String,String>>>

 

quarkus.keycloak."tenant".policy-enforcer.paths."paths".claim-information-point."simple-config"

简单配置。

环境变量: QUARKUS_KEYCLOAK_TENANT__POLICY_ENFORCER_PATHS__PATHS__CLAIM_INFORMATION_POINT_SIMPLE_CONFIG_

Map<String,Map<String,String>>

 

quarkus.keycloak."tenant".policy-enforcer.path-cache.max-entries

定义应在缓存中保存的条目限制

环境变量: QUARKUS_KEYCLOAK_TENANT__POLICY_ENFORCER_PATH_MAX_ENTRIES

int

1000

quarkus.keycloak."tenant".policy-enforcer.path-cache.lifespan

定义条目应过期的时间(毫秒)

环境变量: QUARKUS_KEYCLOAK_TENANT__POLICY_ENFORCER_PATH_CACHE_LIFESPAN

long

30000

quarkus.keycloak."tenant".policy-enforcer.lazy-load-paths

指定适配器应如何获取与应用程序中路径关联的资源的服务器。如果为 true,策略强制器将通过请求的路径相应地获取资源

环境变量: QUARKUS_KEYCLOAK_TENANT__POLICY_ENFORCER_LAZY_LOAD_PATHS

布尔值

true

quarkus.keycloak."tenant".policy-enforcer.claim-information-point."complex-config"

复杂配置。

环境变量: QUARKUS_KEYCLOAK_TENANT__POLICY_ENFORCER_CLAIM_INFORMATION_POINT_COMPLEX_CONFIG_

Map<String,Map<String,Map<String,String>>>

 

quarkus.keycloak."tenant".policy-enforcer.claim-information-point."simple-config"

简单配置。

环境变量: QUARKUS_KEYCLOAK_TENANT__POLICY_ENFORCER_CLAIM_INFORMATION_POINT_SIMPLE_CONFIG_

Map<String,Map<String,String>>

 

quarkus.keycloak."tenant".policy-enforcer.http-method-as-scope

指定范围应如何映射到 HTTP 方法。如果设置为 true,策略 enforcer 将使用当前请求中的 HTTP 方法来检查是否应授予访问权限

环境变量: QUARKUS_KEYCLOAK_TENANT__POLICY_ENFORCER_HTTP_METHOD_AS_SCOPE

布尔值

false

1.20. 参考

法律通告

Copyright © 2025 Red Hat, Inc.
The text of and illustrations in this document are licensed by Red Hat under a Creative Commons Attribution–Share Alike 3.0 Unported license ("CC-BY-SA"). An explanation of CC-BY-SA is available at http://creativecommons.org/licenses/by-sa/3.0/. In accordance with CC-BY-SA, if you distribute this document or an adaptation of it, you must provide the URL for the original version.
Red Hat, as the licensor of this document, waives the right to enforce, and agrees not to assert, Section 4d of CC-BY-SA to the fullest extent permitted by applicable law.
Red Hat, Red Hat Enterprise Linux, the Shadowman logo, the Red Hat logo, JBoss, OpenShift, Fedora, the Infinity logo, and RHCE are trademarks of Red Hat, Inc., registered in the United States and other countries.
Linux® is the registered trademark of Linus Torvalds in the United States and other countries.
Java® is a registered trademark of Oracle and/or its affiliates.
XFS® is a trademark of Silicon Graphics International Corp. or its subsidiaries in the United States and/or other countries.
MySQL® is a registered trademark of MySQL AB in the United States, the European Union and other countries.
Node.js® is an official trademark of Joyent. Red Hat is not formally related to or endorsed by the official Joyent Node.js open source or commercial project.
The OpenStack® Word Mark and OpenStack logo are either registered trademarks/service marks or trademarks/service marks of the OpenStack Foundation, in the United States and other countries and are used with the OpenStack Foundation's permission. We are not affiliated with, endorsed or sponsored by the OpenStack Foundation, or the OpenStack community.
All other trademarks are the property of their respective owners.
Red Hat logoGithubredditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。 了解我们当前的更新.

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

Theme

© 2026 Red Hat
返回顶部