安全编码指南

输入验证

// 白名单验证(优于黑名单) func validateEmail(email string) bool { pattern := `^[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}$` matched, _ := regexp.MatchString(pattern, email) return matched && len(email) <= 254 } // 数值范围验证 func validateAge(age int) error { if age < 0 || age > 150 { return errors.New("年龄必须在 0 到 150 之间") } return nil } // 文件上传验证 allowedTypes := map[string]bool{ "image/jpeg": true, "image/png": true, "image/webp": true, } // 始终检查魔术字节,而非仅检查扩展名或 Content-Type

密码哈希

// Go - bcrypt(推荐) import "golang.org/x/crypto/bcrypt" func hashPassword(password string) (string, error) { bytes, err := bcrypt.GenerateFromPassword([]byte(password), 14) return string(bytes), err } func checkPassword(password, hash string) bool { err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password)) return err == nil } // 绝不使用: // md5.Sum([]byte(password)) // sha256.Sum256([]byte(password)) // 快速哈希,不适合密码

密钥管理

// 绝不硬编码密钥 // 不好的做法: apiKey := "sk-live-abc123def456..." // 好的做法:环境变量 apiKey := os.Getenv("OPENAI_API_KEY") if apiKey == "" { log.Fatal("OPENAI_API_KEY 未设置") } // 更好的做法:密钥管理服务 // AWS Secrets Manager、HashiCorp Vault、GCP Secret Manager // .gitignore 必须包含: // .env // *.pem // *.key // credentials.json

HTTP 安全响应头

// Go/Gin 中间件 func SecurityHeaders() gin.HandlerFunc { return func(c *gin.Context) { c.Header("X-Content-Type-Options", "nosniff") c.Header("X-Frame-Options", "DENY") c.Header("X-XSS-Protection", "1; mode=block") c.Header("Referrer-Policy", "strict-origin-when-cross-origin") c.Header("Strict-Transport-Security", "max-age=31536000; includeSubDomains") c.Header("Content-Security-Policy", "default-src 'self'; script-src 'self'") c.Next() } }

安全编码原则

原则说明
纵深防御多层安全控制;单点失效不会导致系统沦陷
最小权限每个组件只授予其所需的最小权限
安全失败发生错误时拒绝访问而非放行
关注点分离隔离认证、数据、业务逻辑
不信任输入验证和净化所有外部数据
保持简单复杂代码漏洞更多;简洁即安全