问题起因:
在Shiro配置类中定义如下:
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(ShiroAuthFilter shiroAuthFilter, SecurityManager securityManager) {
ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
Map<String, Filter> filters = new HashMap<>(1);
filters.put("shiroAuthFilter", shiroAuthFilter);
factoryBean.setFilters(filters);
factoryBean.setSecurityManager(securityManager);
// 必须使用LinkedHashMap来保持有序性
Map<String, String> filterMap = new LinkedHashMap<>();
// anon: Filter that allows access to a path immeidately without performing security checks of any kind.
filterMap.put("/swagger*/**", "anon");
filterMap.put("/v2/api-docs", "anon");
filterMap.put("/test/**", "anon");
filterMap.put("/**", "shiroAuthFilter");
System.out.println(filterMap.keySet());
factoryBean.setFilterChainDefinitionMap(filterMap);
return factoryBean;
}
可以发现,我正确地使用了LinkedHashMap作为存储集合并把filterMap.put("/**", "shiroAuthFilter");
放在了最后,按道理是最后一个过滤的,但结果是访问如/test/2
、/swagger/123
这样的路径也会被自定义的shiroAuthFilter
过滤器拦截
在网上搜索大量资料后发现SpringBoot会自动注册shiroAuthFilter
为全局过滤器,即使只使用了@Component注解。
顺序如下:
2023-10-29 16:29:18.810 DEBUG 24532 --- [ restartedMain] o.s.b.w.s.ServletContextInitializerBeans :
Mapping filters:
filterRegistrationBean urls=[/*] order=2147483647,
com.timqiu.ocos.filter.XssFilter urls=[/*] order=2147483647,
characterEncodingFilter urls=[/*] order=-2147483648,
formContentFilter urls=[/*] order=-9900,
requestContextFilter urls=[/*] order=-105,
shiroAuthFilter urls=[/*] order=2147483647,
shiroFilterFactoryBean urls=[/*] order=2147483647
顺便说下如何开启这个日志:
logging:
level:
web: debug
可以看到,shiroAuthFilter
在shiroFilterFactoryBean
之前,匹配路径为/*
,并且优先级还和shiroFilterFactoryBean
一样!!!!
也就是说,不管请求怎么走,都会先经过shiroAuthFilter
过滤器而不会走shiroFilterFactoryBean
过滤器!!!
那怎么解决呢?当然是禁用掉该过滤器的自动注册功能!!
在SpringBoot官方文档中就说的很清楚如何禁用过滤器的自动注册功能:
Disable Registration of a Servlet or Filter
As described earlier, any Servlet
or Filter
beans are registered with the servlet container automatically. To disable registration of a particular Filter
or Servlet
bean, create a registration bean for it and mark it as disabled, as shown in the following example:
@Configuration(proxyBeanMethods = false)
public class MyFilterConfiguration {
@Bean
public FilterRegistrationBean<MyFilter> registration(MyFilter filter) {
FilterRegistrationBean<MyFilter> registration = new FilterRegistrationBean<>(filter);
registration.setEnabled(false);
return registration;
}
}
链接如下:Spring Boot Reference Documentation
禁用之后,再次查看日志,发现没有shiroAuthFilter
这一项了,正常访问没有被过滤的网址,问题解决。