Ver código fonte

增加自动获取所有配置文件方法,成功注册到数据库

qdy 1 mês atrás
pai
commit
73a6b9e295

+ 93
- 0
auth/basic_auth_middewara.go Ver arquivo

1
+package auth
2
+
3
+import (
4
+	"encoding/base64"
5
+	"net/http"
6
+	"strings"
7
+	"time"
8
+
9
+	"git.x2erp.com/qdy/go-base/config"
10
+	"git.x2erp.com/qdy/go-base/ctx"
11
+)
12
+
13
+// BasicAuth 简化的Basic认证中间件
14
+func BasicAuth(next http.Handler) http.Handler {
15
+	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
16
+		// 1. 检查认证头
17
+		authHeader := r.Header.Get("Authorization")
18
+		if authHeader == "" {
19
+			unauthorized(w, "缺少认证信息")
20
+			return
21
+		}
22
+
23
+		// 2. 检查Basic格式
24
+		if !strings.HasPrefix(authHeader, "Basic ") {
25
+			unauthorized(w, "认证格式错误,请使用Basic认证")
26
+			return
27
+		}
28
+
29
+		// 3. 解码凭证
30
+		base64Creds := strings.TrimPrefix(authHeader, "Basic ")
31
+		credsBytes, err := base64.StdEncoding.DecodeString(base64Creds)
32
+		if err != nil {
33
+			unauthorized(w, "认证信息解码失败")
34
+			return
35
+		}
36
+
37
+		// 4. 分割用户名密码
38
+		creds := string(credsBytes)
39
+		parts := strings.SplitN(creds, ":", 2)
40
+		if len(parts) != 2 {
41
+			unauthorized(w, "用户名密码格式错误")
42
+			return
43
+		}
44
+
45
+		username := parts[0]
46
+		password := parts[1]
47
+
48
+		// 5. 验证用户名密码
49
+		userID, tenantID, ok := verifyCredentials(username, password)
50
+		if !ok {
51
+			unauthorized(w, "用户名或密码错误")
52
+			return
53
+		}
54
+
55
+		// 6. 创建请求上下文
56
+		traceID := r.Header.Get("X-Trace-ID")
57
+		if traceID == "" {
58
+			// 生成简单的时间戳追踪ID
59
+			traceID = time.Now().Format("20060102150405.000")
60
+		}
61
+
62
+		cfg := config.GetConfig()
63
+
64
+		requestCtx := &ctx.RequestContext{
65
+			ServiceName:  cfg.GetServiceConfig().ServiceName,
66
+			InstanceName: cfg.GetServiceConfig().InstanceName,
67
+			TraceID:      traceID,
68
+			TenantID:     tenantID,
69
+			UserID:       userID,
70
+			Username:     username,
71
+		}
72
+
73
+		// 7. 保存到请求
74
+		r = ctx.SaveContext(r, requestCtx)
75
+
76
+		// 8. 继续处理
77
+		next.ServeHTTP(w, r)
78
+	})
79
+}
80
+
81
+// 验证用户名密码(简单示例)
82
+func verifyCredentials(username, password string) (userID, tenantID string, ok bool) {
83
+
84
+	// 这里替换为你的实际验证逻辑
85
+	cfg := config.GetConfig()
86
+	sysUsername := cfg.GetServiceConfig().Username
87
+	sysPassword := cfg.GetServiceConfig().Password
88
+
89
+	if username == sysUsername && password == sysPassword {
90
+		return sysUsername, "tenant-admin", true
91
+	}
92
+	return "", "", false
93
+}

+ 27
- 0
auth/error_unauthorized.go Ver arquivo

