You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于Kong OIDC传递的x-userinfo头在Quarkus中实现自定义认证

基于Kong OIDC透传头的Quarkus身份认证实现方案

Kong完成OIDC认证后会将用户信息通过x-userinfo请求头透传给下游Quarkus应用,你可以通过以下步骤实现基于该头的身份认证:

1. 引入核心依赖

首先在项目中引入Quarkus安全相关基础依赖,以Maven为例:

<dependencies>
    <dependency>
        <groupId>io.quarkus</groupId>
        <artifactId>quarkus-security</artifactId>
    </dependency>
    <!-- REST层依赖,根据你项目实际使用的框架引入即可 -->
    <dependency>
        <groupId>io.quarkus</groupId>
        <artifactId>quarkus-resteasy-reactive-jackson</artifactId>
    </dependency>
</dependencies>

2. 定义用户信息映射实体

根据你x-userinfo头内的JSON结构定义对应实体类,用于反序列化:

public class UserInfo {
    // 用户唯一标识,对应OIDC的sub字段
    private String sub;
    private String email;
    private String name;
    // 用户权限角色列表
    private List<String> roles;
    // 按需添加其他字段,补全getter、setter方法
}

3. 实现认证拦截器

通过优先级最高的认证层拦截器解析请求头,构造Quarkus安全上下文:

import io.quarkus.security.identity.SecurityIdentity;
import io.quarkus.security.runtime.QuarkusSecurityIdentity;
import jakarta.annotation.Priority;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.ws.rs.Priorities;
import jakarta.ws.rs.container.ContainerRequestContext;
import jakarta.ws.rs.container.ContainerRequestFilter;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.ext.Provider;
import com.fasterxml.jackson.databind.ObjectMapper;

@Provider
@Priority(Priorities.AUTHENTICATION)
@ApplicationScoped
public class KongHeaderAuthFilter implements ContainerRequestFilter {

    private final ObjectMapper objectMapper;

    // 注入Jackson序列化工具
    public KongHeaderAuthFilter(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    @Override
    public void filter(ContainerRequestContext requestContext) {
        String userInfoHeader = requestContext.getHeaderString("x-userinfo");
        // 头不存在直接返回401未认证
        if (userInfoHeader == null || userInfoHeader.isBlank()) {
            requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).build());
            return;
        }
        UserInfo userInfo;
        try {
            // 若你的x-userinfo是Base64编码,需要先解码再反序列化:
            // userInfoHeader = new String(Base64.getDecoder().decode(userInfoHeader));
            userInfo = objectMapper.readValue(userInfoHeader, UserInfo.class);
        } catch (Exception e) {
            requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).build());
            return;
        }
        // 构造安全上下文
        SecurityIdentity identity = QuarkusSecurityIdentity.builder()
                .setPrincipal(() -> userInfo.getSub())
                .addRoles(userInfo.getRoles())
                .addAttribute("fullUserInfo", userInfo)
                .build();
        // 存入请求上下文
        requestContext.setProperty(SecurityIdentity.class.getName(), identity);
    }
}

如果你使用的是Quarkus 2.x及更早版本,将所有jakarta包导入替换为javax即可

4. 业务层获取用户信息

你可以在任意Bean中直接注入SecurityIdentity获取认证后的用户信息:

import io.quarkus.security.identity.SecurityIdentity;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.annotation.security.RolesAllowed;

@Path("/user")
public class UserController {

    @Inject
    SecurityIdentity securityIdentity;

    @GET
    @Path("/current")
    // 角色校验注解直接生效,只要之前构造Identity时正确传入了roles
    @RolesAllowed("user")
    public UserInfo getCurrentUser() {
        return securityIdentity.getAttribute("fullUserInfo");
    }
}

生产环境配置注意

  • 必须在Kong层配置拦截并丢弃客户端主动携带的x-userinfo头,仅保留Kong OIDC插件生成的头,避免攻击者伪造身份
  • 建议配置Quarkus仅监听内网地址,避免服务直接暴露到公网被绕过Kong访问

内容的提问来源于stack exchange,提问作者Trevor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 10:42:00