安全实践:输入校验、输出转义、CSRF/点击劫持概念与基本防护

Web 安全三板斧:不信任输入、正确编码输出、为浏览器策略兜底。本章给出 Go/Gin 侧可落地的基础实践;更完整的基线以 OWASP 与各库官方文档为准。

1. 输入校验:binding 标签

Gin 内置基于 go-playground/validator 的绑定校验,结构体标签写规则,ShouldBind* 返回错误即参数不合法:

type CreateUserReq struct {
    Email string `json:"email" binding:"required,email"`
    Age   int    `json:"age" binding:"required,min=0,max=150"`
    Role  string `json:"role" binding:"omitempty,oneof=user admin"`
}

var in CreateUserReq
if err := c.ShouldBindJSON(&in); err != nil {
    c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
    return
}

常用标签:requiredmin/maxlenemailoneofomitempty。跨字段业务规则(如结束时间晚于开始时间)再到 service 层校验。

2. 输出转义

  • HTML 输出交给 html/template{{ .X }} 会被自动转义;
  • 除非完全可信,别用 template.HTMLtemplate.JS 关闭转义;
  • JSON 输出由 encoding/json 负责转义,直接 c.JSON 即可。

3. 密码存储:bcrypt

密码绝不能明文或裸哈希存储,用 golang.org/x/crypto/bcrypt 加盐哈希:

hash, err := bcrypt.GenerateFromPassword([]byte(pwd), bcrypt.DefaultCost)
// 登录校验:
if bcrypt.CompareHashAndPassword(hash, []byte(pwd)) != nil {
    return errors.New("密码错误")
}

4. CSRF 与点击劫持

概念先分清(以 OWASP 说明为准):

  • CSRF:攻击者借浏览器里已登录的 Cookie,诱导用户向目标站发跨站请求。缓解:关键写操作校验 CSRF Token;Cookie 设 SameSite;纯 API 用 Header 里的 Token 认证(而非 Cookie)基本免疫。
  • 点击劫持:攻击者用透明 iframe 覆盖诱饵界面骗点击。缓解:响应头 X-Frame-Options: DENY 或 CSP 的 frame-ancestors
r.Use(func(c *gin.Context) {
    c.Header("X-Frame-Options", "DENY")
    c.Header("X-Content-Type-Options", "nosniff")
    c.Header("Referrer-Policy", "no-referrer")
    c.Next()
})

5. 其他基础项

  • 限制请求体大小:上传/大提交接口用 http.MaxBytesReaderr.MaxMultipartMemory
  • 错误信息不外泄内部细节(堆栈、DSN),统一错误体;
  • 依赖保持更新,关注各库安全公告;
  • HTTPS 传输是前提,配置见部署章节。

注意点

  • 校验走「默认拒绝」:白名单式规则优于黑名单过滤。
  • 转义发生在输出侧,输入侧做长度/类型限制,各管一段。
  • CSRF 对纯 Authorization 头认证基本不适用,别硬套 Cookie 那套方案。

小结

安全不是某一个库,而是每层的默认动作:入口校验、出口转义、密码加盐、浏览器策略。先把这些基础项做全,再谈纵深防御与渗透测试。

笔记加载中…