Golang中如何判断未知来源字符串是否经过URL编码
Go语言判断字符串是否为URL编码并安全解码
核心判断思路
URL编码(百分号编码)的判定不能仅靠字符串中是否存在%字符,也不能仅靠解码不报错作为依据——普通字符串也可能包含%,且无转义字符的普通字符串传入URL解码函数也不会报错、会直接返回原串。
正确判定需要同时满足两个条件:
- 字符串中存在合法的URL转义序列:即
%后紧跟2位十六进制字符(取值范围为0-9/a-f/A-F) - 对字符串执行URL解码操作无报错,且解码结果与原字符串不相等
修正补全后的代码
package main import ( "fmt" "log" "net/url" ) // decode 执行URL Query解码 func decode(str1 string) string { resl, err := url.QueryUnescape(str1) if err != nil { log.Printf("URL decode error: %v", err) return str1 } return resl } // ifUrlEncoded 判断字符串是否为URL编码格式 func ifUrlEncoded(s string) bool { hasValidEscape := false length := len(s) for i := 0; i < length; i++ { // 找到%字符,校验后面是否跟2位合法十六进制字符 if s[i] == '%' { if i+2 >= length { // %后面不足2位,不是合法转义 continue } c1, c2 := s[i+1], s[i+2] isHex := func(c byte) bool { return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') } if isHex(c1) && isHex(c2) { hasValidEscape = true break } } } if !hasValidEscape { return false } // 二次验证:解码无报错且结果和原串不同 decoded, err := url.QueryUnescape(s) if err != nil { return false } return decoded != s } func main() { testStrs := []string{ "elementINPUT61599119%5B%5D", // 合法URL编码 "普通测试字符串", // 普通中文串 "test%GGstring", // 带非法%序列,不算编码 "test123", // 普通英文串 "100%测试", // 带%但无合法转义 } for _, str := range testStrs { if ifUrlEncoded(str) { fmt.Printf("原串: %s -> 解码结果: %s\n", str, decode(str)) } else { fmt.Printf("原串: %s -> 普通字符串,无需解码: %s\n", str, str) } } }
逻辑说明
- 先做轻量遍历校验,避免对完全没有转义特征的字符串做不必要的解码操作,性能更好
- 过滤掉
%后面字符不符合十六进制规则的场景,避免把普通带%的字符串误判为URL编码 - 解码后对比原串,避免把本身不需要解码、解码后和原串完全一致的字符串误判
内容的提问来源于stack exchange,提问作者Mesc
相关产品推荐
相关产品推荐

