在Redis 6.0之前,整个实例只有一个密码,所有连上来的客户端都拥有相同的权限,能执行所有命令、访问所有数据。这种粗放的安全模型在多人共用一个Redis集群时隐患很大:一个业务方的误操作,比如执行了FLUSHALL,可能把其他业务的数据全部清空。ACL(Access Control List,访问控制列表)机制就是为了解决这个问题而引入的,而acl setuser命令正是配置这套机制的核心入口。掌握它,你就能给每个业务分配独立账号,把权限牢牢锁在该有的范围内。

ACL基本概念与setuser命令语法
ACL的核心思路是把“用户”作为权限的基本单位。每个用户拥有四个维度的配置:一是是否启用(on/off),二是密码(可以设置多个),三是允许执行的命令集合,四是允许访问的Key模式。默认情况下Redis自带一个名为default的默认用户,它在未做任何配置时拥有全部权限,这就是为什么老版本升级后服务还能照常工作。
acl setuser的语法结构是ACL SETUSER username [rule [rule ...]],其中username是用户名,后面的rule是一系列规则参数,可以同时传多个。需要注意的是,如果用户不存在,执行该命令会自动创建;如果已存在,则是在原有配置基础上做增量修改,这一点和很多人直觉里的“覆盖式更新”不同,如果确实想重置某个用户,需要显式传入reset规则。
常用的规则关键词包括:on和off控制用户启用状态;reset将用户恢复到初始状态(禁用、清空密码和权限);>password添加密码,<password删除密码;~pattern设置可访问的Key模式,支持glob通配符;+command授权某个命令,-command收回某个命令;allkeys等价于~*,allcommands等价于+@all。理解这些规则之后,几乎所有权限配置场景都能覆盖。
实战:创建一个受限的业务账号
假设有一个订单服务需要访问Redis,我们希望它只能读写以order:开头的Key,只能执行基本的读写命令,不能执行FLUSHDB、CONFIG这类危险命令。可以按下面的步骤操作。
redis-cli # 创建用户order_svc,启用它,设置密码,限制Key前缀,只授权基础命令 ACL SETUSER order_svc on >Order@2024 ~order:* +get +set +del +mget +expire +ttl # 查看配置结果 ACL GETUSER order_svc
执行ACL GETUSER后,会看到类似这样的输出,包含flags标记、密码哈希、命令权限和Key模式四个部分。其中密码在输出中显示的是SHA256哈希值,这是Redis有意为之,明文密码不会回显。
1) "flags" 2) 1) "on" 2) "sanitize-payload" 3) "passwords" 4) 1) "a58c4b2f...(SHA256哈希)" 5) "commands" 6) "-@all +get +set +del +mget +expire +ttl" 7) "keys" 8) 1) "order:*"
验证一下效果:用新用户连接后,执行SET order:1001 test会成功,但执行SET user:1001 test会收到WRONGTYPE类似的权限错误(实际是NOPERM类错误),提示Key不匹配允许的模式。同样,尝试执行FLUSHDB也会被拒绝。这种细粒度控制正是ACL的价值所在。
# 用指定账号连接 redis-cli --user order_svc --pass Order@2024 127.0.0.1:6379> SET order:1001 hello OK 127.0.0.1:6379> SET user:1001 hello (error) ERR NOPERM this user has no permissions to access one of the keys used as arguments 127.0.0.1:6379> FLUSHDB (error) ERR NOPERM this user has no permissions to run the 'flushdb' command
命令分类与Key模式的高级用法
如果每个命令都单独授权,规则会写得很长。Redis内置了命令类别(category),用@符号表示,比如@read包含所有读命令,@write包含所有写命令,@connection包含PING、AUTH等连接类命令,@dangerous则聚集了FLUSHALL、SHUTDOWN、DEBUG等高危命令。合理组合类别能让配置更简洁,例如给一个只读统计账号授权+@read +@connection,再显式减去危险命令。
# 给报表账号授予读权限和连接权限 ACL SETUSER report_svc on >Report@2024 ~stat:* +@read +@connection # 授权大部分常用命令但明确禁止危险命令 ACL SETUSER app_user on >App@2024 allkeys +@all -@dangerous
Key模式方面,~指定的模式支持glob语法,~order:*匹配所有order前缀的Key,~*:*匹配所有包含冒号的Key。还可以用resetkeys先清空已有模式再重新设置,用allkeys直接放开全部Key。如果要限制用户只能从特定网段连接,可以用&规则绑定客户端来源,比如&192.168.1.*只允许该网段连接。
另外还有一个容易踩的坑:通过命令行设置的ACL规则默认只存在内存中,Redis重启后会丢失。生产环境一定要把ACL规则写入配置文件,在redis.conf中通过aclfile /etc/redis/users.acl指定外部ACL文件,或者直接在配置文件里写user指令。使用外部文件时,可以通过ACL LOAD命令重载文件,ACL SAVE命令把当前内存中的规则持久化到文件,避免每次改动都要重启服务。
# users.acl 文件示例 user default on nopass ~* +@all user order_svc on #a58c4b2f... ~order:* +get +set +del +expire user report_svc on >Report@2024 ~stat:* +@read +@connection
注意文件里密码可以用#加SHA256哈希的形式存储,避免明文落盘,这个哈希值可以从ACL GETUSER的输出中复制。日常运维时配合ACL LIST查看所有用户概要、ACL WHOAMI确认当前连接身份、ACL USERS列出全部用户名,就能形成一套完整的管理闭环。
常见问题与注意事项
第一,不要随意禁用default用户。很多客户端SDK和旧应用依赖默认用户做认证,直接ACL SETUSER default off可能导致大量连接失败。正确做法是给default设置强密码并逐步迁移业务到独立账号。
第二,密码规则中>和<后面的密码不能包含空格,如果密码里有特殊字符,建议提前测试转义行为,或者改用#加哈希的方式设置。第三,规则修改是增量生效的,排查权限问题时先用ACL GETUSER看清楚当前实际状态,不要凭记忆判断。第四,Key模式只对涉及Key参数的命令生效,像INFO、DBSIZE这类不针对具体Key的命令不受Key模式约束,只能靠命令权限控制。
总结来说,acl setuser是Redis权限体系的基石,从创建用户、设置密码到命令授权、Key模式限制,一条命令全部搞定。建议在生产环境中给每个业务系统分配独立账号,遵循最小权限原则,只授予必要的命令类别和Key范围,再配合ACL文件持久化,安全性和可维护性都会有明显提升。