1
+package auth
2
+
3
+import (
4
+	"encoding/json"
5
+	"net/http"
6
+	"time"
7
+
8
+	"git.x2erp.com/qdy/go-base/logger"
9
+)
10
+
11
+// 未授权响应
12
+func unauthorized(w http.ResponseWriter, message string) {
13
+	w.Header().Set("Content-Type", "application/json")
14
+	w.WriteHeader(http.StatusUnauthorized)
15
+
16
+	// 简单JSON响应
17
+	response := map[string]interface{}{
18
+		"success": false,
19
+		"error":   message,
20
+		"time":    time.Now().Format(time.RFC3339),
21
+	}
22
+
23
+	json.NewEncoder(w).Encode(response)
24
+
25
+	// 记录日志
26
+	logger.Warn("Basic认证失败: %s", message)
27
+}

+ 81
- 0
auth/token_auth_middleware.go Ver arquivo

1
+package auth
2
+
3
+import (
4
+	"net/http"
5
+	"strings"
6
+
7
+	"git.x2erp.com/qdy/go-base/config"
8
+	"git.x2erp.com/qdy/go-base/ctx"
9
+	"git.x2erp.com/qdy/go-base/logger"
10
+)
11
+
12
+// // 全局配置(单例)
13
+// var appConfig config.IConfig
14
+
15
+// // ResponseFormat 响应格式
16
+// type ResponseFormat int
17
+
18
+// const (
19
+// 	FormatJSON ResponseFormat = iota
20
+// 	FormatCSV
21
+// )
22
+
23
+// // JWTAuthMiddlewareInit 初始化中间件配置
24
+// func JWTAuthMiddlewareInit(config config.IConfig) {
25
+// 	appConfig = config
26
+// }
27
+
28
+// JWT认证中间件(支持指定响应格式)
29
+func TokenAuth(next http.Handler) http.Handler {
30
+	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
31
+
32
+		// 从Header获取Authorization
33
+		authHeader := r.Header.Get("Authorization")
34
+
35
+		// 检查Authorization头是否存在
36
+		if authHeader == "" {
37
+			unauthorized(w, "Authorization header is required")
38
+
39
+		}
40
+
41
+		// 检查Bearer格式
42
+		if !strings.HasPrefix(authHeader, "Bearer ") {
43
+			unauthorized(w, "Authorization header must start with 'Bearer '")
44
+
45
+		}
46
+
47
+		token := strings.TrimPrefix(authHeader, "Bearer ")
48
+
49
+		// 验证JWT令牌
50
+		if !isValidToken(token) {
51
+			unauthorized(w, "Invalid token")
52
+		}
53
+
54
+		appConfig := config.GetConfig()
55
+		//保存上下文
56
+		// 创建LoggerContext(从token解析用户信息)
57
+		requestContext := &ctx.RequestContext{
58
+			ServiceName:  appConfig.GetServiceConfig().ServiceName,
59
+			InstanceName: appConfig.GetServiceConfig().InstanceName,
60
+			TraceID:      "trace_id-123", // 生成追踪ID
61
+			TenantID:     "tenant-123",   // 从token解析
62
+			UserID:       "user-456",     // 从token解析
63
+		}
64
+
65
+		if logger.IsDebug() {
66
+			logger.DebugC(requestContext, "Before save requestContext: %+v", requestContext)
67
+		}
68
+
69
+		// 保存到请求
70
+		r = ctx.SaveContext(r, requestContext)
71
+		// 继续处理请求
72
+		next.ServeHTTP(w, r)
73
+	})
74
+}
75
+
76
+// 验证令牌(需要根据实际项目实现)
77
+func isValidToken(token string) bool {
78
+	// TODO: 实现真正的JWT验证逻辑
79
+	// 暂时简化处理
80
+	return token != ""
81
+}

+ 17
- 7
config/config.go Ver arquivo

27
 	//服务支持
27
 	//服务支持
28
 	GetServiceConfig() *subconfigs.ServiceConfig       //获取默认微服务配置
28
 	GetServiceConfig() *subconfigs.ServiceConfig       //获取默认微服务配置
29
 	GetMcpServiceConfig() *subconfigs.McpServiceConfig //获取默认微服务配置
