Spring Boot3集成Shiro1.5.3时JWT过滤器不生效问题排查
问题:Spring Boot 3 + Shiro 1.5.3 自定义JWT过滤器未拦截请求
环境
- Spring Boot 3
- Shiro 1.5.3
问题详情
配置了基于JWT的Shiro自定义过滤器,但过滤器未按预期拦截请求,调试发现请求完全没有进入过滤器的isAccessAllowed()方法。
现有代码
ShiroConfig.java
@Configuration public class ShiroConfig { // Other configurations... @Bean("lifecycleBeanPostProcessor") public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() { return new LifecycleBeanPostProcessor(); } @Bean("securityManager") public SecurityManager securityManager(UserRealm realm) { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(realm); return securityManager; } @Bean("shiroFilter") public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") SecurityManager securityManager) { ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean(); shiroFilter.setSecurityManager(securityManager); Map<String, Filter> map = new HashMap<>(); map.put("jwt", new UserFilter()); shiroFilter.setFilters(map); Map<String, String> filterMap = new LinkedHashMap<>(); filterMap.put("/**", "jwt"); shiroFilter.setFilterChainDefinitionMap(filterMap); return shiroFilter; } }
自定义过滤器UserFilter.java
@Slf4j @Component @Scope("prototype") public class UserFilter extends BasicHttpAuthenticationFilter { @Override protected boolean executeLogin(ServletRequest request, ServletResponse response) throws ServiceException { //... } @Override protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) { try { executeLogin(request, response); return true; } catch (Exception e) { return false; } } }
排查与解决建议
1. 版本兼容性问题
Shiro 1.5.3不支持Spring Boot 3(Spring Boot 3基于Spring Framework 6,要求Servlet 5.0+),版本不兼容会导致过滤器无法正常注册生效。直接升级Shiro到1.12.0及以上版本,该版本已完成对Spring Boot 3和Servlet 5的适配。
2. 手动注册Shiro过滤器
Spring Boot 3中,仅通过ShiroFilterFactoryBean创建Bean无法自动将Shiro过滤器注册到Servlet容器中,需要手动配置注册:
@Bean public FilterRegistrationBean<ShiroFilter> shiroFilterRegistrationBean(@Qualifier("shiroFilter") ShiroFilterFactoryBean shiroFilterFactoryBean) throws Exception { FilterRegistrationBean<ShiroFilter> registrationBean = new FilterRegistrationBean<>(); // 获取ShiroFilter实例 ShiroFilter shiroFilter = (ShiroFilter) shiroFilterFactoryBean.getObject(); registrationBean.setFilter(shiroFilter); // 设置最高优先级,确保Shiro最先拦截请求 registrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE); // 匹配所有请求路径 registrationBean.addUrlPatterns("/*"); return registrationBean; }
3. 修正自定义过滤器的实例化方式
你当前在配置中直接new UserFilter(),但UserFilter标注了@Component,这种混合方式会导致过滤器脱离Spring容器管理,丢失依赖注入或生命周期处理。改为从Spring容器注入:
@Configuration public class ShiroConfig { // 注入Spring管理的UserFilter实例 @Autowired private UserFilter userFilter; // ...其他Bean配置... @Bean("shiroFilter") public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") SecurityManager securityManager) { ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean(); shiroFilter.setSecurityManager(securityManager); Map<String, Filter> map = new HashMap<>(); // 使用Spring容器中的实例 map.put("jwt", userFilter); shiroFilter.setFilters(map); Map<String, String> filterMap = new LinkedHashMap<>(); filterMap.put("/**", "jwt"); shiroFilter.setFilterChainDefinitionMap(filterMap); return shiroFilter; } }
4. 检查过滤器优先级
如果项目中存在其他全局过滤器(如Spring Security过滤器、自定义全局过滤器),优先级高于Shiro过滤器时会导致请求被提前处理。通过上述FilterRegistrationBean设置setOrder(Ordered.HIGHEST_PRECEDENCE)确保Shiro过滤器最先执行。
内容的提问来源于stack exchange,提问作者Alpha Beta
相关产品推荐
相关产品推荐

