Redis在6.0之前,客户端通过requirepass参数配置的单一密码完成认证,通过后即拥有实例的全部权限。这意味着一个只负责读取缓存的应用,理论上也可以执行FLUSHALL清空全部数据,或通过CONFIG SET修改持久化配置。Redis 6.0引入ACL访问控制列表后,认证身份与操作权限被彻底拆分,管理员可以创建多个用户,为每个用户设置独立密码、允许执行的命令、允许访问的键名模式以及Pub/Sub频道。ACL是Redis向多租户和合规场景演进的重要一步。

在ACL体系中,每个用户由一组规则描述,规则按顺序解释,后面规则可以覆盖前面规则。理解规则组合是掌握ACL的关键,下面从用户模型与规则语法讲起。
一、ACL用户模型与规则语法
ACL规则围绕用户定义。一个用户包含用户名、启用状态、密码列表、命令权限、键权限、频道权限和选择器。Redis内置的default用户在未显式配置时拥有所有权限,很多老客户端习惯只提供密码不提供用户名,此时认证的就是default。生产环境如果只设置requirepass,相当于default用户仍然持有全部权限,ACL的价值没有真正发挥。
规则语法简洁但组合灵活。on和off控制用户是否启用;>password用于设置明文密码,Redis会保存SHA256哈希;#hash用于直接写入密码哈希;nopass表示不需要密码;<password是密码删除标记。命令权限用+和-前缀,比如+get允许GET命令,-set禁止SET命令。Redis还提供命令类别,如+@read允许所有读命令,-@admin禁止管理类命令。键权限用~前缀,~cache:*表示只能访问以cache:开头的键,%R~cache:*则表示只读访问该模式。allkeys和allchannels分别表示所有键和所有频道。
下面创建两个用户:app_read可以读缓存,app_write可以写缓存,但都限制在cache:前缀。示例命令如下:
ACL SETUSER app_read on >readpass123 ~cache:* +get +exists +mget ACL SETUSER app_write on >writepass456 ~cache:* +set +del +expire ACL GETUSER app_read
二、ACL核心命令与配置持久化
通过redis-cli管理ACL最常用。ACL LIST返回所有用户规则;ACL GETUSER username查看某用户解析后的权限;ACL SETUSER username rule...创建或修改用户;ACL DELUSER删除用户;ACL WHOAMI显示当前连接身份;ACL CAT可查询命令类别;ACL GENPASS生成随机密码。例如执行ACL CAT read会列出被归入read类别的命令。这些命令可以在线执行,立即生效,适合紧急回收权限。
在线修改默认只影响运行时内存,Redis重启后丢失,除非同时执行ACL SAVE将规则写入aclfile,或在配置文件中预先定义用户。Redis 6默认通过requirepass兼容老客户端,但生产建议设置aclfile指向独立ACL文件并显式管理用户。配置文件中可以写成:
aclfile /etc/redis/users.acl
然后编辑users.acl文件,定义用户规则:
user default off user admin on #8d969eef6ecad3c29a3a... ~* +@all user app_read on #f6a7b... ~cache:* +@read
这样Redis启动时自动加载ACL规则。执行ACL LOAD可以从aclfile重新加载,ACL SAVE把当前规则覆盖写入aclfile。迁移时可以将规则复制到文件或使用ACL LIST输出再导入。需要注意的是,如果启用了aclfile,直接修改配置文件中的requirepass并不能覆盖ACL默认用户行为。
三、最小权限原则与多业务隔离实践
权限控制最常见的错误是直接给业务用户+@all,这等于又回到单密码时代。应该按业务模块拆分用户。例如订单服务需要读写order:*,用户服务读写user:*,两个服务使用不同账号,既能防止误操作也能缩小泄露范围。命令权限同样需要最小化:缓存读取场景只给+@read,后台任务才给+@write或具体命令。
Pub/Sub频道同样受ACL控制,频道权限用&前缀。如果不设置频道权限,默认用户可访问所有频道。创建一个只允许发布和订阅events:频道的用户:
ACL SETUSER notifier on >notify789 &events:* +publish +subscribe +psubscribe
在应用中,客户端连接应指定用户名,避免所有服务使用default账号。以Python客户端为例:
import redis
client = redis.Redis(
host="127.0.0.1",
port=6379,
username="app_read",
password="readpass123",
decode_responses=True
)
value = client.get("cache:user:1001")
print(value)
如果客户端库不支持用户名参数,也可以在连接后使用AUTH username password认证。逐步将业务迁移到独立用户后,再收紧default账号权限,可以降低切换风险。
四、ACL故障排查与安全审计
认证或权限异常时,先看错误信息。WRONGPASS invalid username-password pair表示用户名或密码错误;NOPERM this user has no permissions to run the command表示身份正确但命令或键权限不够。如果使用的是default账号,执行ACL WHOAMI会打印default。使用ACL LOG可以查看最近被拒绝的命令记录,包括时间、用户、命令和键,适合审计暴力尝试或越权操作。
客户端连接时建议显式指定用户名,否则默认使用default身份。如果default被设置为off,不带用户名的老客户端会全部失败。为了兼容,可以在内部网段保留一个只读default,外网强制使用专用用户。同时限制Redis绑定地址,使用TLS传输密码,避免明文密码在网络上暴露。
生产环境应把ACL规则纳入配置管理,变更走代码评审。定期执行ACL LIST对比基线,检查是否出现+@all、~*、nopass等过度授权标记。对于高危命令如FLUSHALL、FLUSHDB、CONFIG、SHUTDOWN、DEBUG、EVAL等,除非确定必要,不要授予普通业务用户。必要时可使用命令别名重命名,但ACL已经能直接阻止,不必依赖rename-command。
ACL让Redis从单密码粗略控制走向了精细化授权。新项目可以直接采用独立用户加最小权限方案,旧项目可以分阶段迁移,先创建业务用户,再逐步收紧default权限,既保证兼容性,又能有效提升实例安全性。