29
 	GetMcpServiceConfig() *subconfigs.McpServiceConfig //获取默认微服务配置
30
+	GetConfigureConfig() *subconfigs.ConfigureConfig
30
 
31
 
31
 	// 其他配置(保持不变)
32
 	// 其他配置(保持不变)
32
 	GetRedisConfig() *subconfigs.RedisConfig
33
 	GetRedisConfig() *subconfigs.RedisConfig
52
 	GetAppName() string
53
 	GetAppName() string
53
 	GetAppVersion() string
54
 	GetAppVersion() string
54
 	GetAppEnv() string
55
 	GetAppEnv() string
55
-	GetAppAuthToken() string
56
 }
56
 }
57
 
57
 
58
 // Config 主配置结构体 - 访问门面
58
 // Config 主配置结构体 - 访问门面
111
 	return nil
111
 	return nil
112
 }
112
 }
113
 
113
 
114
+func (c *Config) GetConfigureConfig() *subconfigs.ConfigureConfig {
115
+	if config := core.GetRegisteredConfig("configure"); config != nil {
116
+		return config.(*subconfigs.ConfigureConfig)
117
+	}
118
+	return nil
119
+}
120
+
114
 func (c *Config) GetMongoDBConfig() *subconfigs.MongoDBConfig {
121
 func (c *Config) GetMongoDBConfig() *subconfigs.MongoDBConfig {
115
 	if config := core.GetRegisteredConfig("mongodb"); config != nil {
122
 	if config := core.GetRegisteredConfig("mongodb"); config != nil {
116
 		return config.(*subconfigs.MongoDBConfig)
123
 		return config.(*subconfigs.MongoDBConfig)
216
 	return c.GetServiceConfig().AppName
223
 	return c.GetServiceConfig().AppName
217
 }
224
 }
218
 
225
 
219
-// GetAppAuthToken 得到当前配置文件里的token
220
-func (c *Config) GetAppAuthToken() string {
221
-	return c.GetServiceConfig().AppAuthToken
222
-}
223
-
224
 // GetDatabaseConfig 包级便捷函数 - 按名称获取数据库配置
226
 // GetDatabaseConfig 包级便捷函数 - 按名称获取数据库配置
225
 func GetDatabaseConfig() *subconfigs.DatabaseConfig {
227
 func GetDatabaseConfig() *subconfigs.DatabaseConfig {
226
 	if cfgInstance == nil {
228
 	if cfgInstance == nil {
245
 	return cfgInstance.GetRedisConfig()
247
 	return cfgInstance.GetRedisConfig()
246
 }
248
 }
247
 
249
 
248
-// GetRedis 包级便捷函数 - 获取Redis配置
250
+// GetConsulConfig 包级便捷函数 - 获取ConsulConfig配置
249
 func GetConsulConfig() *subconfigs.ConsulConfig {
251
 func GetConsulConfig() *subconfigs.ConsulConfig {
250
 	if cfgInstance == nil {
252
 	if cfgInstance == nil {
251
 		return &subconfigs.ConsulConfig{}
253
 		return &subconfigs.ConsulConfig{}
253
 	return cfgInstance.GetConsulConfig()
255
 	return cfgInstance.GetConsulConfig()
254
 }
256
 }
255
 
257
 
258
+// GetConfigureConfig 包级便捷函数 - 获取GetConfigureConfig配置
259
+func GetConfigureConfig() *subconfigs.ConfigureConfig {
260
+	if cfgInstance == nil {
261
+		return &subconfigs.ConfigureConfig{}
262
+	}
263
+	return cfgInstance.GetConfigureConfig()
264
+}
265
+
256
 // GetHTTP 包级便捷函数 - 获取HTTP配置
266
 // GetHTTP 包级便捷函数 - 获取HTTP配置
257
 func GetHTTPConfig() *subconfigs.HTTPConfig {
267
 func GetHTTPConfig() *subconfigs.HTTPConfig {
258
 	if cfgInstance == nil {
268
 	if cfgInstance == nil {

config/core/core_metadata_config.go → config/core/core_create_meta.go Ver arquivo

14
 
14
 
15
 // FieldMeta 字段元信息
15
 // FieldMeta 字段元信息
16
 type FieldMeta struct {
16
 type FieldMeta struct {
17
-	Type    string `json:"type"`    // 字段类型,如 "string"
18
-	YamlTag string `json:"yamlTag"` // YAML标签,如 "address"
19
-	Desc    string `json:"desc"`    // 字段描述
17
+	Type     string `json:"type"`     // 字段类型,如 "string"
18
+	YamlName string `json:"yamlName"` // YAML标签,如 "address"
19
+	Desc     string `json:"desc"`     // 字段描述
20
 }
20
 }
21
 
21
 
22
 // GetAllConfigsMeta 获取所有配置的元信息
22
 // GetAllConfigsMeta 获取所有配置的元信息
89
 				if valueType.Kind() == reflect.Struct {
89
 				if valueType.Kind() == reflect.Struct {
90
 					// 创建FieldMeta
90
 					// 创建FieldMeta
91
 					fieldMeta := FieldMeta{
91
 					fieldMeta := FieldMeta{
92
-						Type:    field.Type.String(),
93
-						YamlTag: yamlTag,
94
-						Desc:    field.Tag.Get("desc"),
92
+						Type:     field.Type.String(),
93
+						YamlName: yamlTag,
94
+						Desc:     field.Tag.Get("desc"),
95
 					}
95
 					}
96
 
96
 
97
 					// 提取结构体字段
97
 					// 提取结构体字段
109
 				} else {
109
 				} else {
110
 					// 不是结构体类型,只显示map本身
110
 					// 不是结构体类型,只显示map本身
111
 					meta.Fields[field.Name] = FieldMeta{
111
 					meta.Fields[field.Name] = FieldMeta{
112
-						Type:    field.Type.String(),
113
-						YamlTag: yamlTag,
114
-						Desc:    field.Tag.Get("desc"),
112
+						Type:     field.Type.String(),
113
+						YamlName: yamlTag,
114
+						Desc:     field.Tag.Get("desc"),
115
 					}
115
 					}
116
 				}
116
 				}
117
 			} else if fieldType.Kind() == reflect.Struct ||
117
 			} else if fieldType.Kind() == reflect.Struct ||
124
 			} else {
124
 			} else {
125
 				// 其他类型
125
 				// 其他类型
126
 				meta.Fields[field.Name] = FieldMeta{
126
 				meta.Fields[field.Name] = FieldMeta{
127
-					Type:    field.Type.String(),
128
-					YamlTag: yamlTag,
129
-					Desc:    field.Tag.Get("desc"),
127
+					Type:     field.Type.String(),
128
+					YamlName: yamlTag,
129
+					Desc:     field.Tag.Get("desc"),
130
 				}
130
 				}
131
 			}
131
 			}
132
 			continue
132
 			continue
134
 
134
 
135
 		// 处理普通字段
135
 		// 处理普通字段
136
 		meta.Fields[field.Name] = FieldMeta{
136
 		meta.Fields[field.Name] = FieldMeta{
137
-			Type:    field.Type.String(),
138
-			YamlTag: yamlTag,
139
-			Desc:    field.Tag.Get("desc"),
137
+			Type:     field.Type.String(),
138
+			YamlName: yamlTag,
139
+			Desc:     field.Tag.Get("desc"),
140
 		}
140
 		}
141
 	}
141
 	}
142
 
142
 
155
 		}
155
 		}
156
 
156
 
157
 		fields[field.Name] = FieldMeta{
157
 		fields[field.Name] = FieldMeta{
158
-			Type:    field.Type.String(),
159
-			YamlTag: field.Tag.Get("yaml"),
160
-			Desc:    field.Tag.Get("desc"),
158
+			Type:     field.Type.String(),
159
+			YamlName: field.Tag.Get("yaml"),
160
+			Desc:     field.Tag.Get("desc"),
161
 		}
161
 		}
162
 	}
162
 	}
