安全专题

安全基线

Juice 本身不替代应用安全控制。建议把安全分为三层:

  1. SQL 构造层(参数绑定、动态片段)

  2. 应用层(输入校验、鉴权、审计)

  3. 数据库层(账号权限、连接策略)

参数绑定规则(必须)

在 mapper 中优先使用 #{}

  • #{name}:预编译参数,占位符绑定,推荐。

  • ${name}:字符串直拼,存在注入风险,仅在受控场景使用。

安全示例:

<select id="GetUsers">
  SELECT id, name
  FROM users
  WHERE name = #{name}
</select>

高风险示例(避免):

<select id="DangerousSearch">
  SELECT * FROM users WHERE ${rawWhere}
</select>

动态 SQL 安全模式

1) 动态排序白名单

var orderByWhitelist = map[string]string{
    "created_at": "created_at",
    "name":       "name",
    "id":         "id",
}

func SafeOrderBy(input string) string {
    if v, ok := orderByWhitelist[input]; ok {
        return v
    }
    return "created_at"
}

然后再将安全值传给 mapper(即使使用 ${},值也来自白名单)。

2) 动态表名白名单

分表场景下,不直接信任请求参数;先映射成已知表名。

3) IN 列表限长

无论是 foreach 还是手写 SQL,限制列表长度,防止超长 SQL 与资源耗尽。

日志与审计

  • 生产环境避免输出敏感参数(手机号、身份证、token、密码等)。

  • 建议在调试中间件前增加脱敏中间件。

  • 对关键写操作记录审计字段(操作者、请求 ID、时间、来源)。

数据库权限最小化

  • 读写分离账号:读账号仅 SELECT,写账号仅必要 DML

  • 禁止业务账号使用 DROP/ALTER 等高危权限。

  • 按服务拆分数据库账号,避免共享高权限凭据。

事务与安全

  • 不要把跨数据源写入当成一个本地事务(见“多数据源 × 事务交互”)。

  • 对资金、库存等关键路径,结合幂等键和唯一约束,防止重放与并发穿透。

发布前安全检查清单

  • mapper 中是否存在未经白名单约束的 ${}

  • Debug 日志是否会泄露敏感参数。

  • 数据库账号权限是否最小化。

  • 高风险接口是否有鉴权、限流与审计。

  • 动态查询是否有上限(分页、IN 长度、超时)。