This repository has been archived on 2026-06-21. You can view files and clone it, but cannot push or open issues or pull requests.
Files
MetaLab/internal/controller/auth_api_register.go
Victor_Jay daf87f895b refactor: JWT 无状态认证替换为服务端 Session,修复记住我掉线问题
- 新增 internal/session 包:Session 结构体、Store 接口、MemoryStore(内存+后台清理)、RedisStore 预留
- Cookie 从 3 个精简为 1 个 mlb_sid(HttpOnly),移除 JWT access/refresh cookie
- 会话过期采用滑动窗口:每次请求自动续期,记住我 30 天无操作过期
- AuthMiddleware/AuthAdmin/Maintenance 中间件改用 SessionManager.Validate()
- AuthService Login/Register/ConfirmRestore 去除 token 生成,返回 *model.User
- Controller 层在登录/注册后调用 SessionManager.Create 创建会话
- AdminService UpdateUserStatus/ResetUserToken 同步销毁 session 实现即时退登
- 改密/注销时通过 DestroyByUID 删除所有 session(替换 TokenVersion 检查)
- config.yaml 新增 session 配置段(idle_timeout/remember_timeout/cleanup_interval)
- TokenService/auth_parser/auth_token 标记废弃,移除 JWT 到期字段依赖
2026-05-30 23:36:52 +08:00

106 lines
3.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package controller
import (
"net/http"
"metazone.cc/metalab/internal/common"
"metazone.cc/metalab/internal/model"
"github.com/gin-gonic/gin"
)
// CheckEmail 检查邮箱是否已注册
func (ac *AuthController) CheckEmail(c *gin.Context) {
var req model.CheckEmailRequest
if err := c.ShouldBindJSON(&req); err != nil {
common.Error(c, http.StatusBadRequest, "请提供有效的邮箱地址")
return
}
exists, err := ac.authService.CheckEmail(req.Email)
if err != nil {
common.Error(c, http.StatusInternalServerError, "检查失败")
return
}
common.Ok(c, gin.H{"exists": exists})
}
// Register 注册 API
func (ac *AuthController) Register(c *gin.Context) {
var req model.RegisterRequest
if err := c.ShouldBindJSON(&req); err != nil {
common.Error(c, http.StatusBadRequest, "请检查输入:"+err.Error())
return
}
// 注册 IP 限流1 分钟 5 次
regResult, recordReg := ac.rateLimiter.AllowIP(clientIP(c) + ":register")
if regResult.Blocked {
common.Error(c, http.StatusTooManyRequests, "注册请求过于频繁,请稍后重试")
return
}
user, err := ac.authService.Register(req, clientIP(c))
if err != nil {
if recordReg != nil {
recordReg()
}
switch err {
case common.ErrMaintenanceMode:
common.Error(c, http.StatusForbidden, "社区正在维护中,暂不支持注册")
case common.ErrEmailExists:
common.Error(c, http.StatusConflict, "该邮箱已注册")
case common.ErrWeakPassword:
common.Error(c, http.StatusBadRequest, err.Error())
case common.ErrRegistrationDisabled:
common.Error(c, http.StatusForbidden, "注册功能已关闭")
default:
common.Error(c, http.StatusInternalServerError, "注册失败,请稍后重试")
}
return
}
sid, err := ac.sessionManager.Create(user, req.RememberMe)
if err != nil {
common.Error(c, http.StatusInternalServerError, "注册失败,请稍后重试")
return
}
common.SetSessionCookie(c, sid, req.RememberMe, ac.cfg)
common.OkWithMessage(c, user, "注册成功!欢迎加入 MetaLab")
}
// Logout 退出登录:删除服务端 session + 清除 Cookie
func (ac *AuthController) Logout(c *gin.Context) {
if sid, err := c.Cookie(common.SessionCookieName); err == nil && sid != "" {
_ = ac.sessionManager.Destroy(sid)
}
common.ClearSessionCookie(c, ac.cfg)
common.OkMessage(c, "已退出登录")
}
// RefreshToken 检查登录状态并续期session 模式下每次请求已自动续期,此端点用于前端显式检查)
func (ac *AuthController) RefreshToken(c *gin.Context) {
sid, err := c.Cookie(common.SessionCookieName)
if err != nil || sid == "" {
common.Error(c, http.StatusUnauthorized, "请重新登录")
return
}
s, err := ac.sessionManager.Validate(sid)
if err != nil || s == nil {
common.ClearSessionCookie(c, ac.cfg)
common.Error(c, http.StatusUnauthorized, "登录凭证已失效,请重新登录")
return
}
common.Ok(c, gin.H{
"uid": s.UserID,
"email": s.Email,
"username": s.Username,
"role": s.Role,
})
}