http.listenandservetls是生产环境唯一安全的https启动方式,必须提供pem格式完整证书链和未加密私钥,禁用insecureskipverify,并配置tls最低版本与强密码套件;明文http.listenandserve永远不安全且无法支持http/2。

http.ListenAndServeTLS 是生产环境唯一可接受的 HTTP 服务启动方式,明文 http.ListenAndServe 必须禁用。
防止命令注入:永远不用 exec.Command 拼接字符串
- 错误写法:
exec.Command("sh", "-c", "ls "+userInput)—— shell 解释器会执行任意代码 - 正确写法:
exec.Command("ls", "-l", userInput)—— 参数被严格隔离,不经过 shell - 关键点:只要参数来自用户输入,就必须拆成独立
[]string元素传入,哪怕只有一个参数也要显式写出 - 容易踩的坑:用
fmt.Sprintf构造命令字符串、对路径未做filepath.Clean校验、忽略os/exec的StdinPipe泄露风险
SQL 注入防护:禁止字符串拼接,强制使用参数化查询
-
db.Query("SELECT * FROM users WHERE id = " + userID)是高危写法,直接导致注入 - 必须用占位符:
db.Query("SELECT <em> FROM users WHERE id = ?", userID)</em>或db.Query("SELECT FROM users WHERE id = $1", userID)(PostgreSQL) - 注意 driver 差异:MySQL 用
?,PostgreSQL 用$1,SQLite 两者都支持但风格需统一 - 更安全的做法是预编译:
stmt, _ := db.Prepare("UPDATE accounts SET balance = ? WHERE id = ?"),复用语句并避免语法解析开销 - 切忌在 WHERE 条件中拼接表名或字段名——这些无法参数化,必须走白名单校验
JSON 反序列化:拒绝 interface{},定义结构体并控制数字类型
-
json.Unmarshal(data, &v)中v是interface{}?立刻重构 - 后果包括:超深嵌套触发栈溢出、float64 精度丢失(如 ID 被转成
123.0)、类型断言爆炸式增长 - 正确姿势:
type Req struct { ID json.Number <code>json:"id"},再调用ID.Int64()或ID.Float64()显式转换 - 若字段可选,用指针:
Name *string <code>json:"name",避免零值覆盖业务逻辑 - 解码前建议先
strings.TrimSpace,防止 BOM 或空格导致invalid character错误
Base64 编解码:选错编码器会导致静默失败或解码崩溃
- 往 URL、JWT、Cookie 里塞数据?必须用
base64.URLEncoding,不是base64.StdEncoding -
base64.StdEncoding.EncodeToString([]byte("hello"))输出aGVsbG8=,但+和/在 URL 中会被篡改或丢弃 - 解码前不
strings.TrimSpace?常见报错:illegal base64 data at input byte 0 - 传
nil切片给EncodeToString?返回空字符串"",不是 panic,极易被当成“成功”继续往下走 - 高频场景(如日志脱敏)建议预分配:
dst := make([]byte, base64.URLEncoding.EncodedLen(len(src))),避免反复 alloc
真正难的不是记住哪条规则,而是每次拿到外部输入时——无论它来自 query、header、body 还是 env——都本能地停顿半秒,问自己:这个值有没有可能被构造为恶意 payload?有没有可能绕过当前校验?有没有可能在下游某个环节被 reinterpret?
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











