feat(auth): 微信 access_token 走中控服务器(腾讯云静态 IP 换 token)
隐患:gateway 换 access_token 时微信看到的是本地宽带出网 IP(106.58.232.43, 动态会变),一变白名单就失效、二维码建不出来(40164)。 按微信官方推荐的「中控服务器」架构解决:腾讯云静态 IP 统一换 token,gateway 拉取 使用。微信 IP 白名单只限制换 token 这一步,拿 token 建二维码不查 IP —— 所以 换 token 挪到中控、建二维码仍在 gateway 本地,白名单只填腾讯云 IP,永不失效。 - wechat.PullToken:从中控 HTTPS 端点拉 token(Bearer 密钥鉴权),坏响应/403/空 token 一律报错不当成功;中控没给 expires_in 时按 7200 兜底。 - handler.accessToken:配了 WECHAT_TOKEN_URL 就只从中控拉、绝不自己 FetchAccessToken (微信要求单点刷新,多点各自换会互相顶掉 token);不配维持直连,零副作用可回退。 - compose:gateway 加 WECHAT_TOKEN_URL / WECHAT_TOKEN_SECRET(从宿主机 .env 注入)。 - deploy/wechat-token-zhongkong.md:腾讯云侧 cron 脚本 + nginx 配置 + 切换验证步骤。 本地验证(假中控 httptest + 真 gateway):建票时 Redis 缓存的是中控给的 token (FAKE_TOKEN_FROM_ZHONGKONG),gateway 未直连微信换 token;随后拿该 token 调 qrcode/create(假 token 报 40001 属预期)——证明「中控换 token → 本地建二维码」链路成立。 4 组 PullToken 单测覆盖正常/403/坏JSON/兜底。 真机验证(部署后):把本地 IP 从白名单删掉、只留腾讯云 IP,扫码仍能登录即坐实 qrcode 不受 IP 限制;若建二维码报 40164 则退回 tinyproxy 正向代理备选。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -8,6 +8,7 @@ import (
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -60,7 +61,19 @@ func (h *Handler) accessToken(ctx context.Context, cfg wechat.Config) (string, e
|
||||
if t := h.cache.WxTokenGet(ctx, cfg.AppID); t != "" { // 双检
|
||||
return t, nil
|
||||
}
|
||||
token, ttl, err := cfg.FetchAccessToken(ctx)
|
||||
// 中控模式:配了 WECHAT_TOKEN_URL 就只从中控拉(腾讯云静态 IP 换 token),
|
||||
// 绝不自己调 FetchAccessToken——微信要求单点刷新,多点各自换会互相顶掉 token。
|
||||
// 没配则维持直连(本地出网换 token,受动态 IP 白名单约束)。
|
||||
var (
|
||||
token string
|
||||
ttl int
|
||||
err error
|
||||
)
|
||||
if tokenURL := os.Getenv("WECHAT_TOKEN_URL"); tokenURL != "" {
|
||||
token, ttl, err = wechat.PullToken(ctx, tokenURL, os.Getenv("WECHAT_TOKEN_SECRET"))
|
||||
} else {
|
||||
token, ttl, err = cfg.FetchAccessToken(ctx)
|
||||
}
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user