1.3. OIDC 响应过滤器
您可以通过注册一个或多个 OidcResponseFilter 实现来过滤对 OIDC 客户端请求的响应,该实现可以检查响应状态、标头和正文,以记录它们或执行其他操作。
您可以有一个过滤器,截获对所有 OIDC 客户端请求的响应,或使用 @OidcEndpoint 注解将此过滤器应用到仅针对特定 OIDC 客户端请求的响应。例如:
package io.quarkus.it.keycloak;
import jakarta.enterprise.context.ApplicationScoped;
import org.jboss.logging.Logger;
import io.quarkus.arc.Unremovable;
import io.quarkus.oidc.common.OidcEndpoint;
import io.quarkus.oidc.common.OidcEndpoint.Type;
import io.quarkus.oidc.common.OidcResponseFilter;
import io.quarkus.oidc.common.runtime.OidcConstants;
@ApplicationScoped
@Unremovable
@OidcEndpoint(value = Type.TOKEN)
public class TokenEndpointResponseFilter implements OidcResponseFilter {
private static final Logger LOG = Logger.getLogger(TokenEndpointResponseFilter.class);
@Override
public void filter(OidcResponseContext rc) {
String contentType = rc.responseHeaders().get("Content-Type");
if (contentType.equals("application/json")
&& "refresh_token".equals(rc.requestProperties().get(OidcConstants.GRANT_TYPE))
&& rc.responseBody().toJsonObject().containsKey("refresh_token")) {
LOG.debug("Tokens have been refreshed");
}
}
}
package io.quarkus.it.keycloak;
import jakarta.enterprise.context.ApplicationScoped;
import org.jboss.logging.Logger;
import io.quarkus.arc.Unremovable;
import io.quarkus.oidc.common.OidcEndpoint;
import io.quarkus.oidc.common.OidcEndpoint.Type;
import io.quarkus.oidc.common.OidcResponseFilter;
import io.quarkus.oidc.common.runtime.OidcConstants;
@ApplicationScoped
@Unremovable
@OidcEndpoint(value = Type.TOKEN)
public class TokenEndpointResponseFilter implements OidcResponseFilter {
private static final Logger LOG = Logger.getLogger(TokenEndpointResponseFilter.class);
@Override
public void filter(OidcResponseContext rc) {
String contentType = rc.responseHeaders().get("Content-Type");
if (contentType.equals("application/json")
&& "refresh_token".equals(rc.requestProperties().get(OidcConstants.GRANT_TYPE))
&& rc.responseBody().toJsonObject().containsKey("refresh_token")) {
LOG.debug("Tokens have been refreshed");
}
}
}
OidcResponseFilter 可以通过准备 io.vertx.mutiny.core.buffer.Buffer 的实例来自定义响应正文,并将其设置为响应上下文的属性,例如:
package io.quarkus.it.keycloak;
import jakarta.enterprise.context.ApplicationScoped;
import io.quarkus.arc.Unremovable;
import io.quarkus.oidc.common.OidcEndpoint;
import io.quarkus.oidc.common.OidcEndpoint.Type;
import io.quarkus.oidc.common.OidcRequestContextProperties;
import io.quarkus.oidc.common.OidcResponseFilter;
import io.vertx.core.json.JsonObject;
import io.vertx.mutiny.core.buffer.Buffer;
@ApplicationScoped
@Unremovable
@OidcEndpoint(value = Type.TOKEN)
public class TokenResponseFilter implements OidcResponseFilter {
@Override
public void filter(OidcResponseContext rc) {
JsonObject body = rc.responseBody().toJsonObject();
// JSON `scope` property has multiple values separated by a comma character.
// It must be replaced with a space character.
String scope = body.getString("scope");
body.put("scope", scope.replace(",", " "));
rc.responseBody(Buffer.buffer(body.toString()));
}
}
package io.quarkus.it.keycloak;
import jakarta.enterprise.context.ApplicationScoped;
import io.quarkus.arc.Unremovable;
import io.quarkus.oidc.common.OidcEndpoint;
import io.quarkus.oidc.common.OidcEndpoint.Type;
import io.quarkus.oidc.common.OidcRequestContextProperties;
import io.quarkus.oidc.common.OidcResponseFilter;
import io.vertx.core.json.JsonObject;
import io.vertx.mutiny.core.buffer.Buffer;
@ApplicationScoped
@Unremovable
@OidcEndpoint(value = Type.TOKEN)
public class TokenResponseFilter implements OidcResponseFilter {
@Override
public void filter(OidcResponseContext rc) {
JsonObject body = rc.responseBody().toJsonObject();
// JSON `scope` property has multiple values separated by a comma character.
// It must be replaced with a space character.
String scope = body.getString("scope");
body.put("scope", scope.replace(",", " "));
rc.responseBody(Buffer.buffer(body.toString()));
}
}