【问题标题】:Expand Timeout using Spring Session (JDBC) on Spring Boot在 Spring Boot 上使用 Spring Session (JDBC) 扩展超时
【发布时间】:2017-02-09 15:39:26
【问题描述】:

我正在使用 Spring Boot 和 Spring Session 来控制一个使用 ReactJS 作为前端的应用程序。我的问题很简单,我尝试了几种方法来处理都没有成功。

React 部分在登录后使用 AJAX 调用 Spring REST 服务(我也在使用 Spring Security),这至少持续了 30 分钟。 之后会话结束,所有调用都会收到一个 302 和登录页面作为响应。这是预期的。

但我的问题是:有什么更好的方法来扩展后端生存时间(超过 30 分钟的默认值)?

    // Gradle portion
    compile('org.springframework.boot:spring-boot-devtools')
    compile('org.springframework.boot:spring-boot-starter-jdbc')
    compile('org.springframework.boot:spring-boot-starter-thymeleaf')
    compile('org.springframework.boot:spring-boot-starter-web')
    compile('org.springframework.boot:spring-boot-starter-aop')
    compile('org.springframework.boot:spring-boot-starter-security')
    compile('org.springframework.security:spring-security-test:4.1.1.RELEASE')

    // Cache configuration - JDBC
    compile('org.springframework.session:spring-session:1.2.2.RELEASE')
    compile('org.springframework.session:spring-session-jdbc:1.2.2.RELEASE')
    compile('org.springframework.boot:spring-boot-starter-jdbc')

我习惯加:

// A 24 hours long session
server.session.timeout = 86400 

这样我就可以在 SPRING_SESSION 表上看到我的会话以 MAX_INACTIVE_INTERVAL = 86400 存储。 一切似乎都很好......只有30分钟。在第 31 分钟,我尝试单击另一个触发 AJAX 调用的页面,我将在登录页面上收到 302 作为响应。

我使用另一种方法得到了完全相同的行为,通过 Java 设置验证成功:

@Component
public class AuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {

    @Value("${server.session.timeout}")
    private String defaultSessionTimeoutInSeconds;

    @Override
    public void onAuthenticationSuccess(
            HttpServletRequest request,
            HttpServletResponse response,
            Authentication authentication) throws ServletException, IOException {

        request.getSession().setMaxInactiveInterval(Integer.parseInt(defaultSessionTimeoutInSeconds));
        super.onAuthenticationSuccess(request, response, authentication);
    }
}

当然,我可以在数据库存储的会话中验证我的号码,但 30 分钟后会话再次被删除。

那么,真正将 Spring Session 超时时间延长到 30 分钟以上的正确方法是什么?由于 MAX_INACTIVE_INTERVAL 没有做我认为应该做的事情,那么正确的方法是什么?

我可以使用任何库的最新版本。

PS:当我的 AJAX 调用(基于 JQuery)收到 /login 重定向以及回退情况时,我可以考虑另一种解决方案来重定向整个浏览器。

提前致谢。

更新:

我尝试了以下方法:

添加属性 -> server.session.cookie.max-age= 777777 security.sessions=never

行为没有任何改变。我可以在 JdbcOperationsSessionRepository#cleanUpExpiredSessions 看到调试:

@Scheduled(cron = "0 * * * * *")
public void cleanUpExpiredSessions() {
    long now = System.currentTimeMillis();
    long maxInactiveIntervalSeconds = (this.defaultMaxInactiveInterval != null)
            ? this.defaultMaxInactiveInterval
            : MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS;

    final long sessionsValidFromTime = now - (maxInactiveIntervalSeconds * 1000);

this.defaultMaxInactiveInterval 仍然总是填充“1800”,这意味着需要 30 分钟才能终止所有会话。

这是 cmets 的预期行为:

我仍在尝试将这个持久的默认值 1800 更改为更大的值... :)

更新 2

仔细查看代码,在我的例子中,当 JdbcOperationsSessionRepository 被实例化时,它是由JdbcHttpSessionConfiguration#sessionRepository创建的

具体在哪里:

@Bean
public JdbcOperationsSessionRepository sessionRepository(
        @Qualifier("springSessionJdbcOperations") JdbcOperations jdbcOperations,
        PlatformTransactionManager transactionManager) {
    JdbcOperationsSessionRepository sessionRepository =
            new JdbcOperationsSessionRepository(jdbcOperations, transactionManager);
    String tableName = getTableName();
    if (StringUtils.hasText(tableName)) {
        sessionRepository.setTableName(tableName);
    }
    sessionRepository
            .setDefaultMaxInactiveInterval(this.maxInactiveIntervalInSeconds); // Always 1800 (private Integer maxInactiveIntervalInSeconds = 1800;)
    if (this.lobHandler != null) {
        sessionRepository.setLobHandler(this.lobHandler);
    }
    if (this.springSessionConversionService != null) {
        sessionRepository.setConversionService(this.springSessionConversionService);
    }
    else if (this.conversionService != null) {
        sessionRepository.setConversionService(this.conversionService);
    }
    else if (deserializingConverterSupportsCustomClassLoader()) {
        GenericConversionService conversionService = createConversionServiceWithBeanClassLoader();
        sessionRepository.setConversionService(conversionService);
    }
    return sessionRepository;
}

