关注“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架构栈,干货天天多不断哦!