Go 官方只有 http.cookie,没有官方的 Session 包。
也就是说:
- Cookie:官方一等公民
- Session:官方不提供
在标准库里,Cookie 是完整内建的。
相关 API 都在:
net/http二、那为什么 Go 官方不提供 Session?这是设计哲学问题。
1、session ≠ HTTP 标准
- Cookie 是HTTP 标准的一部分
- Session 是应用层概念
- Session 的实现方式五花八门:
- 内存
- Redis
- 文件
- JWT(甚至没 Session)
官方没法“选边站”
2、Go 的设计哲学:最小但通用
Go 官方库的原则是:
只做通用、底层、稳定的东西
Session 涉及:
- 存储方案
- 过期策略
- 分布式
- 安全策略
- 业务模型
一旦官方出 Session:
- 就等于帮你做架构决策
- 很容易限制场景
$_SESSION["user_id"] = 1;简单,但:
- 强绑定 Cookie
- 强绑定文件 / 内存
- 不利于分布式
HttpSession session = Request.getSession();重、复杂、历史包袱
Go
“我给你工具,你自己搭积木”三、那 Go 官方有没有“接近 Session 的东西”?有,但很底层1、context.Context❌ 不是 Session
ctx := r.Context()- 只在一次请求链路内
- 不跨请求
- 用于超时 / 取消 / trace
不能用来做登录态
2、http.Request/ResponseWriter
只负责:
- Header
- Cookie
- Body
不碰业务状态
四、Go 社区是怎么解决 Session 的?常用第三方库1、gorilla/sessions(最经典)
store := sessions.NewCookieStore([]byte("secret"))session, _ := store.Get(r, "mysession")session.Values["user_id"] = 1session.Save(r, w)支持:
- Cookie
- Filesystem
- Redis(插件)
sessions.Default(c).Set("user_id", 1)五、Go 官方“默认推荐”的方式是什么?不是 Session,而是:
自己实现 / 使用第三方 / 或用 Token(JWT)
所以你会看到很多 Go 项目:
- 微服务:JWT / OAuth
- 单体 Web:Session + Redis
- API 服务:Token + Header
实现一个最小但完整的登录系统:
- /login:登录,创建 Session
- /profile:需要登录才能访问
- /logout:退出登录,销毁 Session
技术点:
- Cookie 保存 session_id
- 服务端内存保存 Session
- 中间件校验登录态
请求└── Cookie: session_idGo Server├── SessionStore(map)├── 登录校验└── 业务处理6.3、完整可运行代码直接 go run main.go 就能用
package mainimport ("fmt""log""math/rand""net/http""sync""time"// ===== 1. Session 结构 =====type Session struct {UserID intUsername stringExpiresAt time.Time// ===== 2. Session 存储 =====var (sessionStore = make(map[string]*Session)mu sync.Mutex// ===== 3. 生成 SessionID =====func newSessionID() string {return fmt.Sprintf("%d_%d", time.Now().UnixNano(), rand.Int())// ===== 4. 创建 Session =====func createSession(w http.ResponseWriter, userID int, username string) {sid := newSessionID()mu.Lock()sessionStore[sid] = &Session{UserID: userID,Username: username,ExpiresAt: time.Now().Add(30 * time.Minute),mu.Unlock()http.SetCookie(w, &http.Cookie{Name: "session_id",Value: sid,Path: "/",HttpOnly: true,// ===== 5. 获取 Session =====func getSession(r *http.Request) (*Session, bool) {cookie, err := r.Cookie("session_id")if err != nil {return nil, falsemu.Lock()defer mu.Unlock()sess, ok := sessionStore[cookie.Value]if !ok {return nil, falseif sess.ExpiresAt.Before(time.Now()) {delete(sessionStore, cookie.Value)return nil, falsereturn sess, true// ===== 6. 销毁 Session =====func destroySession(w http.ResponseWriter, r *http.Request) {cookie, err := r.Cookie("session_id")if err == nil {mu.Lock()delete(sessionStore, cookie.Value)mu.Unlock()http.SetCookie(w, &http.Cookie{Name: "session_id",Value: "",Path: "/",MaxAge: -1,// ===== 7. 登录接口 =====func loginHandler(w http.ResponseWriter, r *http.Request) {// 模拟账号校验username := r.FormValue("username")password := r.FormValue("password")if username != "admin" || password != "123456" {w.WriteHeader(http.StatusUnauthorized)w.Write([]byte("login failed"))returncreateSession(w, 1, username)w.Write([]byte("login success"))// ===== 8. 需要登录的接口 =====func profileHandler(w http.ResponseWriter, r *http.Request) {sess, ok := getSession(r)if !ok {w.WriteHeader(http.StatusUnauthorized)w.Write([]byte("please login"))returnw.Write([]byte("hello " + sess.Username))// ===== 9. 退出登录 =====func logoutHandler(w http.ResponseWriter, r *http.Request) {destroySession(w, r)w.Write([]byte("logout success"))// ===== 10. main =====func main() {rand.Seed(time.Now().UnixNano())http.HandleFunc("/login", loginHandler)http.HandleFunc("/profile", profileHandler)http.HandleFunc("/logout", logoutHandler)log.Println("server running at :8080")log.Fatal(http.ListenAndServe(":8080", nil))6.4、如何测试(一步步来)1、登录curl -i -X POST \-d "username=admin&password=123456" \http://localhost:8080/login你会看到:
Set-Cookie: session_id=xxx; HttpOnly2、带 Cookie 访问受保护接口curl -b "session_id=xxx" http://localhost:8080/profile输出:
hello admin3、退出登录curl -b "session_id=xxx" http://localhost:8080/logout6.5、这套代码覆盖的核心点- ✔ SessionID 随机生成
- ✔ Cookie + HttpOnly
- ✔ Session 过期时间
- ✔ 并发安全(sync.Mutex)
- ✔ 登录 / 校验 / 退出完整流程
一定要改的地方:
- map ➜Redis
- SessionID ➜更强随机(UUID / crypto/rand)
- 加:
- HTTPS
- Secure Cookie
- CSRF 防护
- Session 自动续期(滑动过期)
登录本质就是:服务器创建 Session,客户端保存 SessionID,之后每次请求用 SessionID 找回用户身份。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.