参考shiro session设置了过期时间不起作用、无效,出现Redis session expire time: xxxx is less than Session timeout:xxx

当前博客只是自己发现问题的历程,也可能只是适合当前系统,所以当前并不具备一定的代表性。

在开发过程中出现Redis session expire time: xxxx is less than Session timeout:xxx这种问题,虽然不影响功能的使用,但是对于有洁癖的人来说还是有点受不了的。如下图所示:
在这里插入图片描述
通过对源码分析及调试:
RedisSessionDAO:

private void saveSession(Session session) throws UnknownSessionException {
   if (session == null || session.getId() == null) {
      logger.error("session or session id is null");
      throw new UnknownSessionException("session or session id is null");
   }
   byte[] key;
   byte[] value;
   try {
      key = keySerializer.serialize(getRedisSessionKey(session.getId()));
      value = valueSerializer.serialize(session);
   } catch (SerializationException e) {
      logger.error("serialize session error. session id=" + session.getId());
      throw new UnknownSessionException(e);
   }
   if (expire == DEFAULT_EXPIRE) {
      this.redisManager.set(key, value, (int) (session.getTimeout() / MILLISECONDS_IN_A_SECOND));
      return;
   }
   if (expire != NO_EXPIRE && expire * MILLISECONDS_IN_A_SECOND < session.getTimeout()) {
      logger.warn("Redis session expire time: "
            + (expire * MILLISECONDS_IN_A_SECOND)
            + " is less than Session timeout: "
            + session.getTimeout()
            + " . It may cause some problems.");
   }
   this.redisManager.set(key, value, expire);
}

可以看到由于expire 与session.getTimeout比较,redisSessionDAO中设置的时间与session中的时间问题。其实主要就是这个session的问题。我的问题是:RedisSessionDAO设置的过期时间A小于配置的session的过期时间B,包含DefaultWebSessionManager.setGlobalSessionTimeout、DefaultWebSessionManager.getSessionIdCookie().setMaxAge(LongValue)都比A要大,故而出现如上图所示的问题。

注意:如果redis中存在session的过期时间仍然超过RedisSessionDAO的过期时间,还是会出现如上图所示的问题,可以通过flushall刷新redis缓存数据。

redis-cli.sh 
flushall

由于主要配置的是DefaultWebSessionManager,如下所示:

@Bean
public DefaultWebSessionManager sessionManager() {
    DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
    sessionManager.setDeleteInvalidSessions(true);
    sessionManager.setSessionDAO(redisSessionDAO());
    sessionManager.setCacheManager(redisCacheManager());
    sessionManager.setGlobalSessionTimeout(12 * 3600 * 1000);// milliseconds
    sessionManager.getSessionIdCookie().setMaxAge(12 * 3600 * 1000);// milliseconds
    return sessionManager;
}

所以查看DefaultWebSessionManager中源码:

/**
 * Stores the Session's ID, usually as a Cookie, to associate with future requests.
 *
 * @param session the session that was just {@link #createSession created}.
 */
@Override
protected void onStart(Session session, SessionContext context) {
    super.onStart(session, context);

    if (!WebUtils.isHttp(context)) {
        log.debug("SessionContext argument is not HTTP compatible or does not have an HTTP request/response " +
                "pair. No session ID cookie will be set.");
        return;

    }
    HttpServletRequest request = WebUtils.getHttpRequest(context);
    HttpServletResponse response = WebUtils.getHttpResponse(context);

    if (isSessionIdCookieEnabled()) {
        Serializable sessionId = session.getId();
        storeSessionId(sessionId, request, response);
    } else {
        log.debug("Session ID cookie is disabled.  No cookie has been set for new session with id {}", session.getId());
    }

    request.removeAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE);
    request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_IS_NEW, Boolean.TRUE);
}

追溯创建session的类型,发现onStart方法描述为调用的是createSession方法,追溯到DefaultSessionManager:

