Go语言net/url库解析含#号密码的数据库连接串失败如何解决?
Go net/url库解析含特殊字符的PostgreSQL连接串解决方案
问题根因
你的推测完全符合URL规范定义:# 是URL的片段标识符起始标记,解析时会直接截断#之前的所有路径/认证信息逻辑,所以密码中明文出现#时会导致用户认证段识别失败。
方案1:构造连接串时提前编码密码(推荐)
如果是你自己拼接生成数据库连接串,直接用url.QueryEscape()对密码做URL编码即可,所有URL保留字符(#、@、/、:、?等)都会被自动转义,无需单独处理特殊字符。
代码示例:
package main import ( "fmt" "net/url" ) func main() { username := "postgres" rawPassword := "password#" // 对密码做URL编码 escapedPassword := url.QueryEscape(rawPassword) // 拼接连接串 connString := fmt.Sprintf("postgresql://%s:%s@192.168.1.10:5432/postgres", username, escapedPassword) parsedUrl, err := url.Parse(connString) if err != nil { fmt.Println(err) return } fmt.Println("=") fmt.Println(parsedUrl.User) // 要获取明文密码可以调用Password()方法 password, _ := parsedUrl.User.Password() fmt.Println("解析出的明文密码:", password) fmt.Println("=") }
执行结果:
$ go run main.go = postgres:password# 解析出的明文密码: password# =
方案2:预处理已生成的明文连接串
如果拿到的连接串已经是明文带特殊字符、无法修改生成逻辑的,可以先提取用户认证段做转义后再拼接解析:
代码示例:
package main import ( "fmt" "net/url" "strings" ) func escapeUserInfoInConnStr(connStr string) string { // 拆分scheme和剩余部分 schemeSplit := strings.SplitN(connStr, "://", 2) if len(schemeSplit) != 2 { return connStr } scheme := schemeSplit[0] rest := schemeSplit[1] // 找@的位置,拆分用户信息和主机部分 atIndex := strings.Index(rest, "@") if atIndex == -1 { return connStr } userInfo := rest[:atIndex] hostPart := rest[atIndex:] // 拆分用户名和密码分别转义再拼接 userPassSplit := strings.SplitN(userInfo, ":", 2) if len(userPassSplit) == 2 { user := userPassSplit[0] pass := userPassSplit[1] escapedUser := url.QueryEscape(user) escapedPass := url.QueryEscape(pass) userInfo = fmt.Sprintf("%s:%s", escapedUser, escapedPass) } else { userInfo = url.QueryEscape(userInfo) } return fmt.Sprintf("%s://%s%s", scheme, userInfo, hostPart) } func main() { connString := "postgresql://postgres:password#@192.168.1.10:5432/postgres" // 先预处理连接串 processedConnStr := escapeUserInfoInConnStr(connString) parsedUrl, err := url.Parse(processedConnStr) if err != nil { fmt.Println(err) return } fmt.Println("=") fmt.Println(parsedUrl.User) fmt.Println("=") }
执行结果与方案1一致,可正常解析出用户凭证。
内容的提问来源于stack exchange,提问作者atline
相关产品推荐
相关产品推荐

