服务之间怎么传递用户身份?网关登录之后下游为什么还是 401?TokenRelay 到底转发了什么?第二跳要不要自己转发?令牌过期了谁来刷新?这篇用授权服务器、网关和两个资源服务器在 Spring Cloud Gateway 5.0.3 上走一遍。
浏览器访问 GET /api/me:跳转链 ['302', '302', '302', 'AS 登录', '302', '302', '401'](登录之后);最终 HTTP 401,A 回答:
登录态不会变成下游的 Authorization 头,下游 401。
登录后 GET /api/me:HTTP 200,A 回答:A 收到:sub=alice,scope=[read, openid],jti=a1e7c11a,aud=[gw],请求里是否带 Authorization 头=true 再请求两次,A 收到的 jti(令牌的唯一标识):a1e7c11a / a1e7c11a(与第一次 相同) 没有登录的浏览器直接请求 /api/me:HTTP 302,Location /oauth2/authorization/gw 绕过网关直接请求 A 的 /me(不带令牌):HTTP 401,WWW-Authenticate 里带 resource_metadata = True
原样透传同一个令牌;未登录 302;下游不检查受众。
A → B,relay=true:A → B 收到:sub=alice,scope=[read, openid],jti=a1e7c11a,aud=[gw],请求里是否带 Authorization 头=true A → B,relay=false:A → 调用下游失败:Unauthorized:401 Unauthorized: [no body]
下游收到的头不会自动传给更下游,要显式转发。
登录后第一次 A 收到的 jti=b395d43b;等 4 秒再请求一次,jti=a4cb4dc5,HTTP 200:令牌被自动刷新了(jti 变了),浏览器那边没有任何感知
令牌快过期时 TokenRelay 用 refresh_token 刷新。