Redis6 ACL 权限模型

解读

国内一线/二线互联网公司在 PHP 后端面试中,Redis 几乎是“必考题”。Redis 6 之前只有“密码+命令重命名”这种粗糙的鉴权方式,无法满足多业务、多租户、云原生场景下的最小权限要求。ACL(Access Control List)是 Redis 6 的核心安全特性,面试官通过该问题考察:

  1. 你是否真的在生产环境用过 Redis 6,而不是停留在“缓存+String”层面;
  2. 对权限粒度、用户隔离、运维安全的理解;
  3. 能否把 ACL 与 PHP 业务代码、DevOps 流程结合起来落地。

回答时务必“先讲原理 → 再给命令 → 再聊 PHP 实战 → 最后说踩坑”,体现全栈能力。

知识点

  1. 用户(user)与密码(password):支持多用户,每个用户独立密码,可设置外部 ACL 文件或 CONFIG REWRITE 持久化。
  2. 权限类别:
    • 命令权限:+@all、+@read、+@write、+@admin、-@dangerous 等类别;也可精确到单条命令,如 +get、-flushall。
    • key 模式:通过 %RW~key* 前缀限定读写 key 的正则范围,实现“最小 key 可见集”。
    • channel 权限:对 Pub/Sub 的频道做 ACL,如 &chat:*。
  3. 默认用户:default 用户可配置为 nopass 或 requirepass;关闭默认用户需把 default 设置为 off。
  4. 认证方式:AUTH <username> <password>;老版本仅 AUTH <password> 会映射到 default。
  5. 热加载:ACL LOAD / ACL SAVE 支持不重启实例更新规则;适合 Kubernetes Sidecar 热更新。
  6. 与 PHP 交互:
    • phpredis 5.3+ 支持 auth(['user'=>'crm','pass'=>'xxx']);
    • predis 目前需自己发 AUTH 命令,或使用 rawCommand;
    • 连接池、Laravel Redis facade 需在 config/database.php 里新增 ‘username’ 字段。
  7. 性能影响:ACL 检查在命令执行前,做哈希表匹配,压测显示 5w~8w QPS 场景损耗 <1%,可忽略。
  8. 运维配套:审计日志(ACL LOG)、慢查询、告警对接 ELK;与云厂商 RAM、IAM 的映射关系。

答案

“Redis6 的 ACL 权限模型通过‘用户-命令-key-频道’四个维度实现细粒度鉴权,解决早期单密码带来的过度授权问题。
核心机制分三步:

  1. 创建用户:ACL SETUSER api_user on >api_pass ~order:* +@read -@dangerous &order:event
    解释:启用用户 api_user,密码 api_pass,只允许以 order: 为前缀的 key 进行读操作,禁止危险命令,且只能订阅 order:event 频道。
  2. 客户端认证:PHP 端使用 phpredis 扩展时,
    $redis->auth(['user'=>'api_user','pass'=>'api_pass']);
    连接成功后,所有后续命令都会受 ACL 约束;若越权,Redis 直接返回 NOPERM 错误,PHP 层可捕获做降级或报警。
  3. 规则持久化:在 redis.conf 中配置 aclfile /etc/redis/users.acl,通过 ACL SAVE 把内存规则刷盘;CI/CD 流水线里用 Ansible 下发 acl 文件后执行 CONFIG REWRITE,实现灰度更新。

生产落地时,我们给电商大促项目拆了三类用户:

  • 结算服务(user=pay)只允许执行 ~pay:* +@write +@read;
  • 后台运营(user=admin)给予 +@all ~*,但来源 IP 通过 proxy 层的 iptables 再做一层白名单;
  • 监控脚本(user=monitor)只给 +ping +info +slowlog,杜绝 flushdb 风险。

这样即使某个微服务被 SSRF 攻击,也只能访问自己命名空间下的 key,无法删除全库,满足等保 2.0 对‘最小权限’和‘操作审计’的要求。”

拓展思考

  1. 如果公司同时存在 Redis 5 与 Redis 6 混部,如何平滑迁移?
    答:可在代理层(twemproxy、predixy)做双写,老集群用密码,新集群用 ACL;PHP 侧抽象 RedisFactory,根据环境变量决定 auth 方式,逐步灰度。
  2. ACL 与 Redis Module 的权限如何协同?
    答:Module 可注册自己的 ACL 类别,例如 RedisSearch 提供 +@search 类别;面试可提“若自定义 Module,需在 RedisModule_AddACLCategory 中声明,并在命令表绑定标志位”。
  3. 云原生场景下,Sidecar 容器如何动态刷新 ACL?
    答:把 ACL 规则存于 K8s ConfigMap,通过 inotify 监听文件变动,调用 ACL LOAD;同时在上层 Operator 记录 event,实现 GitOps 审计。
  4. 高并发 PHP 长连接池如何避免频繁 AUTH?
    答:连接池复用已认证句柄;若使用 php-fpm,可在 pool 启动时做 AUTH,后续请求不再重复认证;或者开启 redis 的 resp3 协议,使用 HELLO 命令一次性完成版本协商与认证,减少 RTT。