Quarkus OIDC 安全链路时序图

发布于:2025-08-29 ⋅ 阅读:(17) ⋅ 点赞:(0)
  • 请求进入
  • 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 方法执行完后,返回给客户端前执行。

网站公告

今日签到

点亮在社区的每一天
去签到