163
 }
163
 }
174
 		}
174
 		}
175
 
175
 
176
 		fields[field.Name] = FieldMeta{
176
 		fields[field.Name] = FieldMeta{
177
-			Type:    field.Type.String(),
178
-			YamlTag: field.Tag.Get("yaml"),
179
-			Desc:    field.Tag.Get("desc"),
177
+			Type:     field.Type.String(),
178
+			YamlName: field.Tag.Get("yaml"),
179
+			Desc:     field.Tag.Get("desc"),
180
 		}
180
 		}
181
 	}
181
 	}
182
 }
182
 }

+ 56
- 0
config/loader.go Ver arquivo

67
 	return output
67
 	return output
68
 }
68
 }
69
 
69
 
70
+// LoadConfigFromMeta 从ConfigMeta集合加载配置到注册表
71
+func LoadConfigFromMeta(metaMap map[string]*core.ConfigMeta) error {
72
+	// 1. 转换元数据为配置数据
73
+	rawConfig := convertMetaToConfig(metaMap)
74
+
75
+	// 2. 使用现有的LoadConfigFromMap方法加载
76
+	LoadConfigFromMap(rawConfig)
77
+
78
+	return nil
79
+}
80
+
81
+// convertMetaToConfig 将元数据转换为配置数据
82
+func convertMetaToConfig(metaMap map[string]*core.ConfigMeta) map[string]interface{} {
83
+	rawConfig := make(map[string]interface{})
84
+
85
+	for configName, configMeta := range metaMap {
86
+		configData := make(map[string]interface{})
87
+
88
+		// 遍历每个字段,设置默认值
89
+		for fieldName, fieldMeta := range configMeta.Fields {
90
+			// 根据字段类型设置合理的默认值
91
+			defaultValue := getDefaultValueByType(fieldMeta.Type)
92
+			configData[fieldName] = defaultValue
93
+		}
94
+
95
+		rawConfig[configName] = configData
96
+	}
97
+
98
+	return rawConfig
99
+}
100
+
101
+// getDefaultValueByType 根据类型返回默认值
102
+func getDefaultValueByType(typeStr string) interface{} {
103
+	switch typeStr {
104
+	case "string":
105
+		return ""
106
+	case "int", "int8", "int16", "int32", "int64", "uint", "uint8", "uint16", "uint32", "uint64":
107
+		return 0
108
+	case "float32", "float64":
109
+		return 0.0
110
+	case "bool":
111
+		return false
112
+	case "[]string":
113
+		return []string{}
114
+	case "[]int":
115
+		return []int{}
116
+	case "map[string]string":
117
+		return make(map[string]string)
118
+	case "map[string]interface{}":
119
+		return make(map[string]interface{})
120
+	default:
121
+		// 如果是其他结构体或指针类型,返回nil
122
+		return nil
123
+	}
124
+}
125
+
70
 // findConfigFile 查找配置文件
