如何在quarkus-oidc中自定义403、401错误状态码的响应体
Quarkus OIDC 自定义401/403响应体实现方案
Quarkus OIDC的认证授权异常触发时机早于普通JAX-RS请求链路,因此不能直接复用Spring Boot的异常处理逻辑,可通过以下两种方案实现自定义响应:
方案1:自定义Security异常Mapper(推荐,兼容性最强)
该方案适配所有Quarkus安全模块抛出的认证授权异常,不需要修改底层HTTP逻辑:
- 首先确认项目依赖已引入
quarkus-resteasy-reactive或quarkus-resteasy扩展 - 分别创建401、403对应的异常Mapper,添加
@Priority(1)注解覆盖Quarkus默认的异常处理实现
401(未认证)响应自定义代码示例
import io.quarkus.security.AuthenticationFailedException; import jakarta.annotation.Priority; import jakarta.ws.rs.core.Response; import jakarta.ws.rs.ext.ExceptionMapper; import jakarta.ws.rs.ext.Provider; @Provider @Priority(1) public class CustomAuthFailedMapper implements ExceptionMapper<AuthenticationFailedException> { @Override public Response toResponse(AuthenticationFailedException exception) { // 自定义响应体结构,可根据业务需求调整字段 var errorResp = new CustomError(); errorResp.setCode(401); errorResp.setMsg("无效的访问凭证,请重新登录"); return Response.status(Response.Status.UNAUTHORIZED) .entity(errorResp) .build(); } }
403(未授权)响应自定义代码示例
import io.quarkus.security.ForbiddenException; import jakarta.annotation.Priority; import jakarta.ws.rs.core.Response; import jakarta.ws.rs.ext.ExceptionMapper; import jakarta.ws.rs.ext.Provider; @Provider @Priority(1) public class CustomForbiddenMapper implements ExceptionMapper<ForbiddenException> { @Override public Response toResponse(ForbiddenException exception) { var errorResp = new CustomError(); errorResp.setCode(403); errorResp.setMsg("当前账号无权限访问该资源"); return Response.status(Response.Status.FORBIDDEN) .entity(errorResp) .build(); } }
- 在
application.properties中添加配置,禁用OIDC默认的登录挑战头,避免浏览器自动弹出登录框:
quarkus.oidc.authentication.challenge-enabled=false
方案2:Vert.x全局错误处理器(覆盖所有HTTP层异常)
如果方案1无法覆盖token解析失败、OIDC服务连接异常等边缘场景,可以直接注册Vert.x路由器的全局错误处理器:
import io.quarkus.vertx.http.RouterCustomizer; import io.vertx.core.json.Json; import io.vertx.ext.web.Router; import jakarta.enterprise.context.ApplicationScoped; @ApplicationScoped public class GlobalHttpErrorHandler implements RouterCustomizer { @Override public void accept(Router router) { // 处理401异常 router.errorHandler(401, ctx -> { var resp = Json.of("code", 401, "msg", "访问未授权"); ctx.response() .setStatusCode(401) .putHeader("Content-Type", "application/json") .end(resp.encode()); }); // 处理403异常 router.errorHandler(403, ctx -> { var resp = Json.of("code", 403, "msg", "无访问权限"); ctx.response() .setStatusCode(403) .putHeader("Content-Type", "application/json") .end(resp.encode()); }); } }
注意事项
- 不要使用通用
ExceptionMapper<RuntimeException>捕获这两类异常,默认优先级低于Quarkus安全模块内置的Mapper,会出现不生效问题 - 如果项目同时使用了多个安全扩展,优先选择方案1,不会影响其他安全逻辑的正常运行
- 自定义响应需要返回JSON格式时,确保项目已引入
quarkus-resteasy-reactive-jackson或对应的JSON序列化依赖
内容的提问来源于stack exchange,提问作者Utesting
相关产品推荐
相关产品推荐

