feat: 实现 argon2 哈希池、令牌与登录锁定计数
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"runtime"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
// Pool 是 argon2id 并发池(DEVELOPMENT 第 12 节)。
|
||||
type Pool struct {
|
||||
sem chan struct{}
|
||||
waiting atomic.Int64
|
||||
active atomic.Int64
|
||||
maxSeen atomic.Int64 // 测试用:观察到的最大并发
|
||||
}
|
||||
|
||||
// NewPool 创建大小为 CPU 核数的哈希池。
|
||||
func NewPool() *Pool {
|
||||
return NewPoolSize(runtime.NumCPU())
|
||||
}
|
||||
|
||||
// NewPoolSize 创建指定并发上限的哈希池(测试可传入 1)。
|
||||
func NewPoolSize(n int) *Pool {
|
||||
if n < 1 {
|
||||
n = 1
|
||||
}
|
||||
return &Pool{sem: make(chan struct{}, n)}
|
||||
}
|
||||
|
||||
// Hash 在池内计算 PHC 格式哈希。
|
||||
func (p *Pool) Hash(ctx context.Context, _ PasswordKind, password string) (string, error) {
|
||||
if err := p.acquire(ctx); err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer p.release()
|
||||
return HashPassword(password)
|
||||
}
|
||||
|
||||
// Verify 在池内校验;常量时间比较。
|
||||
func (p *Pool) Verify(ctx context.Context, _ PasswordKind, password, phc string) (bool, error) {
|
||||
if err := p.acquire(ctx); err != nil {
|
||||
return false, err
|
||||
}
|
||||
defer p.release()
|
||||
return VerifyPassword(password, phc)
|
||||
}
|
||||
|
||||
// QueueLen 返回等待获取池槽位的任务数。
|
||||
func (p *Pool) QueueLen() int {
|
||||
return int(p.waiting.Load())
|
||||
}
|
||||
|
||||
// MaxActive 返回曾达到的最大并发哈希数(测试用)。
|
||||
func (p *Pool) MaxActive() int {
|
||||
return int(p.maxSeen.Load())
|
||||
}
|
||||
|
||||
func (p *Pool) acquire(ctx context.Context) error {
|
||||
p.waiting.Add(1)
|
||||
select {
|
||||
case p.sem <- struct{}{}:
|
||||
p.waiting.Add(-1)
|
||||
cur := p.active.Add(1)
|
||||
for {
|
||||
old := p.maxSeen.Load()
|
||||
if cur <= old || p.maxSeen.CompareAndSwap(old, cur) {
|
||||
break
|
||||
}
|
||||
}
|
||||
return nil
|
||||
case <-ctx.Done():
|
||||
p.waiting.Add(-1)
|
||||
return ctx.Err()
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Pool) release() {
|
||||
p.active.Add(-1)
|
||||
<-p.sem
|
||||
}
|
||||
|
||||
var _ HashPool = (*Pool)(nil)
|
||||
Reference in New Issue
Block a user