Shiro自定义过滤器会执行两次?看我怎么给你解决

文章讲述了在使用自定义ShiroFilter处理JWT验证时遇到的问题,即过滤器在一次请求中被调用两次。作者通过复现问题、分析原因,发现是因为自定义过滤器同时在ShiroFilterChain和全局过滤器中执行。为了解决这个问题,文章提供了一个解决方案,即通过FilterRegistrationBean设置过滤器为非启用状态,从而避免在全局过滤器链中执行。
摘要由CSDN通过智能技术生成

 关注“Java架构栈”微信公众号,回复暗号【Java面试题】即可获取大厂面试题。

最近九哥的一个学生在使用自定义ShiroFilter处理JWT校验时,发现自己写的Filter在处理一次请求时会被执行两次。这个问题困扰了他一个下午都没有解决,最后不得不求助我来帮忙,那我们就来复现一下这个问题,并给出对应的解决方案吧。

 问题复现

为了复现这个bug,我们先来自定义一个过滤器TokenFilter,代码如下:

/**
 * 自定义shiro过滤器
 */
@Component("jwt")
@Slf4j
public class TokenFilter extends AccessControlFilter {
    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
        // 演示问题,省略调具体业务代码....
        log.debug("=============TokenFilter===============");
        // 演示问题,省略调具体业务代码....
        return true;
    }

    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        // 演示问题,省略调具体业务代码....
        return false;
    }
}

接着还需要有个Shiro配置类,代码如下:

@Configuration
public class ShiroConfig {
    @Bean
    public ShiroFilterChainDefinition shiroFilterChainDefinition(){
        DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition();
        // 白名单
        chainDefinition.addPathDefinition("/user/login","anon");
        chainDefinition.addPathDefinition("/user/regist","anon");
        chainDefinition.addPathDefinition("/error","anon");
        // 让自定义shiro过滤器 jwt(jwt是自定的过滤器的IOC容器中的名字)处理指定的url
        chainDefinition.addPathDefinition("/index/category-recommends","jwt");
        return chainDefinition;
    }
    // 省略其他无关代码
}

最后我们可以执行一次Post请求,观察上面这个自定义过滤器的执行情况。

从控制台的信息中我们可以看出,日志被打印了两次,那么这个问题到底是怎么产生的呢?

 原因分析

为了定位上述问题,我们可以在自定义过滤器中打上断点。

通过断点我们可以清晰的看到,自定义的filter确实被执行了两次。其中第一次是作为shiroFilterChain中的过滤器被shiroFilter调用的,另外又在全局过滤器中注册了我们自定义的过滤器,这就导致了在shirofilter之后,该过滤器又被被执行了一次!

 解决方案

基于上述分析,要想解决这个问题,我们只需要让自定义过滤器不出现在全局过滤器中即可。我们可以编写一个FilterConfig配置类来解决这个问题,代码如下。

@Configuration
public class MyFilterConfig {

    @Bean
    public FilterRegistrationBean<TokenFilter> tokenFilterFilterRegistrationBean(TokenFilter tokenFilter){
        FilterRegistrationBean<TokenFilter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(tokenFilter);
        // 不让该filter出现在全局过滤器链中
        registrationBean.setEnabled(false);
        return registrationBean;
    }
}

添加了该配置类后,我们再次启动应用,并再次观察断点情况。

现在你会发现,Filter处理一次请求会被执行两次的情况就没有了,现在你知道如何解决这个bug了吗?关注Java架构栈,干货天天多不断哦!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值