Shiro执行clearCachedAuthenticationInfo时缓存未清致会话无法清除,求解决方案
解决Shiro执行clearCachedAuthenticationInfo时缓存为null导致会话无法清除的问题
我之前也踩过这个Shiro缓存的坑!从你贴的代码来看,核心问题是getAvailableAuthenticationCache()返回了null,导致后续清除认证缓存的逻辑完全没执行,最终造成会话无法正常清除。下面我给你几个针对性的解决方案:
1. 确认Realm已正确开启认证缓存
Shiro的认证缓存默认是关闭的,必须手动开启才能让getAvailableAuthenticationCache()返回有效缓存实例:
Java配置方式
@Bean public CustomShiroRealm customShiroRealm() { CustomShiroRealm realm = new CustomShiroRealm(); // 开启认证缓存 realm.setAuthenticationCachingEnabled(true); // 指定缓存名称(需和缓存管理器中的配置对应) realm.setAuthenticationCacheName("authenticationCache"); return realm; }
XML配置方式
<bean id="customShiroRealm" class="com.yourpackage.CustomShiroRealm"> <!-- 开启认证缓存 --> <property name="authenticationCachingEnabled" value="true"/> <!-- 指定缓存名称 --> <property name="authenticationCacheName" value="authenticationCache"/> </bean>
2. 确保缓存管理器已正确配置并关联到SecurityManager
如果没有给SecurityManager配置缓存管理器,Realm的缓存也无法正常初始化:
以Ehcache为例的Java配置
// 配置缓存管理器 @Bean public CacheManager shiroCacheManager() { EhCacheManager cacheManager = new EhCacheManager(); // 加载ehcache配置文件 cacheManager.setCacheManagerConfigFile("classpath:ehcache-shiro.xml"); return cacheManager; } // 配置SecurityManager并关联缓存管理器和Realm @Bean public SecurityManager securityManager(CustomShiroRealm customShiroRealm, CacheManager shiroCacheManager) { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(customShiroRealm); securityManager.setCacheManager(shiroCacheManager); return securityManager; }
同时要在ehcache-shiro.xml中定义对应的缓存:
<cache name="authenticationCache" maxEntriesLocalHeap="1000" eternal="false" timeToIdleSeconds="3600" timeToLiveSeconds="7200" overflowToDisk="false"/>
3. 添加兜底逻辑,避免缓存为null时失效
如果配置没问题但偶尔还是出现缓存为null的情况,可以在清除逻辑中添加兜底处理,直接操作会话:
protected void clearCachedAuthenticationInfo(PrincipalCollection principals) { if (!CollectionUtils.isEmpty(principals)) { Cache<Object, AuthenticationInfo> cache = this.getAvailableAuthenticationCache(); if (cache != null) { Object key = this.getAuthenticationCacheKey(principals); cache.remove(key); } else { // 兜底:直接清除会话中的认证标记并终止会话 Subject currentSubject = SecurityUtils.getSubject(); Session session = currentSubject.getSession(false); if (session != null) { // 移除认证状态标记 session.removeAttribute("org.apache.shiro.subject.support.DefaultSubjectContext_AUTHENTICATED_SESSION_KEY"); // 终止会话 session.stop(); } // 同时清除当前Subject的认证状态 currentSubject.logout(); } } }
4. 检查PrincipalCollection的有效性
确保传入的principals包含有效的用户身份信息,比如用户ID、用户名等。如果会话已过期或principals为空,不仅缓存key生成会有问题,后续逻辑也无法正常执行。
内容的提问来源于stack exchange,提问作者licoycn
相关产品推荐
相关产品推荐

