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 到期字段依赖
This commit is contained in:
2026-05-30 23:36:52 +08:00
parent 53f84bfcc4
commit daf87f895b
28 changed files with 617 additions and 482 deletions

View File

@ -2,8 +2,7 @@ package service
import "metazone.cc/metalab/internal/model"
// userAuthStore AuthService 所需的最小仓储接口ISP7 个方法)
// 同时满足 common.UsernameCheckerExistsByUsername可传入 GenerateUsername
// userAuthStore AuthService 所需的最小仓储接口ISP8 个方法)
type userAuthStore interface {
ExistsByEmail(email string) (bool, error)
Create(user *model.User) error
@ -14,12 +13,12 @@ type userAuthStore interface {
ExistsByUsername(username string) (bool, error)
}
// userTokenStore TokenService 所需的最小仓储接口ISP1 个方法)
// userTokenStore 已废弃JWT 替换为 Session保留占位
type userTokenStore interface {
FindByIDForAuth(userID uint) (*model.User, error)
}
// userAdminStore AdminService 所需的最小仓储接口ISP8 个方法)
// userAdminStore AdminService 所需的最小仓储接口
type userAdminStore interface {
CountSearchUsers(keyword, role, status string) (int64, error)
SearchUsers(keyword, role, status string, offset, limit int) ([]model.User, error)
@ -31,7 +30,7 @@ type userAdminStore interface {
IncrementTokenVersion(userID uint) error
}
// postStore PostService 所需的最小仓储接口ISP10 个方法)
// postStore PostService 所需的最小仓储接口
type postStore interface {
Create(post *model.Post) error
FindByID(id uint) (*model.Post, error)
@ -45,18 +44,18 @@ type postStore interface {
Restore(id uint) error
}
// spaceUserStore SpaceService 所需的最小用户仓储接口ISP1 个方法)
// spaceUserStore SpaceService 所需的最小用户仓储接口
type spaceUserStore interface {
FindByID(id uint) (*model.User, error)
}
// spacePostStore SpaceService 所需的最小帖子仓储接口ISP1 个方法)
// spacePostStore SpaceService 所需的最小帖子仓储接口
type spacePostStore interface {
FindByUserID(userID uint, offset, limit int) ([]model.Post, int64, error)
}
// postNotifier PostService 所需的通知服务接口ISP2 个方法)
// postNotifier PostService 所需的通知服务接口
type postNotifier interface {
NotifyPostApproved(userID uint, postTitle string, postID uint)
NotifyPostRejected(userID uint, postTitle, reason string, postID uint)
}
}