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

JavaEE中Pac4j异常处理问题:自定义权限异常无法触发指定错误页

解决pac4j包装异常导致web.xml错误页不生效的问题

问题根源

pac4j的org.pac4j.core.engine.AbstractExceptionAwareLogic#handleException方法会将捕获到的ServletException二次包装为RuntimeException,导致web.xml中基于自定义PermissionDeniedException的错误页映射无法识别原异常类型,进而无法触发对应错误页。

无需自定义SecurityFilter的解决方案

方案1:自定义SecurityLogic覆盖异常处理逻辑

继承pac4j默认的DefaultSecurityLogic,重写handleException方法,针对ServletException直接抛出而非包装:

public class CustomSecurityLogic extends DefaultSecurityLogic {
    @Override
    protected RuntimeException handleException(Exception e, WebContext context, SecurityConfig securityConfig) {
        // 对ServletException直接抛出,保留原异常类型
        if (e instanceof ServletException) {
            throw (ServletException) e;
        }
        // 其他异常沿用原有处理逻辑
        return super.handleException(e, context, securityConfig);
    }
}

在web.xml的SecurityFilter配置中指定自定义逻辑类:

<filter>
    <filter-name>securityFilter</filter-name>
    <filter-class>org.pac4j.core.engine.SecurityFilter</filter-class>
    <init-param>
        <param-name>securityLogic</param-name>
        <param-value>com.your.package.CustomSecurityLogic</param-value>
    </init-param>
    <!-- 其他pac4j配置参数 -->
</filter>

方案2:注册自定义ExceptionHandler

实现pac4j的ExceptionHandler接口,在异常被包装前拦截并处理目标异常:

public class CustomExceptionHandler implements ExceptionHandler {
    @Override
    public void handleException(Exception e, WebContext context) {
        // 识别嵌套PermissionDeniedException的ServletException,直接抛出
        if (e instanceof ServletException se) {
            if (se.getRootCause() instanceof PermissionDeniedException) {
                throw se;
            }
        }
        // 非目标异常交给默认处理器处理
        DefaultExceptionHandler.INSTANCE.handleException(e, context);
    }
}

在pac4j的Config初始化时注册该处理器:

Config pac4jConfig = new Config(yourClient);
pac4jConfig.setExceptionHandler(new CustomExceptionHandler());

方案3:调整web.xml错误页映射(快速适配)

修改web.xml,将RuntimeException映射到目标错误页,然后在错误页中判断原异常类型:

<error-page>
    <exception-type>java.lang.RuntimeException</exception-type>
    <location>/access.xhtml</location>
</error-page>

在/access.xhtml中通过EL表达式获取根异常并判断:

<ui:fragment rendered="#{requestScope['jakarta.servlet.error.exception'].rootCause instanceof com.your.package.PermissionDeniedException}">
    <!-- 权限不足提示内容 -->
</ui:fragment>
<ui:fragment rendered="#{not (requestScope['jakarta.servlet.error.exception'].rootCause instanceof com.your.package.PermissionDeniedException)}">
    <!-- 其他运行时异常提示内容 -->
</ui:fragment>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 11:06:02