feat: 引入依赖注入模式
- 创建Repository接口定义(UserRepository、ProfileRepository、TextureRepository等) - 创建Repository接口实现 - 创建依赖注入容器(container.Container) - 改造Handler层使用依赖注入(AuthHandler、UserHandler、TextureHandler) - 创建新的路由注册方式(RegisterRoutesWithDI) - 提供main.go示例文件展示如何使用依赖注入 同时包含之前的安全修复: - CORS配置安全加固 - 头像URL验证安全修复 - JWT algorithm confusion漏洞修复 - Recovery中间件增强 - 敏感错误信息泄露修复 - 类型断言安全修复
This commit is contained in:
@@ -4,10 +4,12 @@ import (
|
||||
"carrotskin/internal/model"
|
||||
"carrotskin/internal/repository"
|
||||
"carrotskin/pkg/auth"
|
||||
"carrotskin/pkg/config"
|
||||
"carrotskin/pkg/redis"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
@@ -286,24 +288,69 @@ func ValidateAvatarURL(avatarURL string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 允许的域名列表
|
||||
allowedDomains := []string{
|
||||
"rustfs.example.com",
|
||||
"localhost",
|
||||
"127.0.0.1",
|
||||
}
|
||||
|
||||
for _, domain := range allowedDomains {
|
||||
if strings.Contains(avatarURL, domain) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// 允许相对路径
|
||||
if strings.HasPrefix(avatarURL, "/") {
|
||||
return nil
|
||||
}
|
||||
|
||||
return errors.New("头像URL不在允许的域名列表中")
|
||||
return ValidateURLDomain(avatarURL)
|
||||
}
|
||||
|
||||
// ValidateURLDomain 验证URL的域名是否在允许列表中
|
||||
func ValidateURLDomain(rawURL string) error {
|
||||
// 解析URL
|
||||
parsedURL, err := url.Parse(rawURL)
|
||||
if err != nil {
|
||||
return errors.New("无效的URL格式")
|
||||
}
|
||||
|
||||
// 必须是HTTP或HTTPS协议
|
||||
if parsedURL.Scheme != "http" && parsedURL.Scheme != "https" {
|
||||
return errors.New("URL必须使用http或https协议")
|
||||
}
|
||||
|
||||
// 获取主机名(不包含端口)
|
||||
host := parsedURL.Hostname()
|
||||
if host == "" {
|
||||
return errors.New("URL缺少主机名")
|
||||
}
|
||||
|
||||
// 从配置获取允许的域名列表
|
||||
cfg, err := config.GetConfig()
|
||||
if err != nil {
|
||||
// 如果配置获取失败,使用默认的安全域名列表
|
||||
allowedDomains := []string{"localhost", "127.0.0.1"}
|
||||
return checkDomainAllowed(host, allowedDomains)
|
||||
}
|
||||
|
||||
return checkDomainAllowed(host, cfg.Security.AllowedDomains)
|
||||
}
|
||||
|
||||
// checkDomainAllowed 检查域名是否在允许列表中
|
||||
func checkDomainAllowed(host string, allowedDomains []string) error {
|
||||
host = strings.ToLower(host)
|
||||
|
||||
for _, allowed := range allowedDomains {
|
||||
allowed = strings.ToLower(strings.TrimSpace(allowed))
|
||||
if allowed == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
// 精确匹配
|
||||
if host == allowed {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 支持通配符子域名匹配 (如 *.example.com)
|
||||
if strings.HasPrefix(allowed, "*.") {
|
||||
suffix := allowed[1:] // 移除 "*",保留 ".example.com"
|
||||
if strings.HasSuffix(host, suffix) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return errors.New("URL域名不在允许的列表中")
|
||||
}
|
||||
|
||||
// GetUserByEmail 根据邮箱获取用户
|
||||
|
||||
Reference in New Issue
Block a user