使用 OpenID Connect (OIDC) Bearer 令牌身份验证保护服务应用程序
使用 Quarkus OpenID Connect (OIDC) 扩展程序,通过 Bearer 令牌认证来保护 Jakarta REST 应用程序。Bearer 令牌由符合 OIDC 和 OAuth 2.0 的授权服务器颁发,例如 Keycloak。
有关 OIDC Bearer 令牌认证的更多信息,请参阅 Quarkus OpenID Connect (OIDC) Bearer 令牌认证指南。
如果要通过使用 OIDC 授权代码流认证来保护 Web 应用程序,请参阅用于保护 Web 应用程序的 OpenID Connect 授权代码流机制指南。
先决条件
要完成本指南,您需要
-
大约 15 分钟
-
一个 IDE
-
已安装 JDK 17+ 并正确配置了
JAVA_HOME -
Apache Maven 3.9.9
-
一个正常工作的容器运行时(Docker 或 Podman)
-
如果您想使用它,可以选择 Quarkus CLI
-
如果您想构建本机可执行文件(或者如果您使用本机容器构建,则为 Docker),可以选择安装 Mandrel 或 GraalVM 并进行适当的配置
架构
此示例演示了如何构建一个提供两个端点的简单微服务
-
/api/users/me -
/api/admin
这些端点受到保护,只有当客户端发送一个 Bearer 令牌以及请求时才能访问,该令牌必须有效(例如,签名、过期时间和受众)并且受到微服务的信任。
Keycloak 服务器颁发 Bearer 令牌,并表示令牌颁发的主题。因为它是一个 OAuth 2.0 授权服务器,所以该令牌还引用了代表用户行事的客户端。
任何具有有效令牌的用户都可以访问 /api/users/me 端点。作为响应,它会返回一个 JSON 文档,其中包含从令牌信息中获取的用户详细信息。
/api/admin 端点受 RBAC(基于角色的访问控制)保护,只有具有 admin 角色的用户才能访问。在此端点,@RolesAllowed 注释用于声明性地强制执行访问约束。
解决方案
按照以下部分的说明,逐步创建应用程序。您也可以直接转到已完成的示例。
您可以通过运行命令 git clone https://github.com/quarkusio/quarkus-quickstarts.git 来克隆 Git 存储库,也可以下载一个 存档。
该解决方案位于 security-openid-connect-quickstart 目录中。
创建 Maven 项目
您可以创建一个带有 oidc 扩展程序的新 Maven 项目,也可以将扩展程序添加到现有的 Maven 项目。完成以下命令之一
要创建一个新的 Maven 项目,请使用以下命令
对于 Windows 用户
-
如果使用 cmd,(不要使用反斜杠
\并将所有内容放在同一行上) -
如果使用 Powershell,请将
-D参数包装在双引号中,例如"-DprojectArtifactId=security-openid-connect-quickstart"
如果您已经配置了 Quarkus 项目,则可以通过在项目根目录中运行以下命令将 oidc 扩展程序添加到您的项目中
quarkus extension add oidc
./mvnw quarkus:add-extension -Dextensions='oidc'
./gradlew addExtension --extensions='oidc'
这会将以下内容添加到您的构建文件中
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-oidc</artifactId>
</dependency>
implementation("io.quarkus:quarkus-oidc")
编写应用程序
-
按以下示例所示实现
/api/users/me端点,这是一个常规的 Jakarta REST 资源package org.acme.security.openid.connect; import jakarta.annotation.security.RolesAllowed; 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 securityIdentity; @GET @Path("/me") @RolesAllowed("user") @NoCache public User me() { return new User(securityIdentity); } public static class User { private final String userName; User(SecurityIdentity securityIdentity) { this.userName = securityIdentity.getPrincipal().getName(); } public String getUserName() { return userName; } } } -
按以下示例所示实现
/api/admin端点package org.acme.security.openid.connect; import jakarta.annotation.security.RolesAllowed; import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; import jakarta.ws.rs.Produces; import jakarta.ws.rs.core.MediaType; @Path("/api/admin") public class AdminResource { @GET @RolesAllowed("admin") @Produces(MediaType.TEXT_PLAIN) public String admin() { return "granted"; } }此示例的主要区别在于,
@RolesAllowed注释用于验证只有被授予admin角色的用户才能访问该端点。
SecurityIdentity 的注入在 @RequestScoped 和 @ApplicationScoped 上下文中均受支持。
配置应用程序
-
通过在
src/main/resources/application.properties文件中设置以下配置属性来配置 Quarkus OpenID Connect (OIDC) 扩展程序。%prod.quarkus.oidc.auth-server-url=https://:8180/realms/quarkus quarkus.oidc.client-id=backend-service quarkus.oidc.credentials.secret=secret # Tell Dev Services for Keycloak to import the realm file # This property is not effective when running the application in JVM or native modes quarkus.keycloak.devservices.realm-path=quarkus-realm.json
其中
-
%prod.quarkus.oidc.auth-server-url设置 OpenID Connect (OIDC) 服务器的基本 URL。%prod.配置文件前缀确保您在开发(dev)模式下运行应用程序时,Dev Services for Keycloak会启动一个容器。有关更多信息,请参阅在开发模式下运行应用程序部分。 -
quarkus.oidc.client-id设置一个客户端 ID,用于标识应用程序。 -
quarkus.oidc.credentials.secret设置客户端密钥,该密钥由client_secret_basic身份验证方法使用。
有关更多信息,请参阅 Quarkus OpenID Connect (OIDC) 配置属性指南。
启动并配置 Keycloak 服务器
-
将 realm 配置文件放在类路径(
target/classes目录)上,以便在开发模式下运行时自动导入。如果您已经构建了一个 完整的解决方案,则无需执行此操作,在这种情况下,此 realm 文件将在构建期间添加到类路径。在开发模式下运行应用程序时,请勿启动 Keycloak 服务器;
Dev Services for Keycloak将启动一个容器。有关更多信息,请参阅在开发模式下运行应用程序部分。 -
要启动 Keycloak 服务器,您可以使用 Docker 运行以下命令
docker run --name keycloak -e KC_BOOTSTRAP_ADMIN_USERNAME=admin -e KC_BOOTSTRAP_ADMIN_PASSWORD=admin -p 8180:8080 quay.io/keycloak/keycloak:{keycloak.version} start-dev-
其中
keycloak.version设置为26.2.4或更高版本。
-
-
您可以在 localhost:8180 访问您的 Keycloak 服务器。
-
要访问 Keycloak 管理控制台,请使用以下登录凭据以
admin用户身份登录-
用户名:
admin -
密码:
admin
-
-
从上游社区存储库导入 realm 配置文件以创建一个新的 realm。
有关更多信息,请参阅 Keycloak 文档中关于创建和配置新 realm的内容。
|
要通过使用 Keycloak Admin Client 从您的应用程序配置 Keycloak 服务器,请根据您的设置包含以下扩展程序之一
这些指南确保 Keycloak Admin Client 与您的 REST 框架无缝集成,无论您是使用 REST 服务器、REST 客户端还是两者。 有关更多信息,请参阅 Quarkus Keycloak Admin Client 指南。 |
在开发模式下运行应用程序
-
要在开发模式下运行应用程序,请运行以下命令
CLIquarkus devMaven./mvnw quarkus:devGradle./gradlew --console=plain quarkusDev-
Dev Services for Keycloak 将启动一个 Keycloak 容器并导入一个
quarkus-realm.json。
-
-
打开一个 Dev UI,您可以在 /q/dev-ui 中找到它。然后,在
OpenID Connect卡中,单击Keycloak provider链接。 -
当提示您登录到
OpenID Connect Dev UI提供的Single Page Application时,请执行以下步骤-
以
alice(密码:alice)身份登录,她具有user角色。-
访问
/api/admin返回403状态代码。 -
访问
/api/users/me返回200状态代码。
-
-
注销并以
admin(密码:admin)身份再次登录,他同时具有admin和user角色。-
访问
/api/admin返回200状态代码。 -
访问
/api/users/me返回200状态代码。
-
-
在 JVM 模式下运行应用程序
完成开发模式后,您可以将应用程序作为标准 Java 应用程序运行。
-
编译应用程序
CLIquarkus buildMaven./mvnw installGradle./gradlew build -
运行应用程序
java -jar target/quarkus-app/quarkus-run.jar
在原生模式下运行应用程序
您可以将此相同的演示按原样编译为原生模式,而无需进行任何修改。这意味着您不再需要在生产环境中安装 JVM。运行时技术包含在生成的二进制文件中,并经过优化,可以以最少的资源运行。
编译需要一段时间,因此默认情况下禁用此步骤。
-
通过启用
native配置文件再次构建您的应用程序CLIquarkus build --nativeMaven./mvnw install -DnativeGradle./gradlew build -Dquarkus.native.enabled=true -
稍等片刻后,您可以直接运行以下二进制文件
./target/security-openid-connect-quickstart-1.0.0-SNAPSHOT-runner
测试应用程序
有关在开发模式下测试您的应用程序的信息,请参阅前面的在开发模式下运行应用程序部分。
您可以使用 curl 测试在 JVM 或原生模式下启动的应用程序。
-
由于应用程序使用 Bearer 令牌认证,因此您必须首先从 Keycloak 服务器获取访问令牌才能访问应用程序资源
export access_token=$(\
curl --insecure -X POST https://: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' | jq --raw-output '.access_token' \
)
|
当
|
前面的示例获取用户 alice 的访问令牌。
-
任何用户都可以访问
https://:8080/api/users/me端点,该端点返回一个 JSON 有效负载,其中包含有关用户的详细信息。
curl -v -X GET \
https://:8080/api/users/me \
-H "Authorization: Bearer "$access_token
-
只有具有
admin角色的用户才能访问https://:8080/api/admin端点。如果您尝试使用先前颁发的访问令牌访问此端点,您将收到服务器的403响应。
curl -v -X GET \
https://:8080/api/admin \
-H "Authorization: Bearer "$access_token
-
要访问管理端点,请获取
admin用户的令牌
export access_token=$(\
curl --insecure -X POST https://:8180/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' \
)
有关编写依赖于 Dev Services for Keycloak 的集成测试的信息,请参阅“OpenID Connect (OIDC) Bearer 令牌认证”指南的 Dev Services for Keycloak 部分。