首页 文章

Websession失效不适用于Spring Boot 2.0.2

提问于
浏览
2

我想将Spring Webflux项目从Spring Boot 2.0.1升级到Spring Boot 2.0.3 . 在我的项目中,我的会话由Spring Session Data Redis支持 . 升级Spring Boot版本时,我注意到Spring Boot 2.0.2中的websession失效问题 .

在Spring Boot 2.0.1中,我以这种方式使会话无效:

webSession.invalidate().subscribe();

这导致我的当前会话被销毁,并且使用新的会话ID,创建时间等生成了新的会话 .

但是,从Spring Boot 2.0.2开始,相同的代码似乎并没有完全破坏会话 . 当前会话信息只是"cleared",之后仍然使用相同的会话ID . 这是一个问题,因为它在ReactiveRedisOperationsSessionRepository.class中导致空指针异常:

private static final class SessionMapper implements Function<Map<String, Object>, MapSession> {
        private final String id;

        private SessionMapper(String id) {
            this.id = id;
        }

        public MapSession apply(Map<String, Object> map) {
            MapSession session = new MapSession(this.id);
            session.setCreationTime(Instant.ofEpochMilli((Long)map.get("creationTime")));
            session.setLastAccessedTime(Instant.ofEpochMilli((Long)map.get("lastAccessedTime")));
            session.setMaxInactiveInterval(Duration.ofSeconds((long)(Integer)map.get("maxInactiveInterval")));
            map.forEach((name, value) -> {
                if (name.startsWith("sessionAttr:")) {
                    session.setAttribute(name.substring("sessionAttr:".length()), value);
                }

            });
            return session;
        }
    }

由于会话数据为空(无创建时间等),以下行引发NPE:

session.setCreationTime(Instant.ofEpochMilli((Long)map.get("creationTime")));

这是一个bug还是我在Spring Boot 2.0.2中错过了关于Spring Session的新内容?

UPDATE

为了提供更多信息,我创建了一个重现问题的示例项目:https://github.com/adsanche/test-redis-session

该项目包含一个简单的控制器,公开两个 endpoints :

@Controller
public class HelloController {

    @GetMapping(value = "/hello")
    public String hello(final WebSession webSession) {

        webSession.getAttributes().put("test", "TEST");

        return "index";
    }

    @GetMapping(value = "/invalidate")
    public String invalidate(final WebSession webSession) {

        webSession.invalidate().subscribe();

        return UrlBasedViewResolver.REDIRECT_URL_PREFIX + "/hello";
    }
}

Behavior when running the project with Spring Boot 2.0.1

Sess

我们注意到会话ID以7546ff开头,会话数据包含“test”属性加上默认会话信息(创建/上次访问时间等) .

当前会话无效,并在“/ hello”上执行重定向,其中test属性添加到新的Web会话中 .

  • Redis新 Session 的状况:

enter image description here

我们注意到以ba7de开头的新会话ID,以及仍包含测试属性和默认会话信息的新会话数据 .

现在,让我们在Spring Boot 2.0.3的同一个项目中重现这个场景 .

Behavior when running the project with Spring Boot 2.0.3

enter image description here

我们注意到会话ID以12d61开头,会话数据包含“test”属性加上默认会话信息(创建/上次访问时间等) .

enter image description here

我们在这里注意到仍然使用相同的会话ID,但是会话甚至已从其默认信息(创建日期等)中清除 . 因此,当再次调用它时,在我在原始帖子中提到的地方的apply()方法中的反应式redis会话存储库中触发NPE:

enter image description here

希望这个示例项目有助于找出我的错误或实现问题 .

1 回答

  • 1

    这是Spring Session的 SpringSessionWebSessionStore 中的错误,或者更确切地说,是其内部 WebSession 实现中的错误 . 问题是 WebSession#invalidate 会话仅从基础会话存储中清除,但未标记为无效,因此后续请求处理仍然使用相同的会话ID结束 .

    我已经打开gh-1114来在Spring Session中解决这个问题 .

    我相信你之前没有经历过这种情况,即 Spring 季 Session 2.0.2.RELEASE 及以下,因为 SpringSessionWebSessionStore 中的另一个错误已在 2.0.3.RELEASE 中解决 - 请参阅gh-1039 . 此问题是关于无法更新 lastAccessedTime ,并且一旦我们修复了您描述的方案因为无效(和已删除)会话ID的会话仅使用 lastAccessedTime 属性再次保存而开始失败 .

相关问题