From 5cf09020fb39d2f7c5dbdfb29e0e6c06ca50a464 Mon Sep 17 00:00:00 2001 From: cosmo Date: Thu, 23 Nov 2023 17:11:11 +0800 Subject: [PATCH 1/2] update --- config/config.go | 13 ++++++++++++ handlers/send_group_msg.go | 1 + server/wsserver.go | 21 ++++++++++--------- template/config_template.go | 1 + template/config_template.yml | 3 ++- url/shorturl.go | 40 ++++++++++++++++++++++++++++++++---- 6 files changed, 64 insertions(+), 15 deletions(-) diff --git a/config/config.go b/config/config.go index 3d230dd4..307d8675 100644 --- a/config/config.go +++ b/config/config.go @@ -80,6 +80,7 @@ type Settings struct { SendError bool `yaml:"send_error"` AddAtGroup bool `yaml:"add_at_group"` UrlPicTransfer bool `yaml:"url_pic_transfer"` + LotusPassword string `yaml:"lotus_password"` } // LoadConfig 从文件中加载配置并初始化单例配置 @@ -950,3 +951,15 @@ func GetUrlPicTransfer() bool { } return instance.Settings.UrlPicTransfer } + +// 获取GetLotusPassword的值 +func GetLotusPassword() string { + mu.Lock() + defer mu.Unlock() + + if instance == nil { + mylog.Println("Warning: instance is nil when trying to GetLotusPassword value.") + return "" + } + return instance.Settings.LotusPassword +} diff --git a/handlers/send_group_msg.go b/handlers/send_group_msg.go index d8e066d7..ec5c290a 100644 --- a/handlers/send_group_msg.go +++ b/handlers/send_group_msg.go @@ -133,6 +133,7 @@ func handleSendGroupMsg(client callapi.Client, api openapi.OpenAPI, apiv2 openap richMediaMessage, ok := groupReply.(*dto.RichMediaMessage) if !ok { mylog.Printf("Error: Expected RichMediaMessage type for key ") + return } // 上传图片并获取FileInfo fileInfo, err := uploadMedia(context.TODO(), message.Params.GroupID.(string), richMediaMessage, apiv2) diff --git a/server/wsserver.go b/server/wsserver.go index e1540e41..fb223d22 100644 --- a/server/wsserver.go +++ b/server/wsserver.go @@ -59,17 +59,18 @@ func wsHandler(api openapi.OpenAPI, apiV2 openapi.OpenAPI, p *Processor.Processo token = c.Query("access_token") } - if token == "" { - mylog.Printf("Connection failed due to missing token. Headers: %v", c.Request.Header) - c.JSON(http.StatusUnauthorized, gin.H{"error": "Missing token"}) - return - } - - // 使用GetWsServerToken()来获取有效的token + // 获取配置中的有效 token validToken := config.GetWsServerToken() - if token != validToken { - mylog.Printf("Connection failed due to incorrect token. Headers: %v, Provided token: %s", c.Request.Header, tokenFromHeader) - c.JSON(http.StatusForbidden, gin.H{"error": "Incorrect token"}) + + // 如果配置的 token 不为空,但提供的 token 为空或不匹配 + if validToken != "" && (token == "" || token != validToken) { + if token == "" { + mylog.Printf("Connection failed due to missing token. Headers: %v", c.Request.Header) + c.JSON(http.StatusUnauthorized, gin.H{"error": "Missing token"}) + } else { + mylog.Printf("Connection failed due to incorrect token. Headers: %v, Provided token: %s", c.Request.Header, token) + c.JSON(http.StatusForbidden, gin.H{"error": "Incorrect token"}) + } return } diff --git a/template/config_template.go b/template/config_template.go index 0994ebd8..d3a642f2 100644 --- a/template/config_template.go +++ b/template/config_template.go @@ -37,6 +37,7 @@ settings: lotus: false # lotus特性默认为false,当为true时,将会连接到另一个lotus为false的gensokyo。 # 使用它提供的图床和idmaps服务(场景:同一个机器人在不同服务器运行,或内网需要发送base64图)。 # 如果需要发送base64图片,需要设置正确的公网server_dir和开放对应的port + lotus_password : "" # lotus鉴权 设置后,从gsk需要保持相同密码来访问主gsk #增强配置项 diff --git a/template/config_template.yml b/template/config_template.yml index 221ebb51..bc587c7f 100644 --- a/template/config_template.yml +++ b/template/config_template.yml @@ -71,4 +71,5 @@ settings: No_White_Response : "" #默认不兜底,强烈建议设置一个友善的兜底回复,告知审核机器人已无隐藏指令,如:你输入的指令不对哦,@机器人来获取可用指令 send_error : true #将报错用文本发出,避免机器人被审核报无响应 add_at_group : false #自动在群聊指令前加上at,某些机器人写法特别,必须有at才反应时,请打开,默认请关闭(如果需要at,不需要at指令混杂,请优化代码适配群场景,群场景目前没有at概念 - url_pic_transfer : false #把图片url(任意来源图链)变成你备案的白名单url 需要较高上下行+ssl+自备案域名+设置白名单域名(暂时不需要) \ No newline at end of file + url_pic_transfer : false #把图片url(任意来源图链)变成你备案的白名单url 需要较高上下行+ssl+自备案域名+设置白名单域名(暂时不需要) + lotus_password : "" # lotus鉴权 设置后,从gsk需要保持相同密码来访问主gsk \ No newline at end of file diff --git a/url/shorturl.go b/url/shorturl.go index 29accdb4..137866ae 100644 --- a/url/shorturl.go +++ b/url/shorturl.go @@ -1,6 +1,7 @@ package url import ( + "crypto/md5" "crypto/sha256" "encoding/base64" "encoding/hex" @@ -72,6 +73,7 @@ func isValidURL(toTest string) bool { return false } if parsedURL.Scheme != "http" && parsedURL.Scheme != "https" { + mylog.Printf("链接%v缺少协议头,请添加https://或http://", toTest) return false } @@ -131,10 +133,19 @@ func GenerateShortURL(longURL string) string { if config.GetLotusValue() { serverDir := config.GetServer_dir() requestURL := fmt.Sprintf("%s://%s:%s/url", protocol, serverDir, portValue) // 改变变量名以避免冲突 - // 使用 url.Values 构造请求数据 formData := url.Values{} - formData.Set("url", (longURL)) + formData.Set("url", longURL) + // 获取密码 + password := config.GetLotusPassword() + // 如果密码不为空,则计算 MD5 值并添加 token + if password != "" { + hasher := md5.New() + hasher.Write([]byte(password)) + token := hex.EncodeToString(hasher.Sum(nil)) + // 添加 token + formData.Set("token", token) + } // 创建请求 req, err := http.NewRequest("POST", requestURL, strings.NewReader(formData.Encode())) @@ -305,10 +316,13 @@ func isMalicious(decoded string) bool { // 短链接服务handler func CreateShortURLHandler(c *gin.Context) { rawURL := c.PostForm("url") + token := c.PostForm("token") // 接收 token 参数 + longURL := decodeBase64IfNeeded(rawURL) - if longURL == "" || isMalicious(longURL) || !isValidURL(longURL) { - c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid URL"}) + // 检查 URL 是否有效,以及在密码不为空时检查 token + if longURL == "" || isMalicious(longURL) || !isValidURL(longURL) || (config.GetLotusPassword() != "" && !isValidToken(token)) { + c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid URL or token"}) return } @@ -322,6 +336,24 @@ func CreateShortURLHandler(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"shortURL": baseUrl + "/url/" + shortURL}) } +// isValidToken 检查 token 是否有效 +func isValidToken(token string) bool { + // 从配置中获取密码 + password := config.GetLotusPassword() + + // 如果密码为空,直接返回 true + if password == "" { + return true + } + + // 计算 MD5 + hasher := md5.New() + hasher.Write([]byte(password)) + md5Password := hex.EncodeToString(hasher.Sum(nil)) + + return md5Password == token +} + // 短链接baseurl func GetBaseURL() string { serverDir := config.GetServer_dir() From 742a4f8bb823a438313d59d5f113800b1b80d883 Mon Sep 17 00:00:00 2001 From: cosmo Date: Thu, 23 Nov 2023 21:03:18 +0800 Subject: [PATCH 2/2] update --- config/config.go | 13 +++++++++++++ main.go | 5 +++-- template/config_template.go | 6 +++--- template/config_template.yml | 8 ++++---- 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/config/config.go b/config/config.go index 307d8675..e2f7e369 100644 --- a/config/config.go +++ b/config/config.go @@ -81,6 +81,7 @@ type Settings struct { AddAtGroup bool `yaml:"add_at_group"` UrlPicTransfer bool `yaml:"url_pic_transfer"` LotusPassword string `yaml:"lotus_password"` + WsServerPath string `yaml:"ws_server_path"` } // LoadConfig 从文件中加载配置并初始化单例配置 @@ -963,3 +964,15 @@ func GetLotusPassword() string { } return instance.Settings.LotusPassword } + +// 获取GetWsServerPath的值 +func GetWsServerPath() string { + mu.Lock() + defer mu.Unlock() + + if instance == nil { + mylog.Println("Warning: instance is nil when trying to GetWsServerPath value.") + return "" + } + return instance.Settings.WsServerPath +} diff --git a/main.go b/main.go index 15771aa4..c3586724 100644 --- a/main.go +++ b/main.go @@ -307,8 +307,9 @@ func main() { //正向ws if conf.Settings.AppID != 12345 { if conf.Settings.EnableWsServer { - r.GET("/ws", server.WsHandlerWithDependencies(api, apiV2, p)) - log.Println("正向ws启动成功,监听0.0.0.0:" + serverPort + " 请注意设置ws_server_token,并对外放通端口...") + wspath := config.GetWsServerPath() + r.GET("/"+wspath, server.WsHandlerWithDependencies(api, apiV2, p)) + log.Println("正向ws启动成功,监听0.0.0.0:" + serverPort + "/" + wspath + "请注意设置ws_server_token,并对外放通端口...") } } r.POST("/url", url.CreateShortURLHandler) diff --git a/template/config_template.go b/template/config_template.go index d3a642f2..18ced242 100644 --- a/template/config_template.go +++ b/template/config_template.go @@ -48,9 +48,9 @@ settings: record_bitRate : 24000 #语音文件的比特率 默认25000 代表 25 kbps 最高无限 请根据带宽 您发送的实际码率调整 #正向ws设置 - - enable_ws_server: true #是否启用正向ws服务器 监听server_dir:port/ws - ws_server_token : "12345" #正向ws的token 不启动正向ws可忽略 + ws_server_path : "ws" #默认监听0.0.0.0:port/ws_server_path 若有安全需求,可不放通port到公网,或设置ws_server_token 若想监听/ 可改为"" + enable_ws_server: true #是否启用正向ws服务器 监听server_dir:port/ws_server_path + ws_server_token : "12345" #正向ws的token 不启动正向ws可忽略 可为空 #SSL配置类 机器人发送URL设置 diff --git a/template/config_template.yml b/template/config_template.yml index bc587c7f..b6c93798 100644 --- a/template/config_template.yml +++ b/template/config_template.yml @@ -30,9 +30,8 @@ settings: # 使用它提供的图床和idmaps服务(场景:同一个机器人在不同服务器运行,或内网需要发送base64图)。 # 如果需要发送base64图片,需要设置正确的公网server_dir和开放对应的port master_id : ["1","2"] #群场景尚未开放获取管理员和列表能力,手动从日志中获取需要设置为管理,的user_id并填入(适用插件有权限判断场景) - enable_ws_server: true #是否启用正向ws服务器 监听server_dir:port/ws - ws_server_token : "12345" #正向ws的token 不启动正向ws可忽略 - ws_server_token : "12345" #正向ws的token 不启动正向ws可忽略 + enable_ws_server: true #是否启用正向ws服务器 监听server_dir:port/ws_server_path + ws_server_token : "12345" #正向ws的token 不启动正向ws可忽略 可为"" identify_file: true #自动生成域名校验文件,在q.qq.com配置信息URL,在server_dir填入自己已备案域名,正确解析到机器人所在服务器ip地址,机器人即可发送链接 crt: "" #证书路径 从你的域名服务商或云服务商申请签发SSL证书(qq要求SSL) key: "" #密钥路径 Apache(crt文件、key文件)示例: "C:\\123.key" \需要双写成\\ @@ -72,4 +71,5 @@ settings: send_error : true #将报错用文本发出,避免机器人被审核报无响应 add_at_group : false #自动在群聊指令前加上at,某些机器人写法特别,必须有at才反应时,请打开,默认请关闭(如果需要at,不需要at指令混杂,请优化代码适配群场景,群场景目前没有at概念 url_pic_transfer : false #把图片url(任意来源图链)变成你备案的白名单url 需要较高上下行+ssl+自备案域名+设置白名单域名(暂时不需要) - lotus_password : "" # lotus鉴权 设置后,从gsk需要保持相同密码来访问主gsk \ No newline at end of file + lotus_password : "" # lotus鉴权 设置后,从gsk需要保持相同密码来访问主gsk + ws_server_path : "ws" #默认监听0.0.0.0:port/ws_server_path 若有安全需求,可不放通port到公网,或设置ws_server_token 若想监听/ 可改为"" \ No newline at end of file