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

在Quarkus(Kotlin)中为静态资源添加HTTP拦截器的方法

在Quarkus(Kotlin)中拦截静态资源请求并实现Cookie认证

Quarkus默认会让Vert.x静态资源处理器优先处理静态资源请求,这些请求不会进入JAX-RS的过滤器链,所以你用@Provider标注的ContainerRequestFilter只能捕获API请求,碰不到静态资源的请求。下面给你三种可行的解决方案:

方案一:用Vert.x全局HTTP过滤器(推荐)

直接基于Quarkus底层的Vert.x路由,在静态资源处理前插入Cookie校验逻辑,能拦截所有请求(包括静态资源)。

代码实现:

创建一个实现VertxRouterCustomizer的类,自定义路由拦截规则:

import io.quarkus.vertx.http.runtime.VertxRouterCustomizer
import io.vertx.ext.web.Router
import io.vertx.ext.web.RoutingContext
import jakarta.enterprise.context.ApplicationScoped

@ApplicationScoped
class StaticResourceAuthFilter : VertxRouterCustomizer {
    override fun customize(router: Router) {
        // 拦截/books/examplediary下的所有请求,优先级高于静态资源处理器
        router.route("/books/examplediary/*").handler(this::validateCookie)
    }

    private fun validateCookie(ctx: RoutingContext) {
        // 获取指定Cookie
        val authCookie = ctx.request().getCookie("your_cookie_name")
        
        if (authCookie == null) {
            // Cookie不存在,返回403禁止访问
            ctx.response()
                .setStatusCode(403)
                .putHeader("Content-Type", "text/plain")
                .end("Access denied")
            return
        }
        
        // Cookie校验通过,继续处理请求
        ctx.next()
    }
}

静态资源默认放在src/main/resources/META-INF/resources/目录下,确保你的books/examplediary目录在这个路径里。

方案二:通过JAX-RS资源类提供受保护的静态资源

把需要保护的静态资源交给JAX-RS处理,这样就能复用你原来的JAX-RS过滤器。

步骤1:创建JAX-RS资源类

import jakarta.ws.rs.GET
import jakarta.ws.rs.Path
import jakarta.ws.rs.PathParam
import jakarta.ws.rs.core.Response
import java.net.URL

@Path("/books/examplediary")
class ProtectedStaticResource {

    @GET
    @Path("/{fileName:.*}")
    fun getProtectedResource(@PathParam("fileName") fileName: String): Response {
        // 加载静态资源文件
        val resourceUrl: URL? = Thread.currentThread()
            .contextClassLoader
            .getResource("META-INF/resources/books/examplediary/$fileName")
        
        return resourceUrl?.let {
            Response.ok(it.openStream()).build()
        } ?: Response.status(404).entity("Resource not found").build()
    }
}

步骤2:调整原有过滤器的路径匹配

修改CookieValidationFilter,让它匹配JAX-RS处理的静态资源路径:

import jakarta.ws.rs.container.ContainerRequestContext
import jakarta.ws.rs.container.ContainerRequestFilter
import jakarta.ws.rs.core.Response
import jakarta.ws.rs.ext.Provider

@Provider
class CookieValidationFilter : ContainerRequestFilter {
    override fun filter(requestContext: ContainerRequestContext) {
        val requestPath = requestContext.uriInfo.path
        
        // 匹配所有/examplediary下的资源请求
        if (requestPath.startsWith("/books/examplediary/")) {
            val authCookie = requestContext.cookies["your_cookie_name"]
            
            if (authCookie == null) {
                requestContext.abortWith(
                    Response.status(Response.Status.FORBIDDEN)
                        .entity("Access denied")
                        .build()
                )
            }
        }
    }
}

方案三:用Quarkus Security模块做路径保护

借助Quarkus的Security组件,通过配置或注解保护静态资源路径,配合Cookie认证机制(需要配置对应的Cookie认证器)。

示例配置(application.properties)

# 保护指定静态资源路径,要求用户已认证
quarkus.security.authz.paths."/books/examplediary/*".roles-allowed=authenticated

# 指定使用自定义Cookie认证机制
quarkus.security.authentication=custom
quarkus.security.custom-auth-mechanism-implementation=com.yourpackage.CookieAuthMechanism

自定义Cookie认证器示例

import io.quarkus.security.identity.AuthenticationRequestContext
import io.quarkus.security.identity.IdentityProvider
import io.quarkus.security.identity.SecurityIdentity
import io.quarkus.security.runtime.QuarkusSecurityIdentity
import io.smallrye.mutiny.Uni
import jakarta.enterprise.context.ApplicationScoped
import jakarta.ws.rs.core.Cookie

@ApplicationScoped
class CookieAuthMechanism : IdentityProvider<CookieAuthenticationRequest> {
    override fun getRequestType(): Class<CookieAuthenticationRequest> {
        return CookieAuthenticationRequest::class.java
    }

    override fun authenticate(
        request: CookieAuthenticationRequest,
        context: AuthenticationRequestContext
    ): Uni<SecurityIdentity> {
        val authCookie = request.cookies["your_cookie_name"]
        
        return if (authCookie != null && isValidCookie(authCookie.value)) {
            // 校验通过,构建已认证的身份信息
            Uni.createFrom().item(
                QuarkusSecurityIdentity.builder()
                    .setPrincipal(java.security.Principal { "authenticated-user" })
                    .addRole("authenticated")
                    .build()
            )
        } else {
            // 校验失败,返回空表示认证不通过
            Uni.createFrom().nullItem()
        }
    }

    private fun isValidCookie(cookieValue: String): Boolean {
        // 这里实现你的Cookie值校验逻辑(比如解密、验证签名)
        return cookieValue.isNotEmpty()
    }
}

// 自定义认证请求载体类
class CookieAuthenticationRequest(val cookies: Map<String, Cookie>)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 00:40:56