Redis6 ACL 权限模型
解读
国内一线/二线互联网公司在 PHP 后端面试中,Redis 几乎是“必考题”。Redis 6 之前只有“密码+命令重命名”这种粗糙的鉴权方式,无法满足多业务、多租户、云原生场景下的最小权限要求。ACL(Access Control List)是 Redis 6 的核心安全特性,面试官通过该问题考察:
- 你是否真的在生产环境用过 Redis 6,而不是停留在“缓存+String”层面;
- 对权限粒度、用户隔离、运维安全的理解;
- 能否把 ACL 与 PHP 业务代码、DevOps 流程结合起来落地。
回答时务必“先讲原理 → 再给命令 → 再聊 PHP 实战 → 最后说踩坑”,体现全栈能力。
知识点
- 用户(user)与密码(password):支持多用户,每个用户独立密码,可设置外部 ACL 文件或 CONFIG REWRITE 持久化。
- 权限类别:
- 命令权限:+@all、+@read、+@write、+@admin、-@dangerous 等类别;也可精确到单条命令,如 +get、-flushall。
- key 模式:通过 %RW~key* 前缀限定读写 key 的正则范围,实现“最小 key 可见集”。
- channel 权限:对 Pub/Sub 的频道做 ACL,如 &chat:*。
- 默认用户:default 用户可配置为 nopass 或 requirepass;关闭默认用户需把 default 设置为 off。
- 认证方式:AUTH <username> <password>;老版本仅 AUTH <password> 会映射到 default。
- 热加载:ACL LOAD / ACL SAVE 支持不重启实例更新规则;适合 Kubernetes Sidecar 热更新。
- 与 PHP 交互:
- phpredis 5.3+ 支持 auth(['user'=>'crm','pass'=>'xxx']);
- predis 目前需自己发 AUTH 命令,或使用 rawCommand;
- 连接池、Laravel Redis facade 需在 config/database.php 里新增 ‘username’ 字段。
- 性能影响:ACL 检查在命令执行前,做哈希表匹配,压测显示 5w~8w QPS 场景损耗 <1%,可忽略。
- 运维配套:审计日志(ACL LOG)、慢查询、告警对接 ELK;与云厂商 RAM、IAM 的映射关系。
答案
“Redis6 的 ACL 权限模型通过‘用户-命令-key-频道’四个维度实现细粒度鉴权,解决早期单密码带来的过度授权问题。
核心机制分三步:
- 创建用户:ACL SETUSER api_user on >api_pass ~order:* +@read -@dangerous &order:event
解释:启用用户 api_user,密码 api_pass,只允许以 order: 为前缀的 key 进行读操作,禁止危险命令,且只能订阅 order:event 频道。 - 客户端认证:PHP 端使用 phpredis 扩展时,
$redis->auth(['user'=>'api_user','pass'=>'api_pass']);
连接成功后,所有后续命令都会受 ACL 约束;若越权,Redis 直接返回 NOPERM 错误,PHP 层可捕获做降级或报警。 - 规则持久化:在 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 对‘最小权限’和‘操作审计’的要求。”
拓展思考
- 如果公司同时存在 Redis 5 与 Redis 6 混部,如何平滑迁移?
答:可在代理层(twemproxy、predixy)做双写,老集群用密码,新集群用 ACL;PHP 侧抽象 RedisFactory,根据环境变量决定 auth 方式,逐步灰度。 - ACL 与 Redis Module 的权限如何协同?
答:Module 可注册自己的 ACL 类别,例如 RedisSearch 提供 +@search 类别;面试可提“若自定义 Module,需在 RedisModule_AddACLCategory 中声明,并在命令表绑定标志位”。 - 云原生场景下,Sidecar 容器如何动态刷新 ACL?
答:把 ACL 规则存于 K8s ConfigMap,通过 inotify 监听文件变动,调用 ACL LOAD;同时在上层 Operator 记录 event,实现 GitOps 审计。 - 高并发 PHP 长连接池如何避免频繁 AUTH?
答:连接池复用已认证句柄;若使用 php-fpm,可在 pool 启动时做 AUTH,后续请求不再重复认证;或者开启 redis 的 resp3 协议,使用 HELLO 命令一次性完成版本协商与认证,减少 RTT。