96 lines
3.5 KiB
Go
96 lines
3.5 KiB
Go
// Package auth 定义密码哈希池、会话令牌、API 令牌与登录锁定计数的接口。
|
||
// 本包在 T0.4 只提供契约与测试假实现;真正的 argon2 池与令牌逻辑由平台 P 实现。
|
||
package auth
|
||
|
||
import (
|
||
"context"
|
||
"errors"
|
||
"time"
|
||
)
|
||
|
||
// ErrNotImplemented 表示假实现尚未提供业务能力。
|
||
var ErrNotImplemented = errors.New("auth: not implemented")
|
||
|
||
// PasswordKind 区分哈希用途(便于日志与限流,不影响算法)。
|
||
type PasswordKind string
|
||
|
||
const (
|
||
PasswordLogin PasswordKind = "login"
|
||
PasswordTalk PasswordKind = "talk"
|
||
PasswordAdmin PasswordKind = "admin"
|
||
)
|
||
|
||
// HashPool 是 argon2id 并发池(DEVELOPMENT 第 12 节)。
|
||
type HashPool interface {
|
||
// Hash 计算 PHC 格式哈希。
|
||
Hash(ctx context.Context, kind PasswordKind, password string) (phc string, err error)
|
||
// Verify 常量时间比较;ok 为 false 时 err 仍可为 nil(密码不匹配)。
|
||
Verify(ctx context.Context, kind PasswordKind, password, phc string) (ok bool, err error)
|
||
// QueueLen 返回等待哈希的任务数(指标用)。
|
||
QueueLen() int
|
||
}
|
||
|
||
// SessionTokens 管理端会话令牌(nst_ 前缀,库中存 SHA-256)。
|
||
type SessionTokens interface {
|
||
// Issue 生成新令牌明文,返回明文与 SHA-256 十六进制(或原始哈希字节由实现约定)。
|
||
Issue(ctx context.Context) (token string, hash []byte, err error)
|
||
// HashToken 对已有令牌做 SHA-256(校验用,不走 argon2)。
|
||
HashToken(token string) []byte
|
||
// LooksLikeSessionToken 判断密码字段是否以 nst_ 开头。
|
||
LooksLikeSessionToken(credential string) bool
|
||
}
|
||
|
||
// APITokenInfo 是列表项(不含令牌明文)。
|
||
type APITokenInfo struct {
|
||
ID int64
|
||
Name string
|
||
Enabled bool
|
||
CreatedAt time.Time
|
||
LastUsedAt *time.Time
|
||
}
|
||
|
||
// APITokens 管理后台 API 令牌(nxm_ 前缀)。
|
||
type APITokens interface {
|
||
Issue(ctx context.Context) (token string, hash []byte, err error)
|
||
HashToken(token string) []byte
|
||
LooksLikeAPIToken(credential string) bool
|
||
}
|
||
|
||
// LockKind 区分锁定计数器类型。
|
||
type LockKind string
|
||
|
||
const (
|
||
// LockLoginEndpointIP:编号 + IP,5 分钟内 10 次错 → 锁该组合 5 分钟。
|
||
LockLoginEndpointIP LockKind = "login_endpoint_ip"
|
||
// LockLoginEndpoint:编号总数,1 小时内 50 次错 → 暂停该编号密码登录 1 小时。
|
||
LockLoginEndpoint LockKind = "login_endpoint"
|
||
// LockTalkPair:发送方 + 对方对话密码。
|
||
LockTalkPair LockKind = "talk_pair"
|
||
// LockTalkTarget:对方对话密码总数。
|
||
LockTalkTarget LockKind = "talk_target"
|
||
// LockAdminIP:管理员登录 / 错误 API 令牌。
|
||
LockAdminIP LockKind = "admin_ip"
|
||
// LockRegisterIP:注册安全码错误。
|
||
LockRegisterIP LockKind = "register_ip"
|
||
)
|
||
|
||
// LockKey 是一次锁定查询/计数的键。
|
||
type LockKey struct {
|
||
Kind LockKind
|
||
EndpointID string // 端编号;管理员/注册场景可空
|
||
PeerID string // 对话密码对方;可空
|
||
IP string // 来源 IP;按编号总数等场景可空
|
||
}
|
||
|
||
// LoginLocks 是内存锁定计数器(重启清零)。
|
||
type LoginLocks interface {
|
||
// Check 若当前已锁定返回 locked=true 与剩余时间。
|
||
Check(key LockKey) (locked bool, retryAfter time.Duration)
|
||
// Fail 记录一次失败;若因此触发锁定,返回 locked=true。
|
||
Fail(key LockKey) (locked bool, retryAfter time.Duration)
|
||
// ClearEndpoint 清除某端编号相关的登录锁定(两种都清),对应管理 unlock。
|
||
ClearEndpoint(endpointID string)
|
||
// Clear 清除精确键。
|
||
Clear(key LockKey)
|
||
}
|