protected Session doCreateSession(SessionContext context) {
    Session s = newSessionInstance(context);
    if (log.isTraceEnabled()) {
        log.trace("Creating session for host {}", s.getHost());
    }
    create(s);
    return s;
}

通过newSessionInstance最后追溯到SimpleSessionFactory

public class SimpleSessionFactory implements SessionFactory {

    /**
     * Creates a new {@link SimpleSession SimpleSession} instance retaining the context's
     * {@link SessionContext#getHost() host} if one can be found.
     *
     * @param initData the initialization data to be used during {@link Session} creation.
     * @return a new {@link SimpleSession SimpleSession} instance
     */
    public Session createSession(SessionContext initData) {
        if (initData != null) {
            String host = initData.getHost();
            if (host != null) {
                return new SimpleSession(host);
            }
        }
        return new SimpleSession();
    }
}

分析出来,当前系统中的默认采用的是SimpleSession类实现。

### 回答1: 在Shiro设置Session过期时间可以通过在shiro.ini文件中配置sessionManager的globalSessionTimeout属性来实现。例如: [main] # 配置sessionManager sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager # 设置session过期时间为30分钟 sessionManager.globalSessionTimeout = 180000 这样就将Session过期时间设置为30分钟。需要注意的是,这里的globalSessionTimeout属性的单位是毫秒。 ### 回答2: Shiro是一个流行的Java安全框架,它提供了许多安全控制和认证机制。其中之一是Session管理。Shiro允许您设置Session过期时间来保护应用程序不受Session滥用的影响,同时确保用户的安全性。 在Shiro中,Session过期时间可以通过多种方式设置。其中一种方法是通过在Shiro配置文件中配置MaxIdleTime属性。这个属性确定了用户的Session在没有活动的情况下可以保持的时间量。如果一个用户不做任何事情,超过了这个时间,那么他的Session将被终止。 在Shiro中,还可以使用SessionDAO接口来设置Session过期时间SessionDAO是Shiro中实现Session持久化,存储和管理的核心接口之一。使用SessionDAO,您可以轻松地更改和管理Session过期时间。通常情况下,SessionDAO会在Shiro的配置文件中配置。 除了使用Shiro的配置文件和SessionDAO进行设置之外,您还可以在编写自定义Realm时设置Session过期时间。通过重写Realm中的doGetAuthenticationInfo和doGetAuthorizationInfo方法,您可以自定义Session过期时间,并根据需要更改它。 总之,Shiro提供了多种方法来设置Session过期时间。无论您是使用Shiro的配置文件,SessionDAO还是自定义Realm,在设置Session过期时间方面都有很大的灵活性和自由性。为了保护应用程序和用户的数据安全,强烈建议您定期检查和调整Session过期时间。 ### 回答3: ShiroJava开发中广泛使用的安全框架,用于实现身份验证、授权、加密和会话管理等功能。在实际开发中,Shiro提供了非常灵活的session配置,使得开发者可以根据实际需求对session过期时间进行设置。 在Shiro中,session过期时间分为两部分:全局session过期时间和单个session过期时间。 全局session过期时间可以在Shiro配置文件中进行配置,具体方法如下: ``` # 配置全局session过期时间,单位为毫秒 securityManager.sessionManager.globalSessionTimeout = 1800000 # 或者在Java代码中进行配置 DefaultSessionManager sessionManager = new DefaultSessionManager(); sessionManager.setGlobalSessionTimeout(1800000); securityManager.setSessionManager(sessionManager); ``` 这里将全局session过期时间设置为1800000毫秒,即30分钟。当然,具体时间可以根据实际需求进行调整。 而单个session过期时间则可以在代码中进行设置,具体方法如下: ``` Subject subject = SecurityUtils.getSubject(); Session session = subject.getSession(); session.setTimeout(1800000); ``` 这里将单个session过期时间设置为1800000毫秒,即30分钟。需要注意的是,单个session过期时间必须在session创建之后进行设置。 总的来说,通过全局session过期时间和单个session过期时间设置Shiro可以非常灵活地管理会话,从而保证系统的安全性和可靠性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值