126
 // findConfigFile 查找配置文件
71
 func findConfigFile() (string, error) {
127
 func findConfigFile() (string, error) {
72
 	exePath, _ := os.Executable()
128
 	exePath, _ := os.Executable()

+ 47
- 0
config/subconfigs/configure_config.go Ver arquivo

1
+package subconfigs
2
+
3
+import (
4
+	"fmt"
5
+
6
+	"git.x2erp.com/qdy/go-base/config/core"
7
+)
8
+
9
+// ConfigureConfig 配置中心配置
10
+type ConfigureConfig struct {
11
+	core.BaseConfig
12
+	Url   string `yaml:"url" desc:"配置中心地址"`
13
+	token string `yaml:"token" desc:"访问配置中心的token"`
14
+}
15
+
16
+func (c *ConfigureConfig) Description() string {
17
+	return "configure访问配置中心的配置"
18
+}
19
+
20
+func NewConfgigureConfig() *ConfigureConfig {
21
+	return &ConfigureConfig{}
22
+}
23
+
24
+func (c *ConfigureConfig) SetDefaults() {
25
+	c.Url = "http://localhost:8000"
26
+	c.token = "123"
27
+}
28
+
29
+func (c *ConfigureConfig) Load(data map[string]interface{}) error {
30
+	return c.LoadFromYAML(data, c)
31
+}
32
+
33
+func (c *ConfigureConfig) Validate() error {
34
+	if c.Url == "" {
35
+		return fmt.Errorf("configure center url must be positive")
36
+	}
37
+	return nil
38
+}
39
+
40
+func (c *ConfigureConfig) IsConfigured() bool {
41
+	return c.Url != ""
42
+}
43
+
44
+// 自动注册
45
+func init() {
46
+	core.Register("configure", &ConfigureConfig{})
47
+}

+ 11
- 4
config/subconfigs/service_config.go Ver arquivo

11
 // ServiceConfig 服务配置
11
 // ServiceConfig 服务配置
12
 type ServiceConfig struct {
12
 type ServiceConfig struct {
13
 	core.BaseConfig
13
 	core.BaseConfig
14
-	AppName      string `yaml:"app_name" desc:"当前应用名称"`
15
-	AppVersion   string `yaml:"app_version" desc:"当前应用版本"`
16
-	AppEnv       string `yaml:"app_env" desc:"环境参数:dev, test, prod"`
17
-	AppAuthToken string `yaml:"app_auth_token" desc:"静态认证使用的token"`
14
+	AppName    string `yaml:"app_name" desc:"当前应用名称"`
15
+	AppVersion string `yaml:"app_version" desc:"当前应用版本"`
16
+	AppEnv     string `yaml:"app_env" desc:"环境参数:dev, test, prod"`
17
+
18
+	Username  string `yaml:"username" desc:"Basic认证用户名称"`
19
+	Password  string `yaml:"password" desc:"Basic认证用户密码"`
20
+	SecretKey string `yaml:"secret_key" desc:"当前微服务解密token的密钥"`
18
 
21
 
19
 	Port         int    `yaml:"port" desc:"服务监听端口"`
22
 	Port         int    `yaml:"port" desc:"服务监听端口"`
20
 	ServiceName  string `yaml:"service_name" desc:"服务名称"`
23
 	ServiceName  string `yaml:"service_name" desc:"服务名称"`
35
 		c.AppEnv = "dev"
38
 		c.AppEnv = "dev"
36
 	}
39
 	}
37
 
40
 
41
+	if c.SecretKey == "" {
42
+		c.SecretKey = "qwudndgzvxdypdoqd1bhdcdd1qqwzxpoew"
43
+	}
44
+
38
 	if c.Port == 0 {
45
 	if c.Port == 0 {
39
 		c.Port = 8080
46
 		c.Port = 8080
40
 	}
47
 	}

+ 1
- 1
config/test_metadata_test.go Ver arquivo

19
 
19
 
20
 		for fieldName, fieldMeta := range configMeta.Fields {
20
 		for fieldName, fieldMeta := range configMeta.Fields {
21
 			fmt.Printf("  字段: %s, 类型: %s, YAML标签: %s, 描述: %s\n",
21
 			fmt.Printf("  字段: %s, 类型: %s, YAML标签: %s, 描述: %s\n",
22
-				fieldName, fieldMeta.Type, fieldMeta.YamlTag, fieldMeta.Desc)
22
+				fieldName, fieldMeta.Type, fieldMeta.YamlName, fieldMeta.Desc)
23
 		}
23
 		}
24
 	}
24
 	}
