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

Spring Security中如何基于access token实现Cookie免登录认证

问题根因

你遇到这个问题核心是两个默认配置没调整:

  • Spring Security默认生成的JSESSIONID是会话级Cookie,max-age属性为-1,浏览器关闭时会自动清除,存在服务端内存里的用户认证上下文(SecurityContext)会因为找不到对应会话ID直接失效
  • 你虽然把Google OAuth2的access token存到了Cookie里,但没有配置对应逻辑在请求进入时读取这个有效Cookie、重建认证信息,Security框架默认不会主动识别你自定义存储的token,自然不会放行受保护资源。
可选实现方案

两种方案选一种即可,第一种改动量最小,第二种灵活度更高。

方案1:持久化会话 + 统一Cookie有效期(推荐,改动最少)

这个方案不用修改现有登录逻辑,只要把会话从临时内存改成持久化存储,同时把相关Cookie的有效期从“会话级”改成和access token对齐的固定时长即可。

  1. 引入Spring Session依赖,选择你方便的持久化存储(Redis/JDBC/MongoDB都支持),比如用JDBC存数据库的话引入spring-session-jdbc依赖即可。
  2. 修改配置文件,开启会话持久化、设置Cookie过期时间,参考如下配置:
spring:
  session:
    # 会话持久化到指定存储,服务重启、浏览器关闭都不会丢失
    store-type: jdbc
    # 会话超时时间和你拿到的Google access token有效期对齐,比如设置7天
    timeout: 7d
    servlet:
      cookie:
        # 核心配置:给JSESSIONID设置固定有效期,不要用默认值-1(浏览器关闭即删除)
        max-age: 7d
        # 安全配置,生产环境必须开启
        http-only: true
        secure: true
        same-site: lax
  1. 找到你之前OAuth2登录成功后写access token到Cookie的逻辑,把这个Cookie的max-age也设置成和上面一致的7天,不要用默认的会话级有效期。

配置完成后,只要用户带着未过期的两个Cookie访问,服务端就能从持久化存储里找到对应的会话和已认证的SecurityContext,直接放行受保护资源,不需要重复登录。

方案2:自定义基于Access Token的认证过滤器(适合无状态架构)

如果你不想在服务端存储会话数据,可以自定义过滤器,每次请求主动从Cookie读取access token、校验通过后重建认证上下文。

  1. 先做好token的绑定和校验逻辑:不要只把access token明文存在Cookie里,建议给token加HMAC签名防篡改,服务端存储token和对应用户ID、授权范围的映射(存在Redis即可,设置和token一致的过期时间)。
  2. 自定义一个继承OncePerRequestFilter的认证过滤器,核心逻辑:
    • 先判断当前SecurityContext里是否已经存在有效认证信息,存在就直接放行
    • 从指定名称的Cookie中读取access token值,验签、查询服务端映射判断token是否有效、是否过期、对应用户是否存在
    • 校验通过后,构建完整的OAuth2AuthenticationToken(带上用户权限、Google客户端注册ID、用户信息),设置到SecurityContextHolder中
  3. 把这个过滤器注册到Spring Security过滤链中,放在OAuth2LoginAuthenticationFilter之前执行,参考配置:
@Configuration
@EnableWebSecurity
public class SecurityConfig {
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .authorizeHttpRequests(auth -> auth.anyRequest().authenticated())
                .oauth2Login(Customizer.withDefaults())
                // 注册自定义token认证过滤器
                .addFilterBefore(accessTokenAuthFilter(), OAuth2LoginAuthenticationFilter.class)
                // 无状态架构下打开下面配置,不创建服务端会话
                // .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
        ;
        return http.build();
    }
}
注意事项
  • 所有存储认证信息的Cookie必须开启HttpOnly属性,禁止前端JS读取,生产环境HTTPS场景下必须开启Secure属性,配置合理的SameSite规则,降低XSS、CSRF风险
  • Cookie和会话的有效期不要超过Google颁发的access token实际有效期,token过期后自然引导用户重新登录即可,不要设置超长有效期
  • 用方案1的时候记得配置定时任务清理存储中过期的会话数据,避免无效数据占满存储空间
  • 用方案2的时候必须做token签名校验和有效性校验,不能只要Cookie里有token值就直接放行,避免用户伪造身份

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 10:33:22