You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot结合Spring Security实现每次请求刷新Cookie有效期及持久化登录

嘿,这个需求我刚好在项目里实现过,结合Spring Boot + Spring Security来搞定其实挺清晰的,咱们一步步来:

核心思路拆解

首先得明确两个关键点:

  1. 默认情况下,浏览器的JSESSIONID Cookie是会话级的(maxAge=-1),关闭浏览器就会被删除,所以得先把它改成持久化Cookie,设置初始过期时间为1小时;
  2. 要实现“每次请求刷新过期时间”,就得在用户每次发起有效请求时,重新设置Cookie的过期时间,让它从当前时间再往后延1小时。
具体实现步骤

1. 配置Spring Security,让Session Cookie持久化

首先通过Spring Security的CookieSerializer来配置JSESSIONID的属性,把它改成持久化的,同时设置初始超时时间。另外别忘了在配置文件里设置Session的超时时间,保持和Cookie一致。

配置文件(application.properties)

# Session超时时间设置为1小时
server.servlet.session.timeout=3600s

Security配置类(Spring Security 5.7+ 新写法)

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            // 权限配置,根据你的实际需求调整
            .authorizeHttpRequests(auth -> auth
                .anyRequest().authenticated()
            )
            // 登录方式,这里用表单登录做示例,你可以换成自己的登录逻辑
            .formLogin(form -> form
                .permitAll()
            )
            // Session管理配置,防止会话固定攻击,控制最大会话数
            .sessionManagement(session -> session
                .sessionFixation().migrateSession()
                .maximumSessions(1)
            );
        return http.build();
    }

    // 配置JSESSIONID Cookie的属性,设置持久化和初始超时
    @Bean
    public CookieSerializer cookieSerializer() {
        DefaultCookieSerializer serializer = new DefaultCookieSerializer();
        serializer.setCookieName("JSESSIONID");
        serializer.setCookiePath("/"); // Cookie生效路径,一般设为根路径
        serializer.setCookieMaxAge(3600); // 初始过期时间1小时(秒)
        // 如果是生产环境有域名需求,加上下面这行,本地开发可以注释掉
        // serializer.setDomainName("your-domain.com");
        return serializer;
    }
}

如果你的项目还在用旧的WebSecurityConfigurerAdapter,可以这么写:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .permitAll()
                .and()
            .sessionManagement()
                .sessionFixation().migrateSession()
                .maximumSessions(1);
    }

    @Bean
    public CookieSerializer cookieSerializer() {
        DefaultCookieSerializer serializer = new DefaultCookieSerializer();
        serializer.setCookieName("JSESSIONID");
        serializer.setCookiePath("/");
        serializer.setCookieMaxAge(3600);
        return serializer;
    }
}

2. 实现请求拦截器,每次请求刷新Cookie过期时间

写一个拦截器,在用户每次发起请求时(仅限已登录用户),找到JSESSIONID Cookie,重新设置它的过期时间,这样就能实现“活跃时永不超时,停1小时才过期”的效果。

@Component
public class SessionRefreshInterceptor implements HandlerInterceptor {

    // 从配置文件读取Session超时时间,默认1小时
    @Value("${server.servlet.session.timeout:3600}")
    private int sessionTimeoutSeconds;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 只处理已登录用户的请求,未登录的不用管
        if (request.getUserPrincipal() != null) {
            Cookie[] cookies = request.getCookies();
            if (cookies != null) {
                for (Cookie cookie : cookies) {
                    if ("JSESSIONID".equals(cookie.getName())) {
                        // 刷新Cookie的过期时间,从当前时间往后延1小时
                        cookie.setMaxAge(sessionTimeoutSeconds);
                        cookie.setPath("/"); // 必须和原来的Cookie路径一致
                        // 生产环境记得加上域名
                        // cookie.setDomain("your-domain.com");
                        response.addCookie(cookie);
                        break;
                    }
                }
            }
        }
        return true;
    }
}

3. 注册拦截器到Spring Boot中

最后要把刚才写的拦截器注册到WebMvc配置里,让它生效。

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Autowired
    private SessionRefreshInterceptor sessionRefreshInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(sessionRefreshInterceptor)
                .addPathPatterns("/**") // 拦截所有请求
                // 排除不需要拦截的路径,比如登录、登出、静态资源等
                .excludePathPatterns("/login", "/logout", "/static/**", "/error");
    }
}
注意事项
  • 确保Cookie的path和domain设置正确,不然可能会生成多个JSESSIONID Cookie,导致会话混乱;
  • 如果你的项目用了Redis等分布式Session,记得同步配置Redis中Session的超时时间,保持和Cookie一致;
  • 测试的时候,关闭浏览器再打开,检查JSESSIONID Cookie是否还存在,并且每次请求后过期时间是否被刷新。

内容的提问来源于stack exchange,提问作者ArslanAnjum

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 06:53:14