25
 }
25
 }

+ 11
- 0
ctx/request_context.go Ver arquivo

7
 
7
 
8
 // UserContext 用户上下文
8
 // UserContext 用户上下文
9
 type RequestContext struct {
9
 type RequestContext struct {
10
+	//StdCtx       context.Context // 新增:标准上下文
10
 	TraceID      string `json:"trace_id"`
11
 	TraceID      string `json:"trace_id"`
11
 	ServiceName  string `json:"service_name"`
12
 	ServiceName  string `json:"service_name"`
12
 	InstanceName string `json:"instance_name"`
13
 	InstanceName string `json:"instance_name"`
13
 	TenantID     string `json:"tenant_id"`
14
 	TenantID     string `json:"tenant_id"`
14
 	UserID       string `json:"user_id"`
15
 	UserID       string `json:"user_id"`
15
 	ProjectID    string `json:"project_id"`
16
 	ProjectID    string `json:"project_id"`
17
+	Username     string `json:"username"`
16
 }
18
 }
17
 
19
 
18
 // 内部key,不会和其他包冲突
20
 // 内部key,不会和其他包冲突
20
 
22
 
21
 var loggerKey = ctxKey{}
23
 var loggerKey = ctxKey{}
22
 
24
 
25
+// // GetStdContext 获取标准上下文(方便使用)
26
+// func (rc *RequestContext) GetStdContext() context.Context {
27
+// 	if rc.StdCtx == nil {
28
+// 		return context.Background()
29
+// 	}
30
+// 	return rc.StdCtx
31
+// }
32
+
23
 // Save RequestContext
