Add PgStore with hashed token sessions, IAM bootstrap, and store factory wiring; remove in-memory token map and allow_dev_switch from login payload.
78 lines
2.0 KiB
Go
78 lines
2.0 KiB
Go
package auth
|
|
|
|
import (
|
|
"context"
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"errors"
|
|
"time"
|
|
)
|
|
|
|
var errSessionNotFound = errors.New("session not found or expired")
|
|
|
|
const (
|
|
defaultIdleSessionTTL = 24 * time.Hour
|
|
defaultAbsoluteSessionTTL = 7 * 24 * time.Hour
|
|
)
|
|
|
|
// SessionMeta 创建会话时的客户端元数据(可选)。
|
|
type SessionMeta struct {
|
|
IPHash string
|
|
UserAgent string
|
|
}
|
|
|
|
// SessionStore 持久化或内存会话存储。
|
|
type SessionStore interface {
|
|
CreateSession(ctx context.Context, userID int64, tokenHash string, meta SessionMeta) error
|
|
ResolveUserID(ctx context.Context, tokenHash string) (int64, error)
|
|
TouchSession(ctx context.Context, tokenHash string) error
|
|
RevokeByTokenHash(ctx context.Context, tokenHash string) error
|
|
RevokeAllForUser(ctx context.Context, userID int64) error
|
|
}
|
|
|
|
// HashToken 将会话 token 转为存储用 SHA-256 十六进制摘要。
|
|
func HashToken(token string) string {
|
|
sum := sha256.Sum256([]byte(token))
|
|
return hex.EncodeToString(sum[:])
|
|
}
|
|
|
|
// MemorySessionStore 进程内 token 映射(仅 dev/stub fallback)。
|
|
type MemorySessionStore struct {
|
|
tokens map[string]int64
|
|
}
|
|
|
|
func NewMemorySessionStore() *MemorySessionStore {
|
|
return &MemorySessionStore{tokens: make(map[string]int64)}
|
|
}
|
|
|
|
func (s *MemorySessionStore) CreateSession(_ context.Context, userID int64, tokenHash string, _ SessionMeta) error {
|
|
s.tokens[tokenHash] = userID
|
|
return nil
|
|
}
|
|
|
|
func (s *MemorySessionStore) ResolveUserID(_ context.Context, tokenHash string) (int64, error) {
|
|
userID, ok := s.tokens[tokenHash]
|
|
if !ok {
|
|
return 0, errSessionNotFound
|
|
}
|
|
return userID, nil
|
|
}
|
|
|
|
func (s *MemorySessionStore) TouchSession(_ context.Context, _ string) error {
|
|
return nil
|
|
}
|
|
|
|
func (s *MemorySessionStore) RevokeByTokenHash(_ context.Context, tokenHash string) error {
|
|
delete(s.tokens, tokenHash)
|
|
return nil
|
|
}
|
|
|
|
func (s *MemorySessionStore) RevokeAllForUser(_ context.Context, userID int64) error {
|
|
for tok, uid := range s.tokens {
|
|
if uid == userID {
|
|
delete(s.tokens, tok)
|
|
}
|
|
}
|
|
return nil
|
|
}
|