feat(auth): JWT(HS256 stdlib) + RBAC(owner/admin/viewer) + API key + 密码 hash;config 校验

This commit is contained in:
Aska committed 2026-09-06 07:19:28 +08:00
1 parent 7f7cb8fbf7
commit a3f6f4f687
10 files changed
+1116

No files matched your search

+64
View File
@@ -0,0 +1,64 @@
package auth
import (
"encoding/base64"
"strings"
"testing"
)
func TestHashPassword_Check(t *testing.T) {
t.Parallel()
encoded, err := HashPassword("s3cret")
if err != nil {
t.Fatalf("HashPassword error: %v", err)
}
if !strings.HasPrefix(encoded, passwordScheme+"$") {
t.Errorf("encoded = %q, want %q prefix", encoded, passwordScheme+"$")
}
if !CheckPassword("s3cret", encoded) {
t.Error("CheckPassword(correct) = false, want true")
}
if CheckPassword("wrong", encoded) {
t.Error("CheckPassword(wrong) = true, want false")
}
}
func TestHashPassword_SaltRandomizes(t *testing.T) {
t.Parallel()
a, err := HashPassword("s3cret")
if err != nil {
t.Fatalf("HashPassword error: %v", err)
}
b, err := HashPassword("s3cret")
if err != nil {
t.Fatalf("HashPassword error: %v", err)
}
if a == b {
t.Error("equal passwords produced identical encodings; salt not random")
}
}
func TestCheckPassword_Malformed(t *testing.T) {
t.Parallel()
salt := base64.RawStdEncoding.EncodeToString([]byte("saltsaltsaltsalts"))
digest := base64.RawStdEncoding.EncodeToString([]byte("digestdigestdigestdigest"))
cases := []struct {
name string
enc string
}{
{"empty", ""},
{"too few parts", "sha256$onlyone"},
{"wrong scheme", "md5$" + salt + "$" + digest},
{"bad base64 salt", "sha256$!!$" + digest},
{"bad base64 digest", "sha256$" + salt + "$!!"},
}
for _, tc := range cases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
if CheckPassword("s3cret", tc.enc) {
t.Errorf("CheckPassword(%q) = true, want false", tc.enc)
}
})
}
}