OpenID Connect 客户端和令牌传播快速入门
了解如何在您的应用程序中使用带有过滤器的 OpenID Connect (OIDC) 和 OAuth2 客户端来获取、刷新和传播访问令牌。
有关 Quarkus 中 OIDC Client
和 Token Propagation
支持的更多信息,请参阅 OpenID Connect (OIDC) 和 OAuth2 客户端和过滤器参考指南。
要使用 Bearer Token Authorization 保护您的应用程序,请参阅 OpenID Connect (OIDC) Bearer 令牌身份验证 指南。
先决条件
要完成本指南,您需要
-
大约 15 分钟
-
一个 IDE
-
已安装 JDK 17+ 并正确配置了
JAVA_HOME
-
Apache Maven 3.9.9
-
一个正常工作的容器运行时(Docker 或 Podman)
-
如果您想使用它,可以选择 Quarkus CLI
-
如果您想构建本机可执行文件(或者如果您使用本机容器构建,则为 Docker),可以选择安装 Mandrel 或 GraalVM 并进行适当的配置
架构
在此示例中,应用程序构建了两个 Jakarta REST 资源 FrontendResource
和 ProtectedResource
。在此,FrontendResource
使用三种方法之一将访问令牌传播到 ProtectedResource
-
它可以在传播令牌之前使用 OIDC 客户端过滤器获取令牌。
-
它可以借助以编程方式创建的 OIDC 客户端获取令牌,并通过将令牌作为 HTTP
Authorization
标头值传递给 REST 客户端方法来传播令牌。 -
它可以使用 OIDC 令牌传播过滤器来传播传入的访问令牌。
FrontendResource
有八个端点
-
/frontend/user-name-with-oidc-client-token
-
/frontend/admin-name-with-oidc-client-token
-
/frontend/user-name-with-oidc-client-token-header-param
-
/frontend/admin-name-with-oidc-client-token-header-param
-
/frontend/user-name-with-oidc-client-token-header-param-blocking
-
/frontend/admin-name-with-oidc-client-token-header-param-blocking
-
/frontend/user-name-with-propagated-token
-
/frontend/admin-name-with-propagated-token
当调用 /frontend/user-name-with-oidc-client-token
或 /frontend/admin-name-with-oidc-client-token
端点时,FrontendResource
使用带有 OIDC 客户端过滤器的 REST 客户端来获取访问令牌,并将其传播到 ProtectedResource
。当调用 /frontend/user-name-with-oidc-client-token-header-param
或 /frontend/admin-name-with-oidc-client-token-header-param
端点时,FrontendResource
使用以编程方式创建的 OIDC 客户端来获取访问令牌,并通过将令牌作为 HTTP Authorization
标头值传递给 REST 客户端方法来将其传播到 ProtectedResource
。当调用 /frontend/user-name-with-propagated-token
或 /frontend/admin-name-with-propagated-token
端点时,FrontendResource
使用带有 OIDC 令牌传播过滤器
的 REST 客户端将当前的传入访问令牌传播到 ProtectedResource
。
ProtectedResource
有两个端点
-
/protected/user-name
-
/protected/admin-name
这两个端点都返回从传入的访问令牌中提取的用户名,该令牌已从 FrontendResource
传播到 ProtectedResource
。这些端点之间的唯一区别是,只有当当前访问令牌具有 user
角色时才允许调用 /protected/user-name
,并且只有当当前访问令牌具有 admin
角色时才允许调用 /protected/admin-name
。
解决方案
我们建议您按照以下章节中的说明,逐步创建应用程序。但是,您可以直接转到完整的示例。
克隆 Git 存储库:git clone https://github.com/quarkusio/quarkus-quickstarts.git
,或下载 归档文件。
解决方案位于 security-openid-connect-client-quickstart
目录中。
创建 Maven 项目
首先,您需要一个新项目。使用以下命令创建一个新项目
对于 Windows 用户
-
如果使用 cmd,(不要使用反斜杠
\
并将所有内容放在同一行上) -
如果使用 Powershell,请将
-D
参数括在双引号中,例如"-DprojectArtifactId=security-openid-connect-client-quickstart"
它会生成一个 Maven 项目,导入 oidc
、rest-client-oidc-filter
、rest-client-oidc-token-propagation
和 rest
扩展。
如果您已经配置了 Quarkus 项目,则可以通过在项目基本目录中运行以下命令,将这些扩展添加到您的项目中
quarkus extension add oidc,rest-client-oidc-filter,rest-client-oidc-token-propagation,rest
./mvnw quarkus:add-extension -Dextensions='oidc,rest-client-oidc-filter,rest-client-oidc-token-propagation,rest'
./gradlew addExtension --extensions='oidc,rest-client-oidc-filter,rest-client-oidc-token-propagation,rest'
它会将以下扩展添加到您的构建文件中
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-oidc</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-rest-client-oidc-filter</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-rest-client-oidc-token-propagation</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-rest</artifactId>
</dependency>
implementation("io.quarkus:quarkus-oidc,rest-client-oidc-filter,rest-client-oidc-token-propagation,rest")
编写应用程序
首先实现 ProtectedResource
package org.acme.security.openid.connect.client;
import jakarta.annotation.security.RolesAllowed;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import io.quarkus.security.Authenticated;
import io.smallrye.mutiny.Uni;
import org.eclipse.microprofile.jwt.JsonWebToken;
@Path("/protected")
@Authenticated
public class ProtectedResource {
@Inject
JsonWebToken principal;
@GET
@RolesAllowed("user")
@Produces("text/plain")
@Path("userName")
public Uni<String> userName() {
return Uni.createFrom().item(principal.getName());
}
@GET
@RolesAllowed("admin")
@Produces("text/plain")
@Path("adminName")
public Uni<String> adminName() {
return Uni.createFrom().item(principal.getName());
}
}
ProtectedResource
从 userName()
和 adminName()
方法中返回名称。该名称是从当前的 JsonWebToken
中提取的。
接下来,添加以下 REST 客户端
-
RestClientWithOidcClientFilter
,它使用quarkus-rest-client-oidc-filter
扩展提供的 OIDC 客户端过滤器来获取和传播访问令牌。 -
RestClientWithTokenHeaderParam
,它接受已通过编程方式创建的 OidcClient 获取的令牌作为 HTTPAuthorization
标头值。 -
RestClientWithTokenPropagationFilter
,它使用quarkus-rest-client-oidc-token-propagation
扩展提供的 OIDC 令牌传播过滤器来获取和传播访问令牌。
添加 RestClientWithOidcClientFilter
REST 客户端
package org.acme.security.openid.connect.client;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import io.quarkus.oidc.client.filter.OidcClientFilter;
import io.smallrye.mutiny.Uni;
@RegisterRestClient
@OidcClientFilter (1)
@Path("/")
public interface RestClientWithOidcClientFilter {
@GET
@Produces("text/plain")
@Path("userName")
Uni<String> getUserName();
@GET
@Produces("text/plain")
@Path("adminName")
Uni<String> getAdminName();
}
1 | 使用 REST 客户端注册一个 OIDC 客户端过滤器,以获取和传播令牌。 |
添加 RestClientWithTokenHeaderParam
REST 客户端
package org.acme.security.openid.connect.client;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import io.smallrye.mutiny.Uni;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.HeaderParam;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
@RegisterRestClient
@Path("/")
public interface RestClientWithTokenHeaderParam {
@GET
@Produces("text/plain")
@Path("userName")
Uni<String> getUserName(@HeaderParam("Authorization") String authorization); (1)
@GET
@Produces("text/plain")
@Path("adminName")
Uni<String> getAdminName(@HeaderParam("Authorization") String authorization); (1)
}
1 | RestClientWithTokenHeaderParam REST 客户端期望令牌将作为 HTTP Authorization 标头值传递给它。 |
添加 RestClientWithTokenPropagationFilter
REST 客户端
package org.acme.security.openid.connect.client;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import io.quarkus.oidc.token.propagation.common.AccessToken;
import io.smallrye.mutiny.Uni;
@RegisterRestClient
@AccessToken (1)
@Path("/")
public interface RestClientWithTokenPropagationFilter {
@GET
@Produces("text/plain")
@Path("userName")
Uni<String> getUserName();
@GET
@Produces("text/plain")
@Path("adminName")
Uni<String> getAdminName();
}
1 | 使用 REST 客户端注册一个 OIDC 令牌传播过滤器,以传播传入的已存在的令牌。 |
不要在同一个 REST 客户端中使用 RestClientWithOidcClientFilter 和 RestClientWithTokenPropagationFilter 接口,因为它们可能会冲突,从而导致问题。例如,OIDC 客户端过滤器可以覆盖来自 OIDC 令牌传播过滤器的令牌,或者如果传播过滤器尝试传播令牌时没有可用的令牌,则传播过滤器可能无法正常工作,因为它希望 OIDC 客户端过滤器获取新令牌。 |
另外,添加 OidcClientCreator
以在启动时以编程方式创建 OIDC 客户端。OidcClientCreator
支持 RestClientWithTokenHeaderParam
REST 客户端调用
package org.acme.security.openid.connect.client;
import java.util.Map;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import io.quarkus.oidc.client.OidcClient;
import io.quarkus.oidc.client.OidcClients;
import io.quarkus.oidc.client.runtime.OidcClientConfig;
import io.quarkus.oidc.client.runtime.OidcClientConfig.Grant.Type;
import io.quarkus.runtime.StartupEvent;
import io.smallrye.mutiny.Uni;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.event.Observes;
import jakarta.inject.Inject;
@ApplicationScoped
public class OidcClientCreator {
@Inject
OidcClients oidcClients; (1)
@ConfigProperty(name = "quarkus.oidc.auth-server-url")
String oidcProviderAddress;
private volatile OidcClient oidcClient;
public void startup(@Observes StartupEvent event) {
createOidcClient().subscribe().with(client -> {oidcClient = client;});
}
public OidcClient getOidcClient() {
return oidcClient;
}
private Uni<OidcClient> createOidcClient() {
OidcClientConfig cfg = OidcClientConfig
.authServerUrl(oidcProviderAddress)
.id("myclient")
.clientId("backend-service")
.credentials("secret")
.grant(Type.PASSWORD)
.grantOptions("password", Map.of("username", "alice", "password", "alice"))
.build();
return oidcClients.newClient(cfg);
}
}
1 | OidcClients 可用于检索已初始化的命名 OIDC 客户端,并按需创建新的 OIDC 客户端。 |
现在,通过添加 FrontendResource
来完成应用程序的创建
package org.acme.security.openid.connect.client;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import io.quarkus.oidc.client.Tokens;
import io.quarkus.oidc.client.runtime.TokensHelper;
import org.eclipse.microprofile.rest.client.inject.RestClient;
import io.smallrye.mutiny.Uni;
@Path("/frontend")
public class FrontendResource {
@Inject
@RestClient
RestClientWithOidcClientFilter restClientWithOidcClientFilter; (1)
@Inject
@RestClient
RestClientWithTokenPropagationFilter restClientWithTokenPropagationFilter; (2)
@Inject
OidcClientCreator oidcClientCreator;
TokensHelper tokenHelper = new TokensHelper(); (5)
@Inject
@RestClient
RestClientWithTokenHeaderParam restClientWithTokenHeaderParam; (3)
@GET
@Path("user-name-with-oidc-client-token")
@Produces("text/plain")
public Uni<String> getUserNameWithOidcClientToken() { (1)
return restClientWithOidcClientFilter.getUserName();
}
@GET
@Path("admin-name-with-oidc-client-token")
@Produces("text/plain")
public Uni<String> getAdminNameWithOidcClientToken() { (1)
return restClientWithOidcClientFilter.getAdminName();
}
@GET
@Path("user-name-with-propagated-token")
@Produces("text/plain")
public Uni<String> getUserNameWithPropagatedToken() { (2)
return restClientWithTokenPropagationFilter.getUserName();
}
@GET
@Path("admin-name-with-propagated-token")
@Produces("text/plain")
public Uni<String> getAdminNameWithPropagatedToken() { (2)
return restClientWithTokenPropagationFilter.getAdminName();
}
@GET
@Path("user-name-with-oidc-client-token-header-param")
@Produces("text/plain")
public Uni<String> getUserNameWithOidcClientTokenHeaderParam() { (3)
return tokenHelper.getTokens(oidcClientCreator.getOidcClient()).onItem()
.transformToUni(tokens -> restClientWithTokenHeaderParam.getUserName("Bearer " + tokens.getAccessToken()));
}
@GET
@Path("admin-name-with-oidc-client-token-header-param")
@Produces("text/plain")
public Uni<String> getAdminNameWithOidcClientTokenHeaderParam() { (3)
return tokenHelper.getTokens(oidcClientCreator.getOidcClient()).onItem()
.transformToUni(tokens -> restClientWithTokenHeaderParam.getAdminName("Bearer " + tokens.getAccessToken()));
}
@GET
@Path("user-name-with-oidc-client-token-header-param-blocking")
@Produces("text/plain")
public String getUserNameWithOidcClientTokenHeaderParamBlocking() { (4)
Tokens tokens = tokenHelper.getTokens(oidcClientCreator.getOidcClient()).await().indefinitely();
return restClientWithTokenHeaderParam.getUserName("Bearer " + tokens.getAccessToken()).await().indefinitely();
}
@GET
@Path("admin-name-with-oidc-client-token-header-param-blocking")
@Produces("text/plain")
public String getAdminNameWithOidcClientTokenHeaderParamBlocking() { (4)
Tokens tokens = tokenHelper.getTokens(oidcClientCreator.getOidcClient()).await().indefinitely();
return restClientWithTokenHeaderParam.getAdminName("Bearer " + tokens.getAccessToken()).await().indefinitely();
}
}
1 | 当调用 /frontend/user-name-with-oidc-client-token 或 /frontend/admin-name-with-oidc-client-token 时,FrontendResource 使用带有 OIDC 客户端过滤器的注入的 RestClientWithOidcClientFilter REST 客户端来获取访问令牌,并将其传播到 ProtectedResource 。 |
2 | 当调用 /frontend/user-name-with-propagated-token 或 /frontend/admin-name-with-propagated-token 时,FrontendResource 使用带有 OIDC 令牌传播过滤器的注入的 RestClientWithTokenPropagationFilter REST 客户端将当前的传入访问令牌传播到 ProtectedResource 。 |
3 | 当调用 /frontend/user-name-with-oidc-client-token-header-param 或 /frontend/admin-name-with-oidc-client-token-header-param 时,FrontendResource 使用以编程方式创建的 OIDC 客户端来获取访问令牌,并通过将其作为 HTTP Authorization 标头值直接传递给注入的 RestClientWithTokenHeaderParam REST 客户端的方法来将其传播到 ProtectedResource 。 |
4 | 有时,可能需要在以阻塞方式获取令牌,然后再通过 REST 客户端传播令牌。此示例演示了在这种情况下如何获取令牌。 |
5 | 当直接使用 OIDC 客户端时,io.quarkus.oidc.client.runtime.TokensHelper 是一个有用的工具,无需 OIDC 客户端过滤器。要使用 TokensHelper ,请将 OIDC 客户端传递给它以获取令牌,TokensHelper 会以线程安全的方式获取令牌并在必要时刷新它们。 |
最后,添加一个 Jakarta REST ExceptionMapper
package org.acme.security.openid.connect.client;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.ext.ExceptionMapper;
import jakarta.ws.rs.ext.Provider;
import org.jboss.resteasy.reactive.ClientWebApplicationException;
@Provider
public class FrontendExceptionMapper implements ExceptionMapper<ClientWebApplicationException> {
@Override
public Response toResponse(ClientWebApplicationException t) {
return Response.status(t.getResponse().getStatus()).build();
}
}
仅添加此异常映射器是为了在测试期间验证当令牌没有预期的角色时,ProtectedResource
返回 403
。如果没有此映射器,Quarkus REST(以前的 RESTEasy Reactive)会将从 REST 客户端调用中转义的异常正确转换为 500
,以避免泄漏来自下游资源(例如 ProtectedResource
)的信息。但是,在测试中,无法断言 500
是由授权异常引起的,而不是由某些内部错误引起的。
配置应用程序
准备好代码后,您就可以配置应用程序了
# Configure 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 ineffective when running the application in JVM or Native modes but only in dev and test modes.
quarkus.keycloak.devservices.realm-path=quarkus-realm.json
# Configure OIDC Client
quarkus.oidc-client.auth-server-url=${quarkus.oidc.auth-server-url}
quarkus.oidc-client.client-id=${quarkus.oidc.client-id}
quarkus.oidc-client.credentials.secret=${quarkus.oidc.credentials.secret}
quarkus.oidc-client.grant.type=password
quarkus.oidc-client.grant-options.password.username=alice
quarkus.oidc-client.grant-options.password.password=alice
# Configure REST clients
%prod.port=8080
%dev.port=8080
%test.port=8081
org.acme.security.openid.connect.client.RestClientWithOidcClientFilter/mp-rest/url=https://:${port}/protected
org.acme.security.openid.connect.client.RestClientWithTokenHeaderParam/mp-rest/url=https://:${port}/protected
org.acme.security.openid.connect.client.RestClientWithTokenPropagationFilter/mp-rest/url=https://:${port}/protected
前面的配置引用了 Keycloak,ProtectedResource
使用 Keycloak 来验证传入的访问令牌,OidcClient
使用 Keycloak 通过 password
授权为用户 alice
获取令牌。两个 REST 客户端都指向 ProtectedResource
的 HTTP 地址。
在 quarkus.oidc.auth-server-url 中添加 %prod. 配置文件前缀可确保在开发或测试模式下运行应用程序时,Dev Services for Keycloak 会为您启动一个容器。有关更多信息,请参阅在开发模式下运行应用程序部分。 |
启动和配置 Keycloak 服务器
在开发或测试模式下运行应用程序时,请勿启动 Keycloak 服务器;Dev Services for Keycloak 会启动一个容器。有关更多信息,请参阅在开发模式下运行应用程序部分。确保将 realm 配置文件 放在类路径上的 target/classes 目录中。此放置可确保该文件在开发模式下自动导入。但是,如果您已经构建了完整解决方案,则无需将 realm 文件添加到类路径,因为构建过程已经完成了此操作。 |
要启动 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 服务器。
以 admin
用户身份登录以访问 Keycloak 管理控制台。密码是 admin
。
导入 realm 配置文件 以创建一个新 realm。有关更多详细信息,请参阅 Keycloak 文档中有关如何创建新 realm 的信息。
此 quarkus
realm 文件添加了 frontend
客户端,以及 alice
和 admin
用户。alice
具有 user
角色。admin
具有 user
和 admin
角色。
在开发模式下运行应用程序
要在开发模式下运行应用程序,请使用
quarkus dev
./mvnw quarkus:dev
./gradlew --console=plain quarkusDev
Dev Services for Keycloak 启动 Keycloak 容器并导入 quarkus-realm.json
。
当出现提示时,登录到 OpenID Connect Dev UI 提供的 Single Page Application
-
以
admin
身份登录,密码为admin
。此用户具有admin
和user
角色。-
访问
/frontend/user-name-with-propagated-token
,它会返回200
。 -
访问
/frontend/admin-name-with-propagated-token
,它会返回200
。
-
-
注销并以
alice
身份重新登录,密码为alice
。此用户具有user
角色。-
访问
/frontend/user-name-with-propagated-token
,它会返回200
。 -
访问
/frontend/admin-name-with-propagated-token
,它会返回403
。
-
您已经测试了 FrontendResource
可以传播来自 OpenID Connect Dev UI 的访问令牌。
在 JVM 模式下运行应用程序
在开发模式下探索完应用程序后,您可以将其作为标准的 Java 应用程序运行。
首先,编译它
quarkus build
./mvnw install
./gradlew build
然后,运行它
java -jar target/quarkus-app/quarkus-run.jar
在 Native 模式下运行应用程序
您可以将此演示编译为本机代码;无需修改。
这意味着您不再需要在生产环境中安装 JVM,因为运行时技术已包含在生成的二进制文件中,并且经过优化可以以最少的资源运行。
编译需要更长的时间,因此默认情况下此步骤已关闭。要再次构建,请启用 native
配置文件
quarkus build --native
./mvnw install -Dnative
./gradlew build -Dquarkus.native.enabled=true
稍等片刻,当构建完成后,您可以直接运行本机二进制文件
./target/security-openid-connect-quickstart-1.0.0-SNAPSHOT-runner
测试应用程序
有关在开发模式下测试应用程序的更多信息,请参阅前面的在开发模式下运行应用程序部分。
您可以使用 curl
测试在 JVM 或 Native 模式下启动的应用程序。
获取 alice
的访问令牌
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' \
)
使用此令牌调用 /frontend/user-name-with-propagated-token
。此命令返回 200
状态代码和名称 alice
curl -i -X GET \
https://:8080/frontend/user-name-with-propagated-token \
-H "Authorization: Bearer "$access_token
使用相同的令牌调用 /frontend/admin-name-with-propagated-token
。与前面的命令相比,此命令返回 403
,因为 alice
仅具有 user
角色
curl -i -X GET \
https://:8080/frontend/admin-name-with-propagated-token \
-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' \
)
使用此令牌调用 /frontend/user-name-with-propagated-token
。此命令返回 200
状态代码和名称 admin
curl -i -X GET \
https://:8080/frontend/user-name-with-propagated-token \
-H "Authorization: Bearer "$access_token
使用相同的令牌调用 /frontend/admin-name-with-propagated-token
。此命令还会返回 200
状态代码和名称 admin
,因为 admin
具有 user
和 admin
角色
curl -i -X GET \
https://:8080/frontend/admin-name-with-propagated-token \
-H "Authorization: Bearer "$access_token
接下来,检查 FrontendResource
方法,该方法不传播现有令牌,而是使用 OidcClient
来获取和传播令牌。如前所示,OidcClient
配置为获取 alice
用户的令牌。
curl -i -X GET \
https://:8080/frontend/user-name-with-oidc-client-token
此命令返回 200
状态代码和名称 alice
。
curl -i -X GET \
https://:8080/frontend/admin-name-with-oidc-client-token
与前面的命令相比,此命令返回 403
状态代码。
接下来,测试以编程方式创建的 OIDC 客户端是否在反应式和命令式(阻塞)模式下都使用 RestClientWithTokenHeaderParam
正确获取和传播令牌。
调用 /user-name-with-oidc-client-token-header-param
。此命令返回 200
状态代码和名称 alice
curl -i -X GET \
https://:8080/frontend/user-name-with-oidc-client-token-header-param
调用 /admin-name-with-oidc-client-token-header-param
。与前面的命令相比,此命令返回 403
状态代码
curl -i -X GET \
https://:8080/frontend/admin-name-with-oidc-client-token-header-param
接下来,测试在阻塞模式下使用 OIDC 客户端的端点。
调用 /user-name-with-oidc-client-token-header-param-blocking
。此命令返回 200
状态代码和名称 alice
curl -i -X GET \
https://:8080/frontend/user-name-with-oidc-client-token-header-param-blocking
调用 /admin-name-with-oidc-client-token-header-param-blocking
。与前面的命令相比,此命令返回 403
状态代码
curl -i -X GET \
https://:8080/frontend/admin-name-with-oidc-client-token-header-param-blocking