Аннулирование Websession не работает из Spring Boot 2.0.2 - PullRequest
0 голосов
/ 05 июля 2018

Я хотел обновить свой проект Spring Webflux с Spring Boot 2.0.1 до Spring Boot 2.0.3. В моем проекте мои сессии поддерживаются Red Session Data Redis. При обновлении версии Spring Boot я заметил проблему аннулирования веб-сессий в Spring Boot 2.0.2 +.

В Spring Boot 2.0.1 я аннулировал свои сессии следующим образом:

webSession.invalidate().subscribe();

Это привело к уничтожению моего текущего сеанса, и был создан новый сеанс с новым идентификатором сеанса, временем создания и т. Д.

Тем не менее, начиная с Spring Boot 2.0.2, тот же код, по-видимому, не полностью разрушает сеанс. Информация о текущем сеансе просто «очищается», и тот же идентификатор сеанса все еще используется впоследствии. Это проблема, потому что она вызывает исключение пустого указателя в 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")));

Это ошибка или я упустил что-то новое в Spring Boot 2.0.2+ относительно Spring Session?

UPDATE

Для получения дополнительной информации я создал пример проекта, воспроизводящего проблему: https://github.com/adsanche/test-redis-session

Этот проект содержит простой контроллер, выставляющий две конечные точки:

@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";
    }
}

Поведение при запуске проекта с Spring Boot 2.0.1

Sess

Мы замечаем идентификатор сеанса, начинающийся с 7546ff, и данные сеанса, содержащие атрибут «test» плюс информацию о сеансе по умолчанию (время создания / последнего доступа и т. Д.).

Текущий сеанс признан недействительным, и перенаправление выполняется в «/ hello», где атрибут теста добавляется в новый веб-сеанс.

  • Состояние нового сеанса в Redis:

enter image description here

Мы замечаем новый идентификатор сеанса, начинающийся с ba7de, и новые данные сеанса, все еще содержащие атрибут test плюс информацию о сеансе по умолчанию.

Теперь давайте воспроизведем этот сценарий в том же проекте, что и Spring Boot 2.0.3.

Поведение при запуске проекта с Spring Boot 2.0.3

enter image description here

Мы замечаем идентификатор сеанса, начинающийся с 12d61, и данные сеанса, содержащие атрибут «test» плюс информацию о сеансе по умолчанию (время создания / последнего доступа и т. Д.).

enter image description here

Здесь мы заметили, что тот же идентификатор сеанса все еще используется, но сеанс был очищен даже из информации по умолчанию (дата создания и т. Д.). Таким образом, когда он снова вызывается, NPE запускается в репозитории реактивного сеанса redis в методе apply () в месте, которое я упоминал в моем первоначальном сообщении:

enter image description here

Надеюсь, этот пример проекта поможет выяснить, является ли это ошибкой или проблемой реализации на моей стороне.

1 Ответ

0 голосов
/ 10 июля 2018

Это ошибка в SpringSessionWebSessionStore Spring Session или, точнее, во внутренней реализации WebSession. Проблема заключается в том, что в WebSession#invalidate сеанс очищается только из основного хранилища сеансов, но не помечается как недействительный, поэтому последующая обработка запроса по-прежнему заканчивается тем же идентификатором сеанса.

У меня есть openend gh-1114 для решения этой проблемы в весенней сессии.

Я полагаю, что вы не испытывали этого ранее, т. Е. С весенней сессией 2.0.2.RELEASE и ниже, из-за другой ошибки в SpringSessionWebSessionStore, которая была устранена в 2.0.3.RELEASE - см. gh-1039 . Эта проблема была связана с невозможностью обновить lastAccessedTime, и как только мы исправили, что описанный вами сценарий начал сбой из-за того, что сеанс для недействительного (и удаленного) идентификатора сеанса снова сохранялся только с атрибутом lastAccessedTime.

...