使用 OpenID Connect(OIDC)Bearer 令牌认证保护服务应用
使用Quarkus OpenID Connect(OIDC)扩展,通过Bearer令牌认证保护Jakarta REST应用。Bearer令牌由兼容OIDC与OAuth 2.0的授权服务器签发,例如Keycloak。
有关OIDC Bearer令牌认证的更多信息,参见Quarkus OpenID Connect(OIDC)Bearer token authentication指南。
如需使用OIDC授权码流程保护Web应用,参见使用 OpenID Connect 授权码流程保护 Web 应用指南。
前置条件
完成本指南需要:
-
约15分钟。
-
一个IDE。
-
安装JDK 17或更高版本,并正确配置
JAVA_HOME。 -
Apache Maven 3.9.16。
-
可用的容器运行时,Docker或Podman。
-
可选:如果希望通过Quarkus CLI操作,安装该工具。
-
可选:如需构建原生可执行文件,安装并正确配置Mandrel或GraalVM;使用容器构建原生文件时也可使用Docker。
-
jq命令行处理工具。
架构
本示例构建一个简单微服务,提供两个端点:
-
/api/users/me -
/api/admin
这些端点受保护。客户端必须随请求发送Bearer令牌,令牌需要有效(例如签名、有效期和受众均符合要求),并受到微服务信任,才能访问。
Keycloak服务器签发Bearer令牌,令牌代表其签发对象。由于Keycloak是OAuth 2.0授权服务器,令牌还会标识代表用户操作的客户端。
任何持有有效令牌的用户都能访问/api/users/me。该端点根据令牌信息返回包含用户详情的JSON文档。
/api/通过RBAC(基于角色的访问控制)保护,仅admin角色可访问;端点使用admin@RolesAllowed声明式地实施访问约束。
完整方案
可以按后续步骤逐步创建应用,也可以直接查看完成的示例。
运行git clone https://github.com/quarkusio/quarkus-quickstarts.git克隆仓库,或者下载归档文件。
完整方案位于security-openid-connect-quickstart目录。
创建 Maven 项目
可以新建包含oidc扩展的Maven项目,也可以把扩展加入现有项目。选择以下适用的命令。
新建Maven项目:
CLI
quarkus create app org.acme:security-openid-connect-quickstart \
--extension='oidc,rest-jackson' \
--no-code
cd security-openid-connect-quickstart
如需Gradle项目,添加--gradle或--gradle-kotlin-dsl选项。
Quarkus CLI的安装与用法参见Quarkus CLI指南。
Maven
mvn io.quarkus.platform:quarkus-maven-plugin:3.40.1:create \
-DprojectGroupId=org.acme \
-DprojectArtifactId=security-openid-connect-quickstart \
-Dextensions='oidc,rest-jackson' \
-DnoCode
cd security-openid-connect-quickstart
如需Gradle项目,添加-DbuildTool=gradle或-DbuildTool=gradle-kotlin-dsl选项。
Windows用户请注意:
-
使用cmd时,不要使用反斜杠
\续行,应把整个命令放在同一行。 -
使用PowerShell时,用双引号包裹
-D参数,例如"-DprojectArtifactId=security-openid-connect-quickstart"。
现有Quarkus项目可以在项目根目录运行以下命令,添加oidc扩展:
CLI
quarkus extension add oidc
Maven
./mvnw quarkus:add-extension -Dextensions='oidc'
Gradle
./gradlew addExtension --extensions='oidc'
这会在构建文件中加入以下依赖:
pom.xml
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-oidc</artifactId>
</dependency>
build.gradle
implementation("io.quarkus:quarkus-oidc")
编写应用
-
按下面的普通Jakarta REST资源示例,实现
/api/users/me: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 OIDC扩展。%prod.quarkus.oidc.auth-server-url=http://localhost: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
其中:
-
指定OIDC服务器基础URL。%prod.配置档前缀保证在开发模式下由%prod.quarkus.oidc.auth-server-urlDev Services for Keycloak启动容器。详情见“以开发模式运行应用”。 -
quarkus.oidc.client-id设置用于标识应用的客户端ID。 -
quarkus.oidc.credentials.secret设置客户端密钥,供client_secret_basic认证方法使用。
更多配置参见OpenID Connect(OIDC)configuration properties指南。
以开发模式运行应用
把realm配置文件放入src/main/resources目录,使它被复制到类路径并自动导入Keycloak。如果已构建完整示例,则构建时会把该realm文件加入类路径,无需重复此步骤。
-
使用以下命令启动开发模式:
CLI
quarkus devMaven
./mvnw quarkus:devGradle
./gradlew --console=plain quarkusDev-
Dev Services for Keycloak会启动Keycloak容器,并导入
quarkus-realm.json。
-
-
打开/q/dev-ui中的Dev UI,在
OpenID Connect卡片中点击Keycloak provider链接。 -
当
OpenID Connect Dev UI提供的单页应用要求登录时,执行以下步骤:-
以
alice登录,密码为alice;该用户具有user角色。-
访问
/api/admin返回403。 -
访问
/api/users/me返回200。
-
-
退出后,以
admin登录,密码为admin;该用户同时具有admin和user角色。-
访问
/api/admin返回200。 -
访问
/api/users/me返回200。
-
-
启动并配置 Keycloak 服务器
|
在开发模式运行应用时,不要另行启动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:26.7.4 start-dev
-
Keycloak服务器可通过localhost:8180访问。
-
使用以下示例凭据以
admin用户登录Keycloak管理控制台:-
用户名:
admin。 -
密码:
admin。
-
-
从上游社区仓库导入realm配置文件,创建新的realm。
更多信息参见Keycloak文档中创建和配置realm的说明。
|
如果要通过应用中的Keycloak Admin Client配置服务器,根据所用技术栈选择扩展:
这些规则使Keycloak Admin Client能够与所用REST框架配合,不论使用REST服务器、REST客户端还是二者。 更多信息参见Quarkus Keycloak 管理客户端指南。 |
以 JVM 模式运行应用
-
编译应用:
CLI
quarkus buildMaven
./mvnw installGradle
./gradlew build -
运行应用:
java -jar target/quarkus-app/quarkus-run.jar
以原生模式运行应用
同一示例无需修改即可编译为原生可执行文件。这样生产环境中不再需要安装JVM;所需运行时包含在二进制文件中,并经过优化以降低资源需求。
原生编译耗时更长,因此默认不启用。
-
启用
native配置重新构建:CLI
quarkus build --nativeMaven
./mvnw install -DnativeGradle
./gradlew build -Dquarkus.native.enabled=true -
等待构建完成后,可直接运行以下二进制文件:
./target/security-openid-connect-quickstart-1.0.0-SNAPSHOT-runner
测试应用
开发模式的测试方法参见前面的开发模式章节。
JVM或原生模式启动的应用,可以使用curl测试。
-
应用采用Bearer令牌认证,因此访问资源前,必须先从Keycloak获取访问令牌:
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' | jq --raw-output '.access_token' \
)
|
当
|
上例获取的是alice用户的访问令牌。
-
持有有效令牌的任意用户都可访问
http://localhost:8080/api/users/me,获取包含用户详情的JSON负载。
curl -v -X GET \
http://localhost:8080/api/users/me \
-H "Authorization: Bearer "$access_token
-
只有
admin角色可以访问http://localhost:8080/api/admin。使用此前为alice签发的令牌访问,会得到403响应。
curl -v -X GET \
http://localhost:8080/api/admin \
-H "Authorization: Bearer "$access_token
-
如需访问管理员端点,先获取
admin用户的令牌:
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=admin&password=admin&grant_type=password' | jq --raw-output '.access_token' \
)
关于依赖Dev Services for Keycloak的集成测试,参见OIDC Bearer令牌认证指南中的Dev Services for Keycloak章节。
参考资料
-
OIDC配置属性
-
OpenID Connect(OIDC)Bearer令牌认证
-
Keycloak文档
-
OpenID Connect与OAuth2客户端及过滤器参考指南
-
使用SmallRye JWT Build签名与加密JWT令牌
-
组合身份验证机制
-
Quarkus安全概览
正文相关链接
- OpenID Connect (OIDC) Bearer token authentication
- configured appropriately
- jq command-line processor tool
- archive
- complete solution
- Run the application in dev mode
- OIDC configuration properties
- realm configuration file
- creating and configuring a new realm
- Dev Services for Keycloak
- Keycloak Documentation
- OpenID Connect and OAuth2 Client and Filters Reference Guide
- Sign and encrypt JWT tokens with SmallRye JWT Build
- Combining authentication mechanisms
- Quarkus Security overview











暂无评论内容