首页 > 解决方案 > B 不能转换为 org.apache.shiro.session.Session

问题描述

这是一个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]

标签: javashiro

解决方案


问题原因

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);
    }
}

解决方案:</p>

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

我的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();
    }
}

推荐阅读