- 请求进入
- OIDC 验证
SecurityIdentityAugmentor
ContainerRequestFilter
- Resource 方法
ContainerResponseFilter
- 响应返回
🖼️ 时序图(文字版)
┌─────────────────────────────┐
│ HTTP 请求 │
└──────────────┬──────────────┘
│
▼
┌───────────────────┐
│ OIDC 验证 (token) │
│ 构建 SecurityIdentity │
└─────────┬─────────┘
│
▼
┌───────────────────────────────┐
│ SecurityIdentityAugmentor │
│ (增强身份 / 单点登录检查等) │
└─────────────┬─────────────────┘
│
▼
┌───────────────────────────────┐
│ ContainerRequestFilter │
│ (请求级拦截,能拿到identity)│
└─────────────┬─────────────────┘
│
▼
┌───────────────────┐
│ Resource 方法调用 │
└─────────┬─────────┘
│
▼
┌───────────────────────────────┐
│ ContainerResponseFilter │
│ (统一返回值/异常包装) │
└─────────────┬─────────────────┘
│
▼
┌─────────────────────────────┐
│ HTTP 响应 │
└─────────────────────────────┘
1️⃣ Demo 项目结构
最小可运行的 Quarkus Demo,包含以下三个类:
SecurityIdentityAugmentor
→ 增强身份,打印日志。ContainerRequestFilter
→ 请求级别过滤器,打印日志。ContainerResponseFilter
→ 响应级别过滤器,打印日志。
这样你启动应用、访问一个 REST 接口,就能看到日志执行顺序。
src
└── main
└── java
└── com.example.demo
├── LoggingIdentityAugmentor.java
├── LoggingRequestFilter.java
├── LoggingResponseFilter.java
└── HelloResource.java
2️⃣ 代码示例
2.1 SecurityIdentityAugmentor
package com.example.demo;
import io.quarkus.security.identity.SecurityIdentity;
import io.quarkus.security.identity.SecurityIdentityAugmentor;
import io.quarkus.security.identity.request.SecurityIdentityAugmentorRequest;
import jakarta.enterprise.context.ApplicationScoped;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.CompletableFuture;
@ApplicationScoped
public class LoggingIdentityAugmentor implements SecurityIdentityAugmentor {
@Override
public CompletionStage<SecurityIdentity> augment(SecurityIdentity identity,
SecurityIdentityAugmentorRequest request) {
System.out.println(">>> [Augmentor] SecurityIdentityAugmentor executed, user = "
+ identity.getPrincipal().getName());
return CompletableFuture.completedFuture(identity);
}
}
2.2 ContainerRequestFilter
package com.example.demo;
import io.quarkus.security.identity.SecurityIdentity;
import jakarta.annotation.Priority;
import jakarta.inject.Inject;
import jakarta.ws.rs.Priorities;
import jakarta.ws.rs.container.ContainerRequestContext;
import jakarta.ws.rs.container.ContainerRequestFilter;
import jakarta.ws.rs.ext.Provider;
@Provider
@Priority(Priorities.AUTHENTICATION + 10) // 在认证之后执行
public class LoggingRequestFilter implements ContainerRequestFilter {
@Inject
SecurityIdentity identity;
@Override
public void filter(ContainerRequestContext requestContext) {
System.out.println(">>> [RequestFilter] Executed for path = "
+ requestContext.getUriInfo().getPath()
+ ", user = " + identity.getPrincipal().getName());
}
}
2.3 ContainerResponseFilter
package com.example.demo;
import jakarta.ws.rs.container.ContainerRequestContext;
import jakarta.ws.rs.container.ContainerResponseContext;
import jakarta.ws.rs.container.ContainerResponseFilter;
import jakarta.ws.rs.ext.Provider;
import java.io.IOException;
@Provider
public class LoggingResponseFilter implements ContainerResponseFilter {
@Override
public void filter(ContainerRequestContext requestContext,
ContainerResponseContext responseContext) throws IOException {
System.out.println(">>> [ResponseFilter] Executed, status = " + responseContext.getStatus());
}
}
2.4 REST Resource
package com.example.demo;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.core.Response;
@Path("/hello")
public class HelloResource {
@GET
public Response hello() {
System.out.println(">>> [Resource] Hello endpoint executed");
return Response.ok("Hello from Quarkus!").build();
}
}
3️⃣ 运行效果
启动应用后,访问:
curl http://localhost:8080/hello
日志输出顺序应当是:
>>> [Augmentor] SecurityIdentityAugmentor executed, user = <user>
>>> [RequestFilter] Executed for path = hello, user = <user>
>>> [Resource] Hello endpoint executed
>>> [ResponseFilter] Executed, status = 200
这样,你就能清楚看到 Augmentor → RequestFilter → Resource → ResponseFilter 的调用顺序。
✅ 总结
SecurityIdentityAugmentor
→ 在 认证阶段(构建SecurityIdentity
时执行),比ContainerRequestFilter
更早。ContainerRequestFilter
→ 在 认证完成后、进入 Resource 前执行。ContainerResponseFilter
→ 在 Resource 方法执行完后,返回给客户端前执行。