mirror of
https://github.com/laoxong/nofx.git
synced 2026-06-04 09:58:22 +08:00
Feat: Enable admin password in admin mode (#540)
* WIP: save local changes before merging * Enable admin password in admin mode #374
This commit is contained in:
@@ -3,6 +3,8 @@ package auth
|
||||
import (
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"log"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
@@ -17,6 +19,18 @@ var JWTSecret []byte
|
||||
// AdminMode 管理员模式标志
|
||||
var AdminMode bool = false
|
||||
|
||||
// adminPasswordHash 管理员密码哈希(仅内存)
|
||||
var adminPasswordHash string
|
||||
|
||||
// tokenBlacklist 用于登出后的token黑名单(仅内存,按过期时间清理)
|
||||
var tokenBlacklist = struct {
|
||||
sync.RWMutex
|
||||
items map[string]time.Time
|
||||
}{items: make(map[string]time.Time)}
|
||||
|
||||
// maxBlacklistEntries 黑名单最大容量阈值
|
||||
const maxBlacklistEntries = 100_000
|
||||
|
||||
// OTPIssuer OTP发行者名称
|
||||
const OTPIssuer = "nofxAI"
|
||||
|
||||
@@ -35,6 +49,59 @@ func IsAdminMode() bool {
|
||||
return AdminMode
|
||||
}
|
||||
|
||||
// SetAdminPasswordFromPlain 通过明文设置管理员密码(会使用bcrypt哈希,成本12)
|
||||
func SetAdminPasswordFromPlain(plain string) error {
|
||||
bytes, err := bcrypt.GenerateFromPassword([]byte(plain), 12)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
adminPasswordHash = string(bytes)
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckAdminPassword 校验管理员密码
|
||||
func CheckAdminPassword(plain string) bool {
|
||||
if adminPasswordHash == "" {
|
||||
return false
|
||||
}
|
||||
return bcrypt.CompareHashAndPassword([]byte(adminPasswordHash), []byte(plain)) == nil
|
||||
}
|
||||
|
||||
// BlacklistToken 将token加入黑名单直到过期
|
||||
func BlacklistToken(token string, exp time.Time) {
|
||||
tokenBlacklist.Lock()
|
||||
defer tokenBlacklist.Unlock()
|
||||
tokenBlacklist.items[token] = exp
|
||||
|
||||
// 如果超过容量阈值,则进行一次过期清理;若仍超限,记录警告日志
|
||||
if len(tokenBlacklist.items) > maxBlacklistEntries {
|
||||
now := time.Now()
|
||||
for t, e := range tokenBlacklist.items {
|
||||
if now.After(e) {
|
||||
delete(tokenBlacklist.items, t)
|
||||
}
|
||||
}
|
||||
if len(tokenBlacklist.items) > maxBlacklistEntries {
|
||||
log.Printf("auth: token blacklist size (%d) exceeds limit (%d) after sweep; consider reducing JWT TTL or using a shared persistent store",
|
||||
len(tokenBlacklist.items), maxBlacklistEntries)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// IsTokenBlacklisted 检查token是否在黑名单中(过期自动清理)
|
||||
func IsTokenBlacklisted(token string) bool {
|
||||
tokenBlacklist.Lock()
|
||||
defer tokenBlacklist.Unlock()
|
||||
if exp, ok := tokenBlacklist.items[token]; ok {
|
||||
if time.Now().After(exp) {
|
||||
delete(tokenBlacklist.items, token)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Claims JWT声明
|
||||
type Claims struct {
|
||||
UserID string `json:"user_id"`
|
||||
|
||||
Reference in New Issue
Block a user