B 不能转换为 org.apache.shiro.session.Session

Posted

技术标签:

【中文标题】B 不能转换为 org.apache.shiro.session.Session【英文标题】:B cannot be cast to org.apache.shiro.session.Session 【发布时间】:2021-10-31 13:12:57 【问题描述】:

这是一个Spring+Shiro+Redis的项目,运行一段时间后每次都会报这个错误。

为此,我收到此错误

2021-09-02 11:16:39.273 - INFO  [idationThread-1] stractValidatingSessionManager : Validating all active sessions...
2021-09-02 11:16:39.290 -ERROR  [idationThread-1] viceSessionValidationScheduler : Error while validating the session
java.lang.ClassCastException: [B cannot be cast to org.apache.shiro.session.Session
at org.apache.shiro.session.mgt.AbstractValidatingSessionManager.validateSessions(AbstractValidatingSessionManager.java:283) ~[shiro-core-1.7.0.jar:1.7.0]
at org.apache.shiro.session.mgt.ExecutorServiceSessionValidationScheduler.run(ExecutorServiceSessionValidationScheduler.java:120) [shiro-core-1.7.0.jar:1.7.0]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [?:1.8.0_151]
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308) [?:1.8.0_151]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180) [?:1.8.0_151]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294) [?:1.8.0_151]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:1.8.0_151]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:1.8.0_151]
at java.lang.Thread.run(Thread.java:748) [?:1.8.0_151]

【问题讨论】:

你尝试了什么,你的代码是什么样的?你用的是什么版本?时间段是多少?这是关于如何在 SO 上提出重要问题的绝佳资源:***.com/help/how-to-ask 【参考方案1】:

问题原因

org.apache.shiro.session.mgt.AbstractValidatingSessionManager

getactivesessions()方法得到的数据类型不对(可能是我用错了)。那么在执行session s: activesessions的时候,出现了B cannot be cast to org.apache.shiro.session.Session的错误。

public void validateSessions() 
    if (log.isInfoEnabled()) 
        log.info("Validating all active sessions...");
    

    int invalidCount = 0;

    Collection<Session> activeSessions = getActiveSessions();

    if (activeSessions != null && !activeSessions.isEmpty()) 
        for (Session s : activeSessions) 
            try 
                //simulate a lookup key to satisfy the method signature.
                //this could probably stand to be cleaned up in future versions:
                SessionKey key = new DefaultSessionKey(s.getId());
                validate(s, key);
             catch (InvalidSessionException e) 
                if (log.isDebugEnabled()) 
                    boolean expired = (e instanceof ExpiredSessionException);
                    String msg = "Invalidated session with id [" + s.getId() + "]" +
                            (expired ? " (expired)" : " (stopped)");
                    log.debug(msg);
                
                invalidCount++;
            
        
    

    if (log.isInfoEnabled()) 
        String msg = "Finished session validation.";
        if (invalidCount > 0) 
            msg += "  [" + invalidCount + "] sessions were stopped.";
         else 
            msg += "  No sessions were stopped.";
        
        log.info(msg);
    

解决办法:

我们需要重写自定义 Dao 中的getactivesessions() 方法。

我的RedisCachingShiroSessionDao 代码

public class RedisCachingShiroSessionDao extends EnterpriseCacheSessionDAO 

    @Resource
    private RedisTemplate<String,Object> redisTemplate;

    ...

    @Override
    public Collection<Session> getActiveSessions() 
        Set<String> keys = this.redisTemplate.keys(this.prefix + "*");

        if (keys != null && !keys.isEmpty()) 
            List<Object> sessions = this.redisTemplate.opsForValue().multiGet(keys);
            if (sessions != null) 
                return sessions.stream().map(o -> (Session) o).collect(Collectors.toList());
            
        
        return Collections.emptySet();
    

【讨论】:

以上是关于B 不能转换为 org.apache.shiro.session.Session的主要内容,如果未能解决你的问题,请参考以下文章

org.apache.shiro.web.servlet.ShiroHttpServletRequest cannot be cast to org.springframwork.web.mult..

细说shiro之六:session管理

Apache shiro - 我怎么知道缓存正在为授权工作?

使用shiro的session时出现不能登陆

org.apache.shiro.util.bytesource 啥类型

Shiro报错-[org.apache.shiro.mgt.AbstractRememberMeManager] - There was a failure while trying to retri