package auth import ( "fmt" "os" "path/filepath" "strings" "sync" "gopkg.in/yaml.v3" ) // OAuthConfigYAML OAuth配置结构 (从YAML文件加载) type OAuthConfigYAML struct { Common CommonConfig `yaml:"common"` WeChat WeChatOAuthConfig `yaml:"wechat"` Google GoogleOAuthConfig `yaml:"google"` Facebook FacebookOAuthConfig `yaml:"facebook"` QQ QQOAuthConfig `yaml:"qq"` Weibo WeiboOAuthConfig `yaml:"weibo"` Twitter TwitterOAuthConfig `yaml:"twitter"` } // CommonConfig 通用配置 type CommonConfig struct { RedirectBaseURL string `yaml:"redirect_base_url"` CallbackPath string `yaml:"callback_path"` } // WeChatOAuthConfig 微信OAuth配置 type WeChatOAuthConfig struct { Enabled bool `yaml:"enabled"` AppID string `yaml:"app_id"` AppSecret string `yaml:"app_secret"` Scopes []string `yaml:"scopes"` AuthURL string `yaml:"auth_url"` TokenURL string `yaml:"token_url"` UserInfoURL string `yaml:"user_info_url"` MiniProgram MiniProgramConfig `yaml:"mini_program"` } // MiniProgramConfig 小程序配置 type MiniProgramConfig struct { Enabled bool `yaml:"enabled"` AppID string `yaml:"app_id"` AppSecret string `yaml:"app_secret"` } // GoogleOAuthConfig Google OAuth配置 type GoogleOAuthConfig struct { Enabled bool `yaml:"enabled"` ClientID string `yaml:"client_id"` ClientSecret string `yaml:"client_secret"` Scopes []string `yaml:"scopes"` AuthURL string `yaml:"auth_url"` TokenURL string `yaml:"token_url"` UserInfoURL string `yaml:"user_info_url"` JWTAuthURL string `yaml:"jwt_auth_url"` } // FacebookOAuthConfig Facebook OAuth配置 type FacebookOAuthConfig struct { Enabled bool `yaml:"enabled"` AppID string `yaml:"app_id"` AppSecret string `yaml:"app_secret"` Scopes []string `yaml:"scopes"` AuthURL string `yaml:"auth_url"` TokenURL string `yaml:"token_url"` UserInfoURL string `yaml:"user_info_url"` } // QQOAuthConfig QQ OAuth配置 type QQOAuthConfig struct { Enabled bool `yaml:"enabled"` AppID string `yaml:"app_id"` AppKey string `yaml:"app_key"` AppSecret string `yaml:"app_secret"` RedirectURI string `yaml:"redirect_uri"` Scopes []string `yaml:"scopes"` AuthURL string `yaml:"auth_url"` TokenURL string `yaml:"token_url"` OpenIDURL string `yaml:"openid_url"` UserInfoURL string `yaml:"user_info_url"` } // WeiboOAuthConfig 微博OAuth配置 type WeiboOAuthConfig struct { Enabled bool `yaml:"enabled"` AppKey string `yaml:"app_key"` AppSecret string `yaml:"app_secret"` RedirectURI string `yaml:"redirect_uri"` Scopes []string `yaml:"scopes"` AuthURL string `yaml:"auth_url"` TokenURL string `yaml:"token_url"` UserInfoURL string `yaml:"user_info_url"` } // TwitterOAuthConfig Twitter OAuth配置 type TwitterOAuthConfig struct { Enabled bool `yaml:"enabled"` ClientID string `yaml:"client_id"` ClientSecret string `yaml:"client_secret"` Scopes []string `yaml:"scopes"` AuthURL string `yaml:"auth_url"` TokenURL string `yaml:"token_url"` UserInfoURL string `yaml:"user_info_url"` } var ( oauthConfig *OAuthConfigYAML oauthConfigOnce sync.Once ) // LoadOAuthConfig 加载OAuth配置 func LoadOAuthConfig(configPath string) (*OAuthConfigYAML, error) { var err error oauthConfigOnce.Do(func() { // 如果未指定配置文件,尝试默认路径 if configPath == "" { configPath = filepath.Join("configs", "oauth_config.yaml") } // 如果配置文件不存在,尝试从环境变量加载 if _, statErr := os.Stat(configPath); os.IsNotExist(statErr) { oauthConfig = loadFromEnv() return } // 从文件加载配置 data, readErr := os.ReadFile(configPath) if readErr != nil { oauthConfig = loadFromEnv() err = fmt.Errorf("failed to read oauth config file: %w", readErr) return } oauthConfig = &OAuthConfigYAML{} if unmarshalErr := yaml.Unmarshal(data, oauthConfig); unmarshalErr != nil { oauthConfig = loadFromEnv() err = fmt.Errorf("failed to parse oauth config file: %w", unmarshalErr) return } }) return oauthConfig, err } // loadFromEnv 从环境变量加载配置 func loadFromEnv() *OAuthConfigYAML { return &OAuthConfigYAML{ Common: CommonConfig{ RedirectBaseURL: getEnv("OAUTH_REDIRECT_BASE_URL", "http://localhost:8080"), CallbackPath: getEnv("OAUTH_CALLBACK_PATH", "/api/v1/auth/oauth/callback"), }, WeChat: WeChatOAuthConfig{ Enabled: getEnvBool("WECHAT_OAUTH_ENABLED", false), AppID: getEnv("WECHAT_APP_ID", ""), AppSecret: getEnv("WECHAT_APP_SECRET", ""), AuthURL: "https://open.weixin.qq.com/connect/qrconnect", TokenURL: "https://api.weixin.qq.com/sns/oauth2/access_token", UserInfoURL: "https://api.weixin.qq.com/sns/userinfo", }, Google: GoogleOAuthConfig{ Enabled: getEnvBool("GOOGLE_OAUTH_ENABLED", false), ClientID: getEnv("GOOGLE_CLIENT_ID", ""), ClientSecret: getEnv("GOOGLE_CLIENT_SECRET", ""), AuthURL: "https://accounts.google.com/o/oauth2/v2/auth", TokenURL: "https://oauth2.googleapis.com/token", UserInfoURL: "https://www.googleapis.com/oauth2/v2/userinfo", JWTAuthURL: "https://oauth2.googleapis.com/tokeninfo", }, Facebook: FacebookOAuthConfig{ Enabled: getEnvBool("FACEBOOK_OAUTH_ENABLED", false), AppID: getEnv("FACEBOOK_APP_ID", ""), AppSecret: getEnv("FACEBOOK_APP_SECRET", ""), AuthURL: "https://www.facebook.com/v18.0/dialog/oauth", TokenURL: "https://graph.facebook.com/v18.0/oauth/access_token", UserInfoURL: "https://graph.facebook.com/v18.0/me?fields=id,name,email,picture", }, QQ: QQOAuthConfig{ Enabled: getEnvBool("QQ_OAUTH_ENABLED", false), AppID: getEnv("QQ_APP_ID", ""), AppKey: getEnv("QQ_APP_KEY", ""), AppSecret: getEnv("QQ_APP_SECRET", ""), RedirectURI: getEnv("QQ_REDIRECT_URI", ""), AuthURL: "https://graph.qq.com/oauth2.0/authorize", TokenURL: "https://graph.qq.com/oauth2.0/token", OpenIDURL: "https://graph.qq.com/oauth2.0/me", UserInfoURL: "https://graph.qq.com/user/get_user_info", }, Weibo: WeiboOAuthConfig{ Enabled: getEnvBool("WEIBO_OAUTH_ENABLED", false), AppKey: getEnv("WEIBO_APP_KEY", ""), AppSecret: getEnv("WEIBO_APP_SECRET", ""), RedirectURI: getEnv("WEIBO_REDIRECT_URI", ""), AuthURL: "https://api.weibo.com/oauth2/authorize", TokenURL: "https://api.weibo.com/oauth2/access_token", UserInfoURL: "https://api.weibo.com/2/users/show.json", }, Twitter: TwitterOAuthConfig{ Enabled: getEnvBool("TWITTER_OAUTH_ENABLED", false), ClientID: getEnv("TWITTER_CLIENT_ID", ""), ClientSecret: getEnv("TWITTER_CLIENT_SECRET", ""), AuthURL: "https://twitter.com/i/oauth2/authorize", TokenURL: "https://api.twitter.com/2/oauth2/token", UserInfoURL: "https://api.twitter.com/2/users/me", }, } } // GetOAuthConfig 获取OAuth配置 func GetOAuthConfig() *OAuthConfigYAML { if oauthConfig == nil { _, _ = LoadOAuthConfig("") } return oauthConfig } // getEnv 获取环境变量 func getEnv(key, defaultValue string) string { if value := os.Getenv(key); value != "" { return value } return defaultValue } // getEnvBool 获取布尔型环境变量 func getEnvBool(key string, defaultValue bool) bool { if value := os.Getenv(key); value != "" { return strings.ToLower(value) == "true" || value == "1" } return defaultValue }