33
 // Save RequestContext
24
 func SaveContext(r *http.Request, requestContext *RequestContext) *http.Request {
34
 func SaveContext(r *http.Request, requestContext *RequestContext) *http.Request {
25
 	ctx := context.WithValue(r.Context(), loggerKey, requestContext)
35
 	ctx := context.WithValue(r.Context(), loggerKey, requestContext)
50
 		ServiceName:  "test-ServiceName",
60
 		ServiceName:  "test-ServiceName",
51
 		InstanceName: "test-InstanceName",
61
 		InstanceName: "test-InstanceName",
52
 		UserID:       "test-UserID",
62
 		UserID:       "test-UserID",
63
+		Username:     "test-Username",
53
 	}
64
 	}
54
 }
65
 }

+ 0
- 115
middleware/auth_middleware.go Ver arquivo

1
-package middleware
2
-
3
-import (
4
-	"encoding/json"
5
-	"net/http"
6
-	"strings"
7
-	"time"
8
-
9
-	"git.x2erp.com/qdy/go-base/config"
10
-	"git.x2erp.com/qdy/go-base/ctx"
11
-	"git.x2erp.com/qdy/go-base/logger"
12
-	"git.x2erp.com/qdy/go-base/model/response"
13
-)
14
-
15
-// 全局配置(单例)
16
-var appConfig config.IConfig
17
-
18
-// ResponseFormat 响应格式
19
-type ResponseFormat int
20
-
21
-const (
22
-	FormatJSON ResponseFormat = iota
23
-	FormatCSV
24
-)
25
-
26
-// JWTAuthMiddlewareInit 初始化中间件配置
27
-func JWTAuthMiddlewareInit(config config.IConfig) {
28
-	appConfig = config
29
-}
30
-
31
-// JWT认证中间件(支持指定响应格式)
32
-func JWTAuthMiddleware(next http.Handler) http.Handler {
33
-	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
34
-		// 从Header获取Authorization
35
-		authHeader := r.Header.Get("Authorization")
36
-
37
-		// 检查Authorization头是否存在
38
-		if authHeader == "" {
39
-			sendAuthError(w, "Authorization header is required", getResponseFormat(r))
40
-			return
41
-		}
42
-
43
-		// 检查Bearer格式
44
-		if !strings.HasPrefix(authHeader, "Bearer ") {
45
-			sendAuthError(w, "Authorization header must start with 'Bearer '", getResponseFormat(r))
46
-			return
47
-		}
48
-
49
-		token := strings.TrimPrefix(authHeader, "Bearer ")
50
-
51
-		// 验证JWT令牌
52
-		if !isValidToken(token) {
53
-			sendAuthError(w, "Invalid token", getResponseFormat(r))
54
-			return
55
-		}
56
-
57
-		//保存上下文
58
-		// 创建LoggerContext(从token解析用户信息)
59
-		requestContext := &ctx.RequestContext{
60
-			ServiceName:  appConfig.GetServiceConfig().ServiceName,
61
-			InstanceName: appConfig.GetServiceConfig().InstanceName,
62
-			TraceID:      "trace_id-123", // 生成追踪ID
63
-			TenantID:     "tenant-123",   // 从token解析
64
-			UserID:       "user-456",     // 从token解析
65
-		}
66
-
67
-		if logger.IsDebug() {
68
-			logger.DebugC(requestContext, "Before save requestContext: %+v", requestContext)
69
-		}
70
-
71
-		// 保存到请求
72
-		r = ctx.SaveContext(r, requestContext)
73
-		// 继续处理请求
74
-		next.ServeHTTP(w, r)
75
-	})
76
-}
77
-
78
-// 根据请求路径判断响应格式
79
-func getResponseFormat(r *http.Request) ResponseFormat {
80
-	path := r.URL.Path
81
-
82
-	// 判断是否为CSV接口(根据你的路由规则)
83
-	if strings.Contains(path, "/csv") || strings.Contains(path, "/export") {
84
-		return FormatCSV
85
-	}
86
-
87
-	// 默认返回JSON格式
88
-	return FormatJSON
89
-}
90
-
91
-// 发送认证错误响应(根据格式)
92
-func sendAuthError(w http.ResponseWriter, message string, format ResponseFormat) {
93
-	w.WriteHeader(http.StatusUnauthorized)
94
-
95
-	switch format {
96
-	case FormatCSV:
97
-		w.Header().Set("Content-Type", "text/csv")
98
-		w.Write([]byte("error,message\n"))
99
-		w.Write([]byte("unauthorized," + message + "\n"))
100
-	default:
101
-		w.Header().Set("Content-Type", "application/json")
102
-		json.NewEncoder(w).Encode(&response.QueryResult[map[string]interface{}]{
103
-			Success: false,
104
-			Error:   message,
105
-			Time:    time.Now().Format(time.RFC3339),
106
-		})
107
-	}
108
-}
109
-
110
-// 验证令牌(需要根据实际项目实现)
111
-func isValidToken(token string) bool {
112
-	// TODO: 实现真正的JWT验证逻辑
113
-	// 暂时简化处理
114
-	return token != ""
115
-}

+ 5
- 0
webx/router/router_service.go Ver arquivo

1
 package router
1
 package router
2
 
2
 
3
 import (
3
 import (
4
+	"context"
4
 	"encoding/json"
5
 	"encoding/json"
5
 	"net/http"
6
 	"net/http"
6
 	"reflect"
7
 	"reflect"
287
 		return reflect.ValueOf(w)
288
 		return reflect.ValueOf(w)
288
 	case reflect.TypeOf((*http.Request)(nil)):
289
 	case reflect.TypeOf((*http.Request)(nil)):
289
 		return reflect.ValueOf(r)
290
 		return reflect.ValueOf(r)
291
+		// 新增:支持 context.Context
292
+	case reflect.TypeOf((*context.Context)(nil)).Elem():
293
+		return reflect.ValueOf(r.Context())
290
 	}
294
 	}
295
+
291
 	return reflect.Value{}
296
 	return reflect.Value{}
292
 }
297
 }
293
 
298
 

Carregando…
Cancelar
Salvar