Spring Boot中如何实现会话超时并重新要求登录
问题描述
我正在使用Spring Boot构建一个简单的JSON REST API,应用运行正常,已通过Spring Security配置Basic认证。但运行应用时,首次登录后刷新URL不会再次要求输入用户名密码,请问如何实现会话超时后重新提示登录?注:无UI,仅为API。
安全配置类
package com.erplogic.erp.topcon.security; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.core.session.SessionRegistry; import org.springframework.security.core.session.SessionRegistryImpl; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.provisioning.InMemoryUserDetailsManager; import org.springframework.security.web.SecurityFilterChain; @Configuration public class SecurityConfiguration { @Bean SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http.authorizeHttpRequests((authz) -> authz.anyRequest().authenticated() ).sessionManagement(session -> session .sessionCreationPolicy(SessionCreationPolicy.NEVER) ) .httpBasic(); return http.build(); } @Bean InMemoryUserDetailsManager userDetailsService() { UserDetails user = User.builder().username("user").password(encoder().encode("pass")).roles("USER").build(); return new InMemoryUserDetailsManager(user); } @Bean PasswordEncoder encoder() { return new BCryptPasswordEncoder(); } @Bean SessionRegistry sessionRegistry() { return new SessionRegistryImpl(); } }
控制器类
package com.erplogic.erp.topcon.controller; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import com.erplogic.erp.topcon.service.SapApiService; import com.erplogic.poc.objects.Root; import com.fasterxml.jackson.core.JsonProcessingException; import io.erplogic.maven.plclog.wsdl2java.StandardFaultMessage_Exception; @RestController public class OutboundController { @Autowired private SapApiService sapApiService; @RequestMapping(path ="/outbound",produces = MediaType.APPLICATION_JSON_VALUE,method = RequestMethod.GET) public Root getOutbound() throws KeyManagementException, NoSuchAlgorithmException, StandardFaultMessage_Exception, JsonProcessingException { return ((SapApiService) sapApiService).processOutboudService(); } @RequestMapping(value = "/outbound/{outboundId}",produces = MediaType.APPLICATION_JSON_VALUE,method = RequestMethod.GET) public String getOutboundId(@PathVariable String outboundId) throws KeyManagementException, JsonProcessingException, NoSuchAlgorithmException, StandardFaultMessage_Exception { return ((SapApiService) sapApiService).processOutboudServiceByID(outboundId); } }
解决方案
问题核心在于当前会话策略配置为SessionCreationPolicy.NEVER,Spring Security不会创建服务器端会话,浏览器/API工具会自动缓存Basic认证凭证,每次请求自动携带,因此不会触发重新登录。要实现会话超时后重新认证,需按以下步骤修改:
1. 调整会话创建策略并配置超时处理
修改SecurityConfiguration中的filterChain方法,将会话创建策略改为IF_REQUIRED,同时配置会话超时时间和失效后的响应逻辑:
import javax.servlet.http.HttpServletResponse; @Bean SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http.authorizeHttpRequests((authz) -> authz.anyRequest().authenticated()) .sessionManagement(session -> session .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED) .sessionTimeout(timeout -> timeout.inSeconds(300)) // 设置会话超时时间为5分钟 .invalidSessionStrategy((request, response) -> { // 会话失效时返回401未授权状态码 response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); }) .maximumSessions(1) // 限制单个用户只能有一个会话(可选) .sessionRegistry(sessionRegistry()) ) .httpBasic(); return http.build(); }
2. 配置全局会话超时时间(可选)
也可以在application.properties中添加全局会话超时配置,与代码中的配置二选一即可:
# application.properties server.servlet.session.timeout=300s
3. 关键说明
SessionCreationPolicy.IF_REQUIRED:Spring Security会在需要时创建服务器端会话,用于跟踪认证状态。- 会话超时后,服务器端会话失效,后续请求会返回401未授权状态,客户端(浏览器/API工具)会重新提示输入用户名密码。
- 若使用Postman等API调用工具,需确保工具未自动缓存Basic认证凭证,否则可能仍会自动携带旧凭证,需手动清除缓存或重新添加认证信息。
内容的提问来源于stack exchange,提问作者S Mugunthan kumar
相关产品推荐
相关产品推荐

