From 808ce8f0bfa59f6333c27391b6983bdd67fd0bd6 Mon Sep 17 00:00:00 2001
From: zhangzengfei <zhangzengfei@smartai.com>
Date: 星期二, 16 四月 2024 14:37:18 +0800
Subject: [PATCH] 调整缓存的数据
---
pkg/auth/users.go | 151 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 151 insertions(+), 0 deletions(-)
diff --git a/pkg/auth/users.go b/pkg/auth/users.go
new file mode 100644
index 0000000..ba032fe
--- /dev/null
+++ b/pkg/auth/users.go
@@ -0,0 +1,151 @@
+package auth
+
+import (
+ "encoding/csv"
+ "os"
+ "sync"
+)
+
+// SecretProvider is used by authenticators. Takes user name and realm
+// as an argument, returns secret required for authentication (HA1 for
+// digest authentication, properly encrypted password for basic).
+//
+// Returning an empty string means failing the authentication.
+type SecretProvider func(user, realm string) string
+
+// File handles automatic file reloading on changes.
+type File struct {
+ Path string
+ Info os.FileInfo
+ /* must be set in inherited types during initialization */
+ Reload func()
+ mu sync.Mutex
+}
+
+// ReloadIfNeeded checks file Stat and calls Reload() if any changes
+// were detected. File mutex is Locked for the duration of Reload()
+// call.
+//
+// This function will panic() if Stat fails.
+func (f *File) ReloadIfNeeded() {
+ info, err := os.Stat(f.Path)
+ if err != nil {
+ panic(err)
+ }
+ f.mu.Lock()
+ defer f.mu.Unlock()
+ if f.Info == nil || f.Info.ModTime() != info.ModTime() {
+ f.Info = info
+ f.Reload()
+ }
+}
+
+// HtdigestFile is a File holding htdigest authentication data.
+type HtdigestFile struct {
+ // File is used for automatic reloading of the authentication data.
+ File
+ // Users is a map of realms to users to HA1 digests.
+ Users map[string]map[string]string
+ mu sync.RWMutex
+}
+
+func reloadHTDigest(hf *HtdigestFile) {
+ r, err := os.Open(hf.Path)
+ if err != nil {
+ panic(err)
+ }
+ reader := csv.NewReader(r)
+ reader.Comma = ':'
+ reader.Comment = '#'
+ reader.TrimLeadingSpace = true
+
+ records, err := reader.ReadAll()
+ if err != nil {
+ panic(err)
+ }
+
+ hf.mu.Lock()
+ defer hf.mu.Unlock()
+ hf.Users = make(map[string]map[string]string)
+ for _, record := range records {
+ _, exists := hf.Users[record[1]]
+ if !exists {
+ hf.Users[record[1]] = make(map[string]string)
+ }
+ hf.Users[record[1]][record[0]] = record[2]
+ }
+}
+
+// HtdigestFileProvider is a SecretProvider implementation based on
+// htdigest-formated files. It will automatically reload htdigest file
+// on changes. It panics on syntax errors in htdigest files.
+func HtdigestFileProvider(filename string) SecretProvider {
+ hf := &HtdigestFile{File: File{Path: filename}}
+ hf.Reload = func() { reloadHTDigest(hf) }
+ return func(user, realm string) string {
+ hf.ReloadIfNeeded()
+ hf.mu.RLock()
+ defer hf.mu.RUnlock()
+ _, exists := hf.Users[realm]
+ if !exists {
+ return ""
+ }
+ digest, exists := hf.Users[realm][user]
+ if !exists {
+ return ""
+ }
+ return digest
+ }
+}
+
+// HtpasswdFile is a File holding basic authentication data.
+type HtpasswdFile struct {
+ // File is used for automatic reloading of the authentication data.
+ File
+ // Users is a map of users to their secrets (salted encrypted
+ // passwords).
+ Users map[string]string
+ mu sync.RWMutex
+}
+
+func reloadHTPasswd(h *HtpasswdFile) {
+ r, err := os.Open(h.Path)
+ if err != nil {
+ panic(err)
+ }
+ reader := csv.NewReader(r)
+ reader.Comma = ':'
+ reader.Comment = '#'
+ reader.TrimLeadingSpace = true
+
+ records, err := reader.ReadAll()
+ if err != nil {
+ panic(err)
+ }
+
+ h.mu.Lock()
+ defer h.mu.Unlock()
+ h.Users = make(map[string]string)
+ for _, record := range records {
+ h.Users[record[0]] = record[1]
+ }
+}
+
+// HtpasswdFileProvider is a SecretProvider implementation based on
+// htpasswd-formated files. It will automatically reload htpasswd file
+// on changes. It panics on syntax errors in htpasswd files. Realm
+// argument of the SecretProvider is ignored.
+func HtpasswdFileProvider(filename string) SecretProvider {
+ h := &HtpasswdFile{File: File{Path: filename}}
+ h.Reload = func() { reloadHTPasswd(h) }
+ return func(user, realm string) string {
+ h.ReloadIfNeeded()
+ h.mu.RLock()
+ password, exists := h.Users[user]
+ h.mu.RUnlock()
+ if !exists {
+ return ""
+ }
+ return password
+ }
+}
--
Gitblit v1.8.0