Files
Wormhole/internal/auth/limiter_test.go
T
rose_cat707 612d68f56f feat: Wormhole 内网穿透与反向代理网关
Go + Vue 管理台,SQLite 持久化;支持隧道/域名穿透、域名转发插件链、访客认证、
IP 规则、API Key、Docker 单镜像部署;配置通过 Web 系统设置管理,无需 YAML 文件。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-23 12:15:02 +08:00

60 lines
1.3 KiB
Go

package auth
import (
"errors"
"testing"
"time"
"github.com/wormhole/wormhole/internal/config"
)
func TestLoginLimiterBlocksAfterMaxAttempts(t *testing.T) {
l := NewLoginLimiter(&config.AuthConfig{
LoginMaxAttempts: 3,
LoginWindow: time.Minute,
LoginLockout: 10 * time.Minute,
})
ip := "192.168.1.1"
user := "admin"
for i := 0; i < 3; i++ {
if _, blocked := l.IsBlocked(ip, user); blocked {
t.Fatalf("unexpected block at attempt %d", i+1)
}
l.RecordFailure(ip, user)
}
retry, blocked := l.IsBlocked(ip, user)
if !blocked || retry <= 0 {
t.Fatalf("expected block after max attempts, retry=%v blocked=%v", retry, blocked)
}
}
func TestLoginLimiterResetClearsBlock(t *testing.T) {
l := NewLoginLimiter(&config.AuthConfig{
LoginMaxAttempts: 2,
LoginWindow: time.Minute,
LoginLockout: time.Minute,
})
ip := "10.0.0.1"
l.RecordFailure(ip, "u1")
l.RecordFailure(ip, "u1")
if _, blocked := l.IsBlocked(ip, "u1"); !blocked {
t.Fatal("expected blocked")
}
l.Reset(ip, "u1")
if _, blocked := l.IsBlocked(ip, "u1"); blocked {
t.Fatal("expected unblocked after reset")
}
}
func TestLoginBlockedError(t *testing.T) {
err := &LoginBlockedError{RetryAfter: 30 * time.Second}
if !errors.As(err, new(*LoginBlockedError)) {
t.Fatal("LoginBlockedError should be detectable via errors.As")
}
}