当 Spring 会话过期时,expiredSessionStrategy 不会被调用

问题描述 投票:0回答:1

我有一个 HTML 表单,可以向 Spring Boot 后端发出 REST API 调用。我正在使用 Spring Session 来处理同一用户的并发登录。如果我在下面的代码中使用expiredUrl,当当前会话过期时,我会被重定向到login.html页面。当我单击请求 HTML 页面的菜单项时,效果很好。

如果我已经在某个页面上,并且单击向服务器发出 AJAX 调用的按钮,则当会话过期时,我会收到 302(获取/重定向)状态,然后是带有 200 状态的 login.html 页面。因此 Ajax 调用得到的响应为 200,这是不正确的。 我在下面的代码中将expiredUrl替换为expiredSessionStrategy,但是expiredSessionStrategy根本没有被调用。 如果你们中有人知道原因或发现我的代码中存在缺陷,请告诉我。我在 Spring 会话文档中搜索了 expiredSessionStrategy,但没有找到任何内容。

我在 stackoverflow 上发现了几篇文章,建议使用 AjaxAwareAuthenticationEntryPoint 在会话到期时获取 Ajax 调用的自定义响应。我会尝试这种方法,但我想知道为什么在我的情况下没有调用expiredSessionStrategy。

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    
        http
         .csrf(..)
         .authorizeHttpRequests(..)
         .oauth2Login(oauth2 -> { 
                oauth2
               .userInfoEndpoint(userInfo -> userInfo
                                    .oidcUserService(this.oidcUserService())
                                 )
               .loginPage("/login.html") 
               .failureUrl("/loginFailure")
               .successHandler(customOauth2SuccessHandler) ;
                            }
        )
        .logout(...)
        .sessionManagement((sessions) -> sessions
                                        .maximumSessions(1)
                                        .sessionRegistry(this.sessionRegistry())
                                        .expiredSessionStrategy( event -> 
                                            {
                                                String URI = event.getRequest().getRequestURI();
                                                System.out.println("URI="+URI);
                                                if (URI.endsWith(".html"))
                                                    event.getResponse().sendRedirect("/login.html?msgCode=4");
                                                else
                                                {
                                                    event.getResponse().setContentType("application/json");
                                                    event.getResponse().sendError(440, "Session has expired. Please login again !");    
                                                }
                                            } 
                                        )
                                        //.expiredUrl("/login.html?msgCode=4")      
                        );

    return http.build();
}
spring-boot spring-session
1个回答
0
投票

我打开了 Spring Security 包的跟踪,这就是我发现的。当会话过期时,Spring会话管理正在删除过期的会话。您可能可以设置一些属性来控制此行为,但我还没有研究过。当我的应用程序发出 Ajax API 请求时,过期的会话 cookie 会与请求一起发送到服务器。由于该会话已被 Spring 删除,因此它被视为无效会话,而不是过期会话。所以我使用 invalidSessionStrategy 而不是 expiredSessionStrategy 并且事情对我有用。我创建了 InvalidSessionStrategy 接口的新实现,并使其发送 Ajax API 请求的 JSON 响应。

我这边的一个错误是我认为expiredURL 正在工作,因此我对expiredSessionStrategy 没有被调用感到困惑。实际上,expiredURL 从未被调用。默认行为是当 Spring 检测到无效会话时重定向到登录页面。由于在我的情况下,expiredURL 也重定向到登录页面,我认为expiredURL 正在工作,这又是我这边的一个错误,如果这误导了你们中的任何人,我真的很抱歉。

© www.soinside.com 2019 - 2024. All rights reserved.