Как установить атрибуты SameSite=none и Secure для JSESSIONID cookie?

117
15 апреля 2022, 20:40

Большая часть сайта статическая, расположена на github, но есть форма обратной связи, которая расположена на другом сервере, написана на spring-webmvc. Использую общую настройку кросс-доменных запросов CORS:

@Configuration
@EnableWebMvc
public class WebMvcConfig implements WebMvcConfigurer {
    @Value("${allowed.origins}")
    private String allowedOrigins;
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/*").allowCredentials(true)
                .allowedOrigins(allowedOrigins.split(","));
    }
}

В Google Chrome оно не работает, т. к. для сессионной куки JSESSIONID не установлены атрибуты SameSite=none и Secure. Браузер получает куку, пишет error возле неё в инструментах разработчика и обратно на сервер её не передаёт. В результате сервер не видит клиента. В Firefox работает, но выдает предупреждение.

На сколько мне известно, интерфейс HttpSession не позволяет добавлять дополнительные атрибуты для сессионной куки. Или я не туда смотрю?

Проект Java Servlet API в архиве - вместо него теперь Jakarta Servlet, но атрибуты сессионной куки SameSite=none и Secure по-прежнему не настраиваются. Если настраиваются, то как?

Как установить атрибуты SameSite=none и Secure для JSESSIONID cookie?

Answer 1

Можно использовать бин SessionRepositoryFilter из Spring Session Core. Заменим стандартную сессию HttpSession на Spring Session - сессионная кука будет называться SESSION:

SESSION=MzdmNmIyODctZDRhNi00NDM0LTk1MTctMjAyOTI3ZjI1NmM0; Path=/; Secure; HttpOnly; SameSite=None

Дополнительные атрибуты куки можно установить с помощью DefaultCookieSerializer. Расширим немного имплементацию MapSessionRepository, поскольку в ней не реализовано удаление просроченных сессий. Добавим собственное удаление просроченных сессий перед добавлением новых. Я думаю, что для небольшого приложения этого будет достаточно:

@Configuration
@EnableSpringHttpSession
public class WebAppConfig implements WebApplicationInitializer {
    @Override
    public void onStartup(ServletContext servletContext) {
        servletContext
                .addFilter("sessionRepositoryFilter", DelegatingFilterProxy.class)
                .addMappingForUrlPatterns(null, false, "/*");
    }
    @Bean
    public MapSessionRepository sessionRepository() {
        final Map<String, Session> sessions = new ConcurrentHashMap<>();
        MapSessionRepository sessionRepository =
                new MapSessionRepository(sessions) {
                    @Override
                    public void save(MapSession session) {
                        sessions.entrySet().stream()
                                .filter(entry -> entry.getValue().isExpired())
                                .forEach(entry -> sessions.remove(entry.getKey()));
                        super.save(session);
                    }
                };
        sessionRepository.setDefaultMaxInactiveInterval(60*5);
        return sessionRepository;
    }
    @Bean
    public SessionRepositoryFilter<?> sessionRepositoryFilter(MapSessionRepository sessionRepository) {
        SessionRepositoryFilter<?> sessionRepositoryFilter =
                new SessionRepositoryFilter<>(sessionRepository);
        DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();
        cookieSerializer.setSameSite("None");
        cookieSerializer.setUseSecureCookie(true);
        CookieHttpSessionIdResolver cookieHttpSessionIdResolver =
                new CookieHttpSessionIdResolver();
        cookieHttpSessionIdResolver.setCookieSerializer(cookieSerializer);
        sessionRepositoryFilter.setHttpSessionIdResolver(cookieHttpSessionIdResolver);
        return sessionRepositoryFilter;
    }
}
READ ALSO
Пунктирный ProgressBar

Пунктирный ProgressBar

Нужно создать пунктирную шкалу прогресса, как показано на картинке:

233
Открытие закрытого приложения

Открытие закрытого приложения

Как осуществить вызов окна закрытого приложения на Андроид? Хотя бы диалоговогоРаньше делал так, но в Андроид 10-

207
Ошибка RecyclerView

Ошибка RecyclerView

Весь код адаптера

195