package model import "time" // RefreshToken 刷新令牌(支撑「记住登录」,库内只存 SHA-256 摘要,明文仅返回一次)。 // // 设计要点: // 1. 一次性轮换:每次刷新都签发新令牌并撤销旧令牌,旧令牌的 RotatedTo 记录新令牌摘要; // 2. 重放检测:已撤销的令牌再次出现 → 视为令牌泄漏,撤销该用户全部刷新令牌(强制重登); // 3. 与 users.token_valid_after 配合:改密码后旧令牌的 refresh 也会被主动撤销。 // Logan.Li type RefreshToken struct { ID uint `json:"id" gorm:"primaryKey"` UserID uint `json:"user_id" gorm:"index;not null"` TokenHash string `json:"-" gorm:"size:64;uniqueIndex;not null"` // SHA-256(明文令牌) 十六进制 ExpiresAt time.Time `json:"expires_at" gorm:"index;not null"` RevokedAt *time.Time `json:"revoked_at,omitempty"` RotatedTo string `json:"-" gorm:"size:64"` // 轮换后的新令牌摘要(重放链追踪) IP string `json:"ip" gorm:"size:64"` UserAgent string `json:"user_agent" gorm:"size:255"` LastUsed *time.Time `json:"last_used,omitempty"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } // TableName 指定表名,避开 GORM 复数推导 // Logan.Li func (RefreshToken) TableName() string { return "refresh_tokens" }