在Spring Boot上使用Spring Session(JDBC)展开Timeout

Pab*_*ele 8 java spring spring-mvc spring-security spring-session

我正在使用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')
Run Code Online (Sandbox Code Playgroud)

我习惯添加:

// A 24 hours long session
server.session.timeout = 86400 
Run Code Online (Sandbox Code Playgroud)

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

我使用另一种方法获得完全相同的行为,在Auth Success上设置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);
    }
}
Run Code Online (Sandbox Code Playgroud)

当然,我能够在数据库存储会话中验证我的号码,但30分钟后会再次删除会话.

那么,将Spring Session超时扩展到超过30分钟的正确方法是什么?由于MAX_INACTIVE_INTERVAL没有做我认为应该做的事情,那么正确的做法是什么?

我可以使用任何lib的最新版本.

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);
Run Code Online (Sandbox Code Playgroud)

this.defaultMaxInactiveInterval 仍始终填入"1800",这意味着30分钟,以杀死所有会话.

这是评论的预期行为:

从默认值调试信息.

我仍然试图将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;
}
Run Code Online (Sandbox Code Playgroud)

我没有找到任何明确的选项来完美地覆盖它.

更新3

根据评论,我只能使用注释配置为:

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

@EnableJdbcHttpSession(tableName="MYSCHEMA.SPRING_SESSION", maxInactiveIntervalInSeconds = 86400)
public class HttpSessionConfig {
}
Run Code Online (Sandbox Code Playgroud)

有了它,我能够使用定义的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
Run Code Online (Sandbox Code Playgroud)

日志从未显示删除它们.

因此,检查SPRING_SECURITY_CONTEXT的任何其他内容仍然有30分钟的默认超时时间,它会触发整个会话失效.

我正在尝试添加更多断点来弄明白.:)

小智 2

您必须在文件server.session.timeout中设置application.properties。请参阅此文档:服务器属性