我没有找到任何明确的选项来漂亮地覆盖它。

更新 3

按照我只能使用注释来配置的 cmets:

    import org.springframework.session.jdbc.config.annotation.web.http.EnableJdbcHttpSession;

@EnableJdbcHttpSession(tableName="MYSCHEMA.SPRING_SESSION", maxInactiveIntervalInSeconds = 86400)
public class HttpSessionConfig {
}

这样我就可以使用定义的 MAX_INACTIVE_INTERVAL = 86400 来存储会话。

但是如果我在新会话中保留相关的 SPRING_SECURITY_CONTEXT(SPRING_SESSION_ATTRIBUTES 表)信息,则整个会话和属性会在 30 分钟后被删除。

在一次疯狂的测试中,我进行了登录,删除了会话的 SPRING_SECURITY_CONTEXT 属性,会话仍然存在...

默认会话清理器是正确的,它不是这里的违规者..

    2016-10-04 12:18:02,081 8808479 [pool-1-thread-1] INFO  d.s.t.s.ScheduledCacheRefresher - Checking refreshable caches now. 
2016-10-04 12:19:00,001 8866399 [pool-1-thread-1] DEBUG o.s.s.j.JdbcOperationsSessionRepository - Cleaning up sessions older than Mon Oct 03 12:19:00 BRT 2016 
2016-10-04 12:19:02,050 8868448 [pool-1-thread-1] DEBUG o.s.s.j.JdbcOperationsSessionRepository - Cleaned up 0 expired sessions 
2016-10-04 12:19:02,051 8868449 [pool-1-thread-1] INFO  d.s.t.s.ScheduledCacheRefresher - Checking refreshable caches now. 
2016-10-04 12:20:00,001 8926399 [pool-1-thread-1] INFO  d.s.t.s.ScheduledCacheRefresher - Checking refreshable caches now. 
2016-10-04 12:20:00,003 8926401 [pool-1-thread-1] DEBUG o.s.s.j.JdbcOperationsSessionRepository - Cleaning up sessions older than Mon Oct 03 12:20:00 BRT 2016 
2016-10-04 12:20:02,063 8928461 [pool-1-thread-1] DEBUG o.s.s.j.JdbcOperationsSessionRepository - Cleaned up 0 expired sessions

日志从未显示他们被删除。

所以检查 SPRING_SECURITY_CONTEXT 的任何其他内容仍然有大约 30 分钟的默认超时,它会触发整个会话失效。

我正在尝试添加更多断点来解决这个问题。 :)

【问题讨论】:

  • 你是否在配置中设置了 security.sessions=never?这是来自角度和弹簧安全性,但在反应时你需要相同的身份验证spring.io/blog/2015/01/20/…
  • 你能检查(使用调试器)JdbcOperationsSessionRepository#defaultMaxInactiveInterval 的值吗?除此之外,您还可以将org.springframework.session.jdbc.JdbcOperationsSessionRepository logger 设置为 DEBUG 级别,并查看JdbcOperationsSessionRepository#cleanUpExpiredSessions 中记录的内容。
  • 两者都试过并更新了我的问题,核心默认值保持不变,30 分钟后会终止所有会话。
  • 您使用的是什么版本的 Spring Boot 以及您如何配置 Spring Session JDBC 支持?假设启动 1.4,您应该能够使用 spring.session.store-type=jdbc 和所需的 server.session.timeout 值配置您想要的内容。或者,您可以使用 @EnableJdbcHttpSession 并将注释属性 maxInactiveIntervalInSeconds 设置为所需的值。
  • 我正在使用 Spring Boot 1.3.5 并仅使用注释进行配置。所以我有:@EnableJdbcHttpSession(tableName="MY_SCHEMA.SPRING_SESSION", maxInactiveIntervalInSeconds = 84600) 它提供了存储在数据库中的正确信息并检查了 cleanUpExpiredSessions 方法。因为我正在寻找一个 24 小时的会话,所以它在尝试执行 SQL(预期)时得到了昨天的时间。但是其他东西在 30 分钟后仍然会删除我的会话。是否有任何其他位置可以检查或启用日志?提前谢谢你。

标签: java spring spring-mvc spring-security spring-session


【解决方案1】:

您必须在您的application.properties 文件中设置server.session.timeout。 参考这篇文档:server properties

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-01-06
    • 2021-07-21
    • 1970-01-01
    • 1970-01-01
    • 2018-07-03
    • 2017-07-30
    • 2018-01-20
    • 1970-01-01
    相关资源
    最近更新 更多