bigywater.tech
Spring · 112

OAuth2 Client:令牌的获取、刷新与存放

oauth2Login 到底发了哪些请求?登录之后用户信息在哪?令牌存在哪里、过期了谁来刷新?客户端应用重启以后会怎样?这篇在 Spring Boot 4.0.8 上起一个 Authorization Server 和一个 OAuth2 Client,用 Python 手工带 Cookie 走一遍。

7 个请求
从访问 /oauth2/authorization/demo 到回调完成的跳转链
自动刷新
62 秒有效期的 access_token,4 秒后再取就已经是刷新过的新令牌
内存
令牌默认存在 InMemoryOAuth2AuthorizedClientService,重启后旧 session 要重新授权

登录流程

实测 · 本机执行输出
  跳转链:302 客户端 /oauth2/authorization/demo → 302 9601/oauth2/authorize → 200 9601/login → 302 AS POST /login → 302 9601/oauth2/authorize → 302 9602/login/oauth2/code/demo → 404 9602/
  客户端发给授权服务器的授权请求参数:{'response_type': 'code', 'client_id': 'conf', 'scope': 'openid read', 'state': 'nDnzZEqG13jVoncmzmim…', 'redirect_uri': 'http://127.0.0.1:960…', 'nonce': 'UYumkDfyeEHXldQlGWK0…', 'code_challenge': 'K1zN3ogsYqEAUg7r0iku…', 'code_challenge_method': 'S256'}
  GET /me → HTTP 200 principal 类型=DefaultOidcUser,name=alice,authorities=[OIDC_USER, SCOPE_openid, SCOPE_read],id_token 的 claims 键=[aud, auth_time, azp, exp, iat, iss, jti, nonce, sid, sub]
  GET /sess → session 属性 [SPRING_SECURITY_CONTEXT]
  GET /store → OAuth2AuthorizedClientRepository = AuthenticatedPrincipalOAuth2AuthorizedClientRepository;OAuth2AuthorizedClientService = [InMemoryOAuth2AuthorizedClientService]

跳转链经过授权服务器的登录页后回到 /login/oauth2/code/demo;机密客户端也带 PKCE;principal 是 DefaultOidcUser。

令牌与刷新

实测 · 本机执行输出
  登录完立刻 GET /token → HTTP 200 access_token 前 12 位=eyJraWQiOiJj…末 8 位=ydBmflQw,签发=2026-10-20T04:28:37.977370Z,过期=2026-10-20T04:29:38.977370Z,scopes=[openid, read],refresh_token=有
  等 4 秒(access token 的有效期是 62 秒,客户端提前 60 秒就认为快过期了)……
  再 GET /token → HTTP 200 access_token 前 12 位=eyJraWQiOiJj…末 8 位=AzmfkcoA,签发=2026-10-20T04:28:42.173767Z,过期=2026-10-20T04:29:43.173767Z,scopes=[openid, read],refresh_token=有
  两次的 access_token 末 8 位:ydBmflQw 与 AzmfkcoA,不同(用 refresh_token 换了新的)

@RegisteredOAuth2AuthorizedClient 取到的令牌快过期时被自动刷新。

重启

实测 · 本机执行输出
  带着重启之前的 JSESSIONID GET /token → HTTP 302,Location http://127.0.0.1:9602/oauth2/authorization/demo

令牌与 session 都在内存里,重启后旧 JSESSIONID 要重新授权。

分步演示

OAuth2 Client
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / OpenJDK 21.0.12(Homebrew) / Spring Boot 4.0.8(Spring Framework 7.0.9、Tomcat 11.0.24) / Spring Cloud 2025.1.3;用 javac 编译、java 直接运行,依赖由 Maven 从 Maven Central 解析;数字每次运行会有小幅抖动(Spring Security 7.0.7;授权服务器 spring-boot-starter-oauth2-authorization-server,客户端 spring-boot-starter-oauth2-client,issuer-uri 自动发现)。机密客户端 conf(client_secret_basic),access_token 有效期配成 62 秒,不要同意页;用户 alice / pw;全程用 Python 手工带 Cookie 模拟浏览器,每一步只记录状态码与 Location
    • 没有验证:Spring Security 的默认时钟偏差(60 秒)的具体值,只是从现象反推;配置的 62 秒与实际 61 秒的差别;持久化 OAuth2AuthorizedClientService(JDBC)与共享 session;refresh_token 过期或被撤销后的行为;WebClient 的 ServerOAuth2AuthorizedClientExchangeFilterFunction;client_credentials 授权类型的客户端;OIDC 的 RP-Initiated Logout
    京ICP备2026067502号-1京公网安备11010502063487号