mirror of
https://github.com/skyle1995/NetworkAuth.git
synced 2026-05-25 02:24:05 +08:00
更新底层架构
This commit is contained in:
178
config/config.go
178
config/config.go
@@ -5,7 +5,6 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
@@ -19,10 +18,11 @@ import (
|
||||
// ServerConfig 服务器配置结构体
|
||||
// 包含服务器运行相关的配置信息
|
||||
type ServerConfig struct {
|
||||
Host string `json:"host" mapstructure:"host"` // 服务器监听地址
|
||||
Port int `json:"port" mapstructure:"port"` // 服务器监听端口
|
||||
Dist string `json:"dist" mapstructure:"dist"` // 静态文件目录
|
||||
DevMode bool `json:"dev_mode" mapstructure:"dev_mode"` // 开发模式(跳过验证码等)
|
||||
Host string `json:"host" mapstructure:"host"` // 服务器监听地址
|
||||
Port int `json:"port" mapstructure:"port"` // 服务器监听端口
|
||||
Dist string `json:"dist" mapstructure:"dist"` // 静态文件目录
|
||||
DevMode bool `json:"dev_mode" mapstructure:"dev_mode"` // 开发模式(跳过验证码等)
|
||||
AccessLog bool `json:"access_log" mapstructure:"access_log"` // 是否输出访问日志
|
||||
}
|
||||
|
||||
// DatabaseConfig 数据库配置结构体
|
||||
@@ -71,31 +71,12 @@ type LogConfig struct {
|
||||
MaxAge int `json:"max_age" mapstructure:"max_age"` // 日志文件保留天数
|
||||
}
|
||||
|
||||
// CookieConfig Cookie配置结构体
|
||||
// 包含Cookie相关的安全配置信息
|
||||
type CookieConfig struct {
|
||||
Secure bool `json:"secure" mapstructure:"secure"` // 是否只在HTTPS下发送Cookie
|
||||
SameSite string `json:"same_site" mapstructure:"same_site"` // SameSite属性(Strict/Lax/None)
|
||||
Domain string `json:"domain" mapstructure:"domain"` // Cookie域名
|
||||
MaxAge int `json:"max_age" mapstructure:"max_age"` // Cookie最大存活时间(秒)
|
||||
}
|
||||
|
||||
// SecurityConfig 安全配置结构体
|
||||
// 包含应用程序安全相关的配置信息
|
||||
type SecurityConfig struct {
|
||||
JWTSecret string `json:"jwt_secret" mapstructure:"jwt_secret"` // JWT签名密钥
|
||||
EncryptionKey string `json:"encryption_key" mapstructure:"encryption_key"` // 数据加密密钥
|
||||
JWTRefresh int `json:"jwt_refresh" mapstructure:"jwt_refresh"` // JWT令牌刷新阈值(小时)
|
||||
Cookie CookieConfig `json:"cookie" mapstructure:"cookie"` // Cookie配置
|
||||
}
|
||||
|
||||
// AppConfig 应用配置结构体
|
||||
type AppConfig struct {
|
||||
Server ServerConfig `json:"server" mapstructure:"server"`
|
||||
Database DatabaseConfig `json:"database" mapstructure:"database"`
|
||||
Redis RedisConfig `json:"redis" mapstructure:"redis"`
|
||||
Log LogConfig `json:"log" mapstructure:"log"`
|
||||
Security SecurityConfig `json:"security" mapstructure:"security"`
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
@@ -106,10 +87,11 @@ type AppConfig struct {
|
||||
func GetDefaultAppConfig() *AppConfig {
|
||||
return &AppConfig{
|
||||
Server: ServerConfig{
|
||||
Host: "0.0.0.0",
|
||||
Port: 8080,
|
||||
Dist: "",
|
||||
DevMode: false,
|
||||
Host: "0.0.0.0",
|
||||
Port: 8080,
|
||||
Dist: "",
|
||||
DevMode: false,
|
||||
AccessLog: true,
|
||||
},
|
||||
Database: DatabaseConfig{
|
||||
Type: "sqlite",
|
||||
@@ -140,37 +122,9 @@ func GetDefaultAppConfig() *AppConfig {
|
||||
MaxBackups: 5,
|
||||
MaxAge: 30,
|
||||
},
|
||||
Security: SecurityConfig{
|
||||
JWTSecret: "",
|
||||
EncryptionKey: "",
|
||||
JWTRefresh: 6,
|
||||
Cookie: CookieConfig{
|
||||
Secure: true,
|
||||
SameSite: "Lax",
|
||||
Domain: "",
|
||||
MaxAge: 86400,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// GetSecureDefaultAppConfig 获取带有安全密钥的默认应用配置
|
||||
func GetSecureDefaultAppConfig() (*AppConfig, error) {
|
||||
config := GetDefaultAppConfig()
|
||||
|
||||
// 生成安全密钥
|
||||
jwtSecret, encryptionKey, err := GenerateSecureKeys()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 设置安全密钥
|
||||
config.Security.JWTSecret = jwtSecret
|
||||
config.Security.EncryptionKey = encryptionKey
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
// Init 初始化配置文件
|
||||
func Init(cfgFilePath string) {
|
||||
viper.SetConfigFile(cfgFilePath)
|
||||
@@ -180,18 +134,10 @@ func Init(cfgFilePath string) {
|
||||
if err := viper.ReadInConfig(); err != nil {
|
||||
var pathError *fs.PathError
|
||||
if errors.As(err, &pathError) {
|
||||
log.Warn("未找到配置文件,使用默认配置")
|
||||
log.Warn("未找到配置文件,使用默认配置在内存中运行(需通过安装页面初始化)")
|
||||
|
||||
// 生成带有安全密钥的默认配置
|
||||
defaultConfig, configErr := GetSecureDefaultAppConfig()
|
||||
if configErr != nil {
|
||||
log.WithFields(
|
||||
log.Fields{
|
||||
"err": configErr,
|
||||
},
|
||||
).Error("生成安全配置失败,使用基础默认配置")
|
||||
defaultConfig = GetDefaultAppConfig()
|
||||
}
|
||||
// 使用默认配置
|
||||
defaultConfig := GetDefaultAppConfig()
|
||||
|
||||
// 将配置结构体转换为JSON
|
||||
configBytes, marshalErr := json.MarshalIndent(defaultConfig, "", " ")
|
||||
@@ -204,25 +150,7 @@ func Init(cfgFilePath string) {
|
||||
return
|
||||
}
|
||||
|
||||
// 写入配置文件
|
||||
err = os.WriteFile(cfgFilePath, configBytes, 0o644)
|
||||
if err != nil {
|
||||
log.WithFields(
|
||||
log.Fields{
|
||||
"err": err,
|
||||
},
|
||||
).Error("写入默认配置文件失败")
|
||||
} else {
|
||||
// 只显示配置文件名,不显示完整路径
|
||||
fileName := filepath.Base(cfgFilePath)
|
||||
log.WithFields(
|
||||
log.Fields{
|
||||
"file": fileName,
|
||||
},
|
||||
).Info("写入默认配置文件成功(已生成安全密钥)")
|
||||
}
|
||||
|
||||
// 将配置加载到viper中
|
||||
// 将配置加载到viper中,但不写入文件
|
||||
err = viper.ReadConfig(bytes.NewBuffer(configBytes))
|
||||
if err != nil {
|
||||
log.WithFields(
|
||||
@@ -231,8 +159,10 @@ func Init(cfgFilePath string) {
|
||||
},
|
||||
).Error("读取默认配置失败")
|
||||
} else {
|
||||
log.Info("已成功读取默认配置")
|
||||
log.Info("已成功在内存中加载默认配置")
|
||||
}
|
||||
|
||||
// 不在这里写入文件了,安装完成后通过 UpdateConfig 写入
|
||||
} else {
|
||||
log.WithFields(
|
||||
log.Fields{
|
||||
@@ -241,7 +171,7 @@ func Init(cfgFilePath string) {
|
||||
).Fatal("配置文件解析错误")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 只显示配置文件名,不显示完整路径
|
||||
configFile := viper.ConfigFileUsed()
|
||||
if configFile != "" {
|
||||
@@ -266,24 +196,62 @@ func Init(cfgFilePath string) {
|
||||
}
|
||||
}
|
||||
|
||||
// CreateDefaultConfig 创建默认配置文件
|
||||
func CreateDefaultConfig(filePath string) error {
|
||||
// 生成带有安全密钥的默认配置
|
||||
defaultConfig, err := GetSecureDefaultAppConfig()
|
||||
if err != nil {
|
||||
log.WithFields(
|
||||
log.Fields{
|
||||
"err": err,
|
||||
},
|
||||
).Error("生成安全配置失败,使用基础默认配置")
|
||||
defaultConfig = GetDefaultAppConfig()
|
||||
}
|
||||
|
||||
// 将配置结构体转换为JSON
|
||||
configBytes, err := json.MarshalIndent(defaultConfig, "", " ")
|
||||
if err != nil {
|
||||
// UpdateConfig 更新配置文件
|
||||
// 接收一个回调函数,在回调函数中修改配置对象,然后保存到文件
|
||||
func UpdateConfig(updateFn func(*AppConfig)) error {
|
||||
// 1. 获取当前配置
|
||||
var currentConfig AppConfig
|
||||
if err := viper.Unmarshal(¤tConfig); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return os.WriteFile(filePath, configBytes, 0o644)
|
||||
// 2. 执行更新回调
|
||||
updateFn(¤tConfig)
|
||||
|
||||
// 3. 将更新后的配置写回 Viper
|
||||
// 注意:这里需要手动设置回 viper,否则 viper.WriteConfig() 写入的还是旧配置
|
||||
// 也可以直接序列化 currentConfig 写入文件
|
||||
|
||||
// 更新 Server 配置
|
||||
viper.Set("server.host", currentConfig.Server.Host)
|
||||
viper.Set("server.port", currentConfig.Server.Port)
|
||||
viper.Set("server.dist", currentConfig.Server.Dist)
|
||||
viper.Set("server.dev_mode", currentConfig.Server.DevMode)
|
||||
viper.Set("server.access_log", currentConfig.Server.AccessLog)
|
||||
|
||||
// 更新 Database 配置
|
||||
viper.Set("database.type", currentConfig.Database.Type)
|
||||
viper.Set("database.mysql.host", currentConfig.Database.MySQL.Host)
|
||||
viper.Set("database.mysql.port", currentConfig.Database.MySQL.Port)
|
||||
viper.Set("database.mysql.username", currentConfig.Database.MySQL.Username)
|
||||
viper.Set("database.mysql.password", currentConfig.Database.MySQL.Password)
|
||||
viper.Set("database.mysql.database", currentConfig.Database.MySQL.Database)
|
||||
viper.Set("database.mysql.charset", currentConfig.Database.MySQL.Charset)
|
||||
viper.Set("database.mysql.max_idle_conns", currentConfig.Database.MySQL.MaxIdleConns)
|
||||
viper.Set("database.mysql.max_open_conns", currentConfig.Database.MySQL.MaxOpenConns)
|
||||
viper.Set("database.sqlite.path", currentConfig.Database.SQLite.Path)
|
||||
|
||||
// 更新 Redis 配置
|
||||
viper.Set("redis.host", currentConfig.Redis.Host)
|
||||
viper.Set("redis.port", currentConfig.Redis.Port)
|
||||
viper.Set("redis.password", currentConfig.Redis.Password)
|
||||
viper.Set("redis.db", currentConfig.Redis.DB)
|
||||
|
||||
// 更新 Log 配置
|
||||
viper.Set("log.level", currentConfig.Log.Level)
|
||||
viper.Set("log.file", currentConfig.Log.File)
|
||||
viper.Set("log.max_size", currentConfig.Log.MaxSize)
|
||||
viper.Set("log.max_backups", currentConfig.Log.MaxBackups)
|
||||
viper.Set("log.max_age", currentConfig.Log.MaxAge)
|
||||
|
||||
// 4. 保存到文件
|
||||
if err := viper.WriteConfig(); err != nil {
|
||||
// 如果配置文件不存在(比如只用了默认配置没写文件),则尝试 SafeWriteConfig
|
||||
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
|
||||
return viper.SafeWriteConfig()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user