本文介绍在前后端分离、api与应用部署于不同子域(如 app.mything.com 与 api.mything.com)时,如何无需显式传递 user id 即可安全获取用户专属数据,重点讲解共享会话存储与加密 cookie 两种主流方案。
本文介绍在前后端分离、api与应用部署于不同子域(如 app.mything.com 与 api.mything.com)时,如何无需显式传递 user id 即可安全获取用户专属数据,重点讲解共享会话存储与加密 cookie 两种主流方案。
当 Web 应用与 API 服务拆分至不同子域(如 app.mything.com 和 api.mything.com)时,浏览器的同源策略(Same-Origin Policy)和默认 Cookie 作用域限制会导致传统服务端 Session 无法跨域共享——即前端登录后生成的 session ID 无法被 API 子域自动识别,进而使 SELECT * FROM sometable WHERE userid = ? 这类依赖当前用户身份的查询失效。
解决该问题的核心思路是:将用户身份凭证以跨域可识别、服务端可验证的方式持久化,并确保其安全性与不可篡改性。以下是两种经过生产验证的方案:
✅ 方案一:统一后端会话存储(推荐用于强一致性场景)
将原本依赖内存或本地文件的 Session 存储迁移至所有服务实例均可访问的共享存储,例如 MySQL、Redis 或 PostgreSQL。Go 生态中可使用 github.com/gorilla/sessions 配合 github.com/boj/redistore(Redis)或 github.com/srinathgs/mysqlstore(MySQL)实现。
示例(Go + Redis Store):
import (
"github.com/gorilla/sessions"
"github.com/boj/redistore"
)
var store, _ = redistore.NewRediStore(10, "tcp", "localhost:6379", "", []byte("your-secret-key"))
// 设置 Cookie 域名为 .mything.com(注意前导点),使其对所有子域生效
store.Options = &sessions.Options{
Domain: ".mything.com",
Path: "/",
MaxAge: 86400,
HttpOnly: true,
Secure: true, // 生产环境务必启用 HTTPS
}⚠️ 注意事项:
- Cookie 的 Domain 必须设为 .mything.com(带前导点),才能被 app.mything.com 和 api.mything.com 共享;
- 确保 API 服务与前端应用使用相同的 secret key 解密 session;
- Redis/MySQL 需具备高可用与低延迟,避免成为性能瓶颈。
✅ 方案二:使用签名/加密 Cookie 直接携带用户标识(轻量高效)
放弃服务端 Session,转而由认证服务(如登录接口)颁发一个 JWT 或自定义加密 Cookie,其中包含经签名的用户 ID(如 sub: "123")及过期时间。API 层直接解密并校验该 Cookie,无需查库即可确认身份。
示例(Go 中使用 golang.org/x/crypto/nacl/secretbox 加密用户 ID):
// 登录成功后设置加密 Cookie(仅含 userID)
func setAuthCookie(w http.ResponseWriter, userID int64) {
data := []byte(strconv.FormatInt(userID, 10))
encrypted := encrypt(data, secretKey) // 实现 AES/GCM 或 NaCl 加密
http.SetCookie(w, &http.Cookie{
Name: "auth_token",
Value: base64.URLEncoding.EncodeToString(encrypted),
Domain: ".mything.com",
Path: "/",
MaxAge: 3600,
HttpOnly: true,
Secure: true,
SameSite: http.SameSiteStrictMode,
})
}
// API 中解析
func getUserIDFromCookie(r *http.Request) (int64, error) {
cookie, err := r.Cookie("auth_token")
if err != nil { return 0, err }
decrypted := decrypt(cookie.Value, secretKey)
return strconv.ParseInt(string(decrypted), 10, 64)
}✅ 优势:无状态、免查库、扩展性好;
? 安全前提:必须使用强加密+签名(防篡改)、设置 HttpOnly/Secure/SameSite、严格校验有效期与签发源。
? 总结建议
- 若系统已存在成熟 Session 管理且对事务一致性要求高(如需实时同步登录态、踢出机制),优先选择共享存储方案;
- 若追求无状态、水平扩展与现代 API 架构(如微服务),加密 Token/Cookie 方案更简洁可控;
- 切勿在 URL、Header(非 Authorization)或明文 Cookie 中直接传递 userID —— 这属于严重安全风险;
- 所有跨域通信务必启用 HTTPS,并始终校验请求来源(CORS 白名单)与凭证有效性。
通过以上任一方式,你即可在 api.mything.com 上安全、可靠地执行 WHERE userid = ? 查询,彻底解耦前端应用与后端 API 的部署边界。

















