- users 加 token_version(schema v4):改密/登出递增,该用户全部已发 access/refresh 立即作废;refresh 改轮换式换发新 cookie - 邀请码改精确匹配 + 注册成功后消费(一码一用),修复子串匹配让任意后缀放行、可无限薅体验金 - 生产校验拦下 .env.example 占位密钥;OT_ENV 枚举校验(拼错不再静默跳过断言);生产强制 COOKIE_SECURE;非 development 拒绝默认密码播种管理员 - WebAuthn 会话启用过期校验 + 4096 容量上限(未认证 login/begin 可无限撑爆内存),begin/complete 挂登录级限速 - /api/v1 挂 1MB 请求体上限;login 先限 IP 桶再解析 body;全局安全响应头 + CSP - 连接池配置(PG 30/SQLite 8);SQLite DSN 自动追加 WAL + busy_timeout(驱动只认 _pragma,旧注释的 _journal_mode 写法不生效)
65 lines
1.7 KiB
Go
65 lines
1.7 KiB
Go
package jwt
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestSignParseAccess(t *testing.T) {
|
|
m := NewManager("test-secret", "openteam", time.Hour, 24*time.Hour)
|
|
tok, exp, err := m.Sign(42, "alice", "admin", "access", 7)
|
|
if err != nil {
|
|
t.Fatalf("Sign: %v", err)
|
|
}
|
|
if exp.Before(time.Now()) {
|
|
t.Fatal("expires in the past")
|
|
}
|
|
claims, err := m.Parse(tok)
|
|
if err != nil {
|
|
t.Fatalf("Parse: %v", err)
|
|
}
|
|
if claims.UserID != 42 || claims.Username != "alice" || claims.Role != "admin" {
|
|
t.Fatalf("claims mismatch: %+v", claims)
|
|
}
|
|
if claims.Subject != "access" {
|
|
t.Fatalf("subject mismatch: %s", claims.Subject)
|
|
}
|
|
if claims.Ver != 7 {
|
|
t.Fatalf("ver mismatch: %d", claims.Ver)
|
|
}
|
|
}
|
|
|
|
// 会话版本承载撤销语义:Ver 编码进 token,校验方与用户当前版本比对
|
|
func TestClaimsCarryVersion(t *testing.T) {
|
|
m := NewManager("test-secret", "openteam", time.Hour, 24*time.Hour)
|
|
tok, _, err := m.Sign(1, "bob", "user", "refresh", 3)
|
|
if err != nil {
|
|
t.Fatalf("Sign: %v", err)
|
|
}
|
|
claims, err := m.Parse(tok)
|
|
if err != nil {
|
|
t.Fatalf("Parse: %v", err)
|
|
}
|
|
if claims.Ver != 3 || claims.Subject != "refresh" {
|
|
t.Fatalf("claims mismatch: %+v", claims)
|
|
}
|
|
}
|
|
|
|
func TestParseRejectsBadToken(t *testing.T) {
|
|
m := NewManager("test-secret", "openteam", time.Hour, 24*time.Hour)
|
|
if _, err := m.Parse("not-a-jwt"); err == nil {
|
|
t.Fatal("expected error for invalid token")
|
|
}
|
|
}
|
|
|
|
func TestExpiredToken(t *testing.T) {
|
|
m := NewManager("test-secret", "openteam", -time.Hour, -time.Hour)
|
|
tok, _, err := m.Sign(1, "bob", "user", "access", 0)
|
|
if err != nil {
|
|
t.Fatalf("Sign: %v", err)
|
|
}
|
|
if _, err := m.Parse(tok); err == nil {
|
|
t.Fatal("expected error for expired token")
|
|
}
|
|
}
|