beego未内置oauth2封装,必须手动集成golang.org/x/oauth2,严格完成state校验、redirecturl逐字节一致、conf.exchange上下文传入、authorization header构造四步;漏一即静默失败或返回400/401。

Beego 没有内置 OAuth2 封装,必须手动集成 golang.org/x/oauth2,漏掉 state 校验、RedirectURL 逐字节一致、conf.Exchange 上下文传入、Authorization header 构造这四步中的任意一步,都会静默失败或返回 400/401。
Beego 中怎么生成带 state 的授权 URL
不能直接拼 query,必须用 conf.AuthCodeURL 生成,并把 state 存进 session;state 必须用 crypto/rand 安全生成(32 字节 + hex 编码),不能用时间戳或 math/rand。
-
c.SetSession("oauth_state", state)必须在跳转前执行,且 key 名要固定(如"oauth_state") - 调用
conf.AuthCodeURL(state)时,别漏掉oauth2.SetAuthURLParam("login", "")—— 否则 GitHub 可能不显示登录框 - 本地开发统一用
http://localhost:8080/auth/github/callback,GitHub 后台配置必须完全一致(包括末尾斜杠) - 生产环境必须是 HTTPS,否则 GitHub 拒绝回调;Nginx 反代时,
RedirectURL填公网地址,不是内网http://127.0.0.1:8080
回调 handler 怎么校验 state 和换 token
回调里只取 URL 中的 state 不够,必须从 session 里读出来做恒定时间比对;conf.Exchange 必须传 r.Context(),不能用 context.Background(),否则超时卡死。
- 先调
c.GetString("state")获取 URL 参数,再用c.GetSession("oauth_state")取 session 值 - 用
subtle.ConstantTimeCompare比对,成功后立刻c.DelSession("oauth_state")(one-time use) -
conf.Exchange(r.Context(), code)前建议加context.WithTimeout(如 10 秒),避免网络异常 hang 住 goroutine - 错误类型要拆解:
err != nil && strings.Contains(err.Error(), "invalid_request")很可能是RedirectURL不一致
拿到 token 后怎么安全请求 GitHub 用户信息
不能直接用 http.Get,必须用 conf.Client(ctx, token) 构造的 client,它会自动加 Authorization: Bearer xxx;GitHub 返回的 email 字段默认为空,要额外申请 user:email scope。
- 构造 client 后,请求
https://api.github.com/user,响应体里有login、avatar_url、id - 如果需要邮箱,初始化
oauth2.Config时Scopes要包含"user:email",且用户授权页必须勾选 - 组织或仓库信息需额外
read:org或reposscope,不能靠通用 token 获取 - Beego 默认 session 引擎是 file,多实例部署必须切到 redis,否则
oauth_state会丢失
最易被忽略的是:state 比对完没删 session、RedirectURL 多一个/少一个协议、Exchange 用了 background context、token 换用户信息时没走 conf.Client —— 这四个点任何一个出错,都不会报明确错误,而是静默返回空数据或 401。











