☰
Redis6 ACL权限控制实战:从误删事故到精细化权限管理
2026/10/14 18:25:45 网站建设 项目流程

1. 从一次线上误删事故说起:为什么Redis6的ACL值得单独拿出来讲

几年前我还在负责一个中小型电商系统的缓存层维护,当时整个团队对Redis的使用方式非常“粗放”——所有服务共用同一个默认用户,密码就是配置文件里那一行requirepass,谁拿到密码谁就是超级管理员,能执行任何命令。某天凌晨,一个刚入职的同事在排查一个数据不一致问题时,本来只想清理某个业务前缀下的几个key,结果手一抖敲成了FLUSHALL,整个实例的缓存瞬间被清空。虽然缓存可以重建,但那一刻数据库被打穿,接口响应时间从几十毫秒飙到几秒,订单服务直接告警。事后复盘,大家最痛的点不是“人犯错”,而是Redis根本没有给我们任何细粒度的权限约束手段——那个同事的账号理论上就不该拥有FLUSHALL这种危险命令的执行权限。

这件事之后我一直在关注Redis在权限管理上的演进。在Redis6之前,官方的安全手段基本只有两样:requirepass设置一个全局密码,以及通过rename-command把危险命令改名或禁用。前者是“一把钥匙开所有门”,后者则是“把门焊死”,运维起来极其别扭——你没法针对不同业务分配不同权限,也没法在不重启的情况下动态调整。Redis6引入的ACL(Access Control List,访问控制列表)彻底改变了这个局面,它把“用户”这个概念真正带进了Redis,让每个连接可以绑定到不同的用户,每个用户拥有独立的密码、独立的命令权限、独立的key访问范围。

这篇文章我想聊的就是Redis6 ACL这套安全策略到底怎么用、背后的设计逻辑是什么、实际落地时有哪些坑。它适合已经在用Redis、并且开始关心“谁能操作什么”的运维和开发同学,也适合那些还在用单密码裸奔、想升级权限体系但不知道从哪下手的朋友。我会从整体设计思路讲到具体命令,再到生产环境的实操配置和排查技巧,尽量把每个“为什么这么设计”讲透,让你看完能直接在自己的环境里落地一套可用的权限方案。

2. ACL整体设计与核心概念拆解

2.1 为什么是“用户+规则”而不是继续加密码

要理解ACL的设计,先得理解Redis之前的权限模型有多单薄。在Redis6之前,一个实例只有一个密码,所有客户端连上来都是同一个身份,权限完全一致。这种模型在单团队、单业务的小规模场景下勉强够用,但一旦实例被多个业务线共享,问题就来了:A业务只需要读写自己的缓存key,却因为共用密码而拥有了删除任意key、甚至执行CONFIG SET改配置的能力。这本质上是一个权限过度授予的问题。

Redis6的ACL选择用“用户(user)”作为权限的载体,而不是继续在密码上做文章,原因很直接:密码只能回答“你能不能进来”,回答不了“你进来之后能干什么”。用户这个概念天然可以承载多维度的权限描述——密码、命令白名单/黑名单、key模式、频道模式。这样一来,权限的最小粒度就从“整个实例”细化到了“某个用户能碰哪些key、能跑哪些命令”。我在实际项目里最直观的感受是,以前给一个新业务开缓存权限,只能新建实例或者共用密码,现在直接ACL SETUSER建一个用户,把它的key前缀和命令范围卡死,几分钟就能搞定,而且互不干扰。

2.2 ACL的四个核心维度

ACL对用户的权限描述可以拆成四个维度,理解了这四个维度,后面所有命令都是它们的组合。

第一个维度是认证方式,也就是这个用户怎么证明自己是自己。可以是明文密码(>password),也可以是密码的SHA256哈希(#hash),还可以配置多个密码。第二个维度是命令权限,控制这个用户能执行哪些命令,可以精确到子命令,比如只允许GET不允许SET,或者只允许CLIENT LIST不允许CLIENT KILL。第三个维度是key权限,通过模式匹配限定用户能访问哪些key,比如只允许操作order:*开头的key。第四个维度是频道权限,针对发布订阅场景,限定用户能订阅或发布哪些频道。

这四个维度组合起来,就形成了一个用户的完整权限画像。我习惯把它类比成公司门禁系统:认证方式是门禁卡,命令权限是你能进哪些楼层,key权限是你能开哪些房间的门,频道权限是你能收听哪些广播。这个类比虽然不严谨,但能帮新手快速建立直觉。

2.3 默认用户与ACL的兼容性设计

Redis6在引入ACL的同时,必须保证对老版本的兼容,否则升级会变成灾难。它的做法是保留一个名为default的默认用户,所有没有显式认证的客户端都自动以default用户身份运行。在默认配置下,default用户拥有所有命令、所有key、所有频道的权限,并且不需要密码——这跟Redis5的行为完全一致。也就是说,你升级到Redis6之后,如果什么都不配置,业务代码一行不用改,照常运行。

这个兼容性设计非常关键,它意味着ACL的落地可以是渐进的:你可以先让default用户继续裸奔,同时新建几个受限用户给新业务用,等验证稳定后再逐步收紧default的权限,最后把它彻底禁用。我在迁移一个老系统时就是这么干的,前后花了两周时间,业务方完全无感知。这里要提醒一句,default用户虽然方便,但生产环境最终一定要处理它——要么给它设一个强密码,要么直接ACL SETUSER default off禁用它,否则ACL形同虚设。

3. ACL核心命令与实操要点详解

3.1 用户管理命令:从创建到删除的完整链路

ACL的用户管理命令以ACL为前缀,最常用的是ACL SETUSER,它既能创建用户也能修改用户。这个命令的语法是ACL SETUSER username [规则...],规则可以一次给多个,也可以分多次追加。我个人的习惯是创建用户时一次性把规则写全,这样配置意图清晰,也方便后续用ACL LIST导出备份。

创建用户的基本流程是这样的:先ACL SETUSER app_order on >OrderPass123 ~order:* +@read +@write -@dangerous,这条命令做了几件事——开启用户、设置密码、限定只能访问order:开头的key、允许读写类命令、禁止危险命令。然后可以用ACL WHOAMI确认当前连接的身份,用ACL LIST查看所有用户的完整规则,用ACL GETUSER app_order查看单个用户的详情。删除用户用ACL DELUSER username,注意default用户不能被删除,只能被禁用。

这里有个细节值得展开:ACL SETUSER的规则是增量叠加的,不是覆盖。也就是说,如果你先执行了ACL SETUSER app_order +@read,再执行ACL SETUSER app_order +@write,最终这个用户同时拥有读写权限。如果你想重置某个用户的规则,得先用ACL SETUSER app_order reset清空,再重新配置。我踩过一次坑:以为再次SETUSER会覆盖旧规则,结果旧权限一直残留,排查了半天才发现是增量叠加的机制。

3.2 命令权限的精细控制:从命令类别到子命令

命令权限是ACL里最灵活也最容易配错的部分。Redis把命令分成了若干类别,用@符号引用,比如@read、@write、@admin、@dangerous、@fast、@slow等。你可以用+@read允许整个读类别,也可以用-@dangerous禁止所有危险命令。类别的好处是省事,坏处是粒度粗——比如@write里既有安全的SET,也有能清库的FLUSHDB。

所以生产环境我一般会采用“类别打底+单命令微调”的策略。先用+@read +@write给一个基础范围,再用-FLUSHALL -FLUSHDB -KEYS -CONFIG把明确的危险命令摘掉。这里要注意命令的大小写不敏感,+get和+GET效果一样,但为了可读性建议统一大写。另外,子命令的控制用|分隔,比如+config|get只允许查询配置,-config|set禁止修改配置。这个特性在需要给监控系统开只读配置权限时特别有用。

还有一个容易被忽略的点:命令权限的判定顺序。当用户同时被允许和禁止某个命令时,Redis的规则是“后配置的生效”。比如你先+@all再-GET,那GET就是被禁止的;反过来先-GET再+@all,GET又会被允许。这个顺序依赖在多人协作维护ACL时很容易出问题,我的建议是永远把禁止规则放在允许规则之后,并且用ACL GETUSER确认最终生效的权限,不要凭记忆。

3.3 key权限的模式匹配:通配符的边界与陷阱

key权限用~符号声明,后面跟模式。~order:*表示只能访问order:开头的key,~*表示所有key,~后面什么都不跟则表示禁止访问任何key。模式匹配用的是glob风格的通配符,*匹配任意字符,?匹配单个字符,[abc]匹配字符集。这套语法跟Redis的KEYS命令一致,上手不难,但有几个边界要注意。

第一,模式匹配是针对完整key名的,不是前缀匹配。~order:*能匹配order:123,但匹配不了myorder:123,因为后者不以order:开头。第二,多个key权限是“或”的关系,~order:* ~user:*表示两类key都能访问。第三,key权限对命令的约束是全局的,也就是说即使用户有GET命令权限,如果目标key不在它的key模式范围内,命令依然会被拒绝,报错信息是NOPERM。这个报错在实际排查时很有用,看到NOPERM基本就能定位到是key权限或命令权限的问题。

我在配置key权限时有个经验:尽量用业务前缀+冒号的模式,比如~cache:order:*,而不是宽泛的~*order*。后者看起来方便,实际上会把user:order_history这种不相关的key也放进来,权限边界就模糊了。另外,如果业务key的命名本身不规范,比如有的用下划线有的用冒号,那ACL配置会非常痛苦,这时候应该先推动key命名规范,再上ACL。

3.4 频道权限与发布订阅的权限隔离

频道权限用&符号声明,针对的是发布订阅(Pub/Sub)场景。&news:*表示只能订阅或发布news:开头的频道。这个维度在纯缓存场景下用得少,但在用Redis做消息总线的系统里就很重要了。比如一个系统里既有订单消息频道,又有用户消息频道,你肯定不希望订单服务能往用户频道里发消息。

频道权限的配置逻辑和key权限类似,也是模式匹配、多个“或”关系。需要注意的是,频道权限同时约束PUBLISH和SUBSCRIBE,你不能只允许订阅不允许发布,或者反过来,除非用命令权限单独控制PUBLISH和SUBSCRIBE命令。实际项目里我一般会把频道权限和命令权限配合使用:用&order:*限定频道范围,再用+subscribe +publish允许这两个命令,这样权限边界就很清晰了。

4. 生产环境ACL落地的完整实操流程

4.1 配置文件持久化:让ACL规则不丢

用ACL SETUSER在运行时创建的用户,默认只存在于内存里,重启就没了。这在生产环境是致命的,所以必须把ACL规则持久化。Redis提供了两种方式:一种是在redis.conf里用user指令声明,另一种是用ACL SAVE把当前规则写入ACL文件,再在配置里用aclfile指定这个文件。

我推荐用aclfile的方式,原因是它支持运行时ACL SAVE和ACL LOAD,运维起来更灵活。具体做法是在redis.conf里加一行aclfile /etc/redis/users.acl,然后执行ACL SAVE,当前所有用户规则就会写入这个文件。之后每次修改用户,记得再ACL SAVE一次。这里有个坑:如果aclfile指定的文件不存在,Redis启动会报错,所以第一次部署时要先手动创建空文件或者先执行一次ACL SAVE。

还有一种情况是配置文件和aclfile同时存在user定义,这时候aclfile的优先级更高,配置文件里的user会被忽略。这个行为在排查“为什么我改了配置文件没生效”时经常是元凶,记住就行。

4.2 分阶段迁移:从单密码到多用户的平滑过渡

直接给一个正在运行的生产实例上ACL,风险很高,因为一旦配错,业务可能瞬间不可用。我的做法是分四个阶段推进。

第一阶段,保持default用户不变,新建受限用户给新业务用,老业务继续走default。这个阶段的目标是验证ACL规则本身没问题,同时让团队熟悉命令。第二阶段,给default用户设置密码,但保留全部权限,然后逐步把老业务的连接配置改成带密码。第三阶段,收紧default用户的权限,比如去掉@dangerous,观察是否有业务报错。第四阶段,禁用default用户,所有业务都用自己的专属用户。

每个阶段之间至少观察一天,重点看Redis的慢日志和业务侧的NOPERM报错。我在第二阶段遇到过一个问题:某个老服务的连接池配置里密码是写死的,改密码后没同步更新,导致连接全部失败。所以改default密码前,一定要先梳理清楚有哪些客户端在用,别漏了。

4.3 一个完整的用户配置示例与验证

假设我们要给订单服务配一个用户,需求是:只能访问order:和cart:开头的key,允许读写命令,禁止所有危险命令,密码用强密码。配置命令如下:

ACL SETUSER app_order on >Str0ngP@ss2024 ~order:* ~cart:* +@read +@write -@dangerous -FLUSHALL -FLUSHDB -KEYS -CONFIG ACL SAVE

配完之后必须验证,验证分三步。第一步用ACL GETUSER app_order看规则是否符合预期,重点确认keys和commands两栏。第二步用redis-cli --user app_order --pass Str0ngP@ss2024连上去,执行SET order:1 test应该成功,执行SET other:1 test应该报NOPERM,执行FLUSHALL也应该报NOPERM。第三步用ACL LOG查看被拒绝的命令记录,这个命令会列出最近所有权限拒绝事件,是排查权限问题的利器。

注意:ACL LOG默认只保留最近的128条记录,高并发场景下可能很快被冲掉,排查时要及时查看,或者用ACL LOG 数量调整保留条数。

5. 常见问题与排查技巧实录

5.1 NOPERM报错的定位思路

NOPERM是ACL最常见的报错,格式一般是NOPERM this user has no permissions to run the 'xxx' command或者NOPERM this user has no permissions to access one of the keys used as arguments。看到这个报错,第一步是用ACL WHOAMI确认当前连接用的是哪个用户,很多时候问题出在客户端根本没认证成功,还在用default或者匿名身份。第二步用ACL GETUSER 用户名看这个用户的命令权限和key权限,对照报错里的命令名和key名,基本就能定位。

我整理了一个排查速查表,覆盖了几种典型场景:

报错信息关键词可能原因排查动作
no permissions to run the command命令权限不足检查ACL GETUSER的commands栏,确认命令或类别是否被允许
no permissions to access one of the keyskey权限不足检查keys栏的模式是否覆盖目标key,注意前缀和通配符
no permissions to access one of the channels频道权限不足检查channels栏,确认发布订阅的频道在范围内
WRONGPASS密码错误或用户未开启检查用户是否on,密码是否正确,注意>和#的区别
连接直接被拒绝用户被禁用或不存在用ACL LIST确认用户存在且状态为on

5.2 密码配置的两种写法与选择

ACL支持明文密码和哈希密码两种写法。明文用>前缀,比如>mypassword;哈希用#前缀,后面跟密码的SHA256值。明文的好处是直观,配置时不容易出错;坏处是ACL LIST和ACL GETUSER会把密码明文显示出来,任何能执行这些命令的人都能看到密码。哈希的好处是即使规则泄露,攻击者也无法直接得到明文密码;坏处是配置时得先算哈希,稍微麻烦一点。

我的建议是生产环境用哈希,尤其是多人能访问Redis的团队。算哈希可以用echo -n "mypassword" | sha256sum,把结果前面加#填进去。这里有个细节:echo -n的-n不能省,否则会把换行符也算进哈希,导致密码对不上。我见过有人因为这个细节排查了一下午。

5.3 ACL规则冲突与优先级问题

前面提过命令权限是“后配置生效”,但实际场景里还有更复杂的冲突。比如一个用户同时属于+@read和-GET,那GET到底能不能用?答案是看配置顺序,后配的-GET生效,所以GET被禁止。但如果先-GET再+@read,GET又会被@read重新允许。这种顺序依赖在规则多的时候非常容易出错。

我的应对策略是规则分层:先配类别级别的允许(+@read +@write),再配类别级别的禁止(-@dangerous),最后配单命令级别的微调(-FLUSHALL +config|get)。这样从粗到细,顺序固定,不容易乱。另外,每次修改后用ACL GETUSER确认最终结果,不要凭记忆推断。如果团队人多,建议把ACL规则纳入版本管理,每次变更走review,避免有人随手改了一条规则把权限放大。

5.4 性能影响与监控要点

很多人关心ACL会不会拖慢Redis。实测下来,ACL的权限检查是在命令执行前做的一次规则匹配,开销很小,在常规QPS下基本感知不到。但如果一个用户的key权限模式特别多、特别复杂,每次命令都要遍历所有模式做匹配,理论上会有额外开销。我的经验是单个用户的key模式控制在10个以内,超过这个数量就该考虑是不是key命名设计有问题,或者该拆实例了。

监控方面,除了常规的Redis指标,建议关注ACL LOG里的拒绝事件数量。如果某个用户的拒绝事件突然飙升,要么是业务代码改了命令用法,要么是有人在试探权限,都值得警惕。可以用ACL LOG 数量配合定时任务把拒绝日志采集出来,接入告警系统。另外,INFO里的acl相关字段也能反映一些状态,虽然信息不多,但聊胜于无。

6. 我在实际落地中总结的几条经验

ACL这套东西刚上手时命令不少,但真正用起来核心就是SETUSER、GETUSER、LIST、SAVE、LOG这几个。我最大的体会是:ACL的价值不在于技术多复杂,而在于它逼着团队去梳理“谁该有什么权限”。以前共用密码时,没人说得清某个服务到底需要哪些命令,上了ACL之后,每个用户的规则就是一份权限文档,反而让架构更清晰了。

另一个经验是别追求一步到位。我见过有团队想一次性把所有用户配好、把default禁掉,结果业务大面积报错,回滚都来不及。ACL的迁移一定是渐进的,先兼容、再收紧、最后禁用,每一步都留观察期。还有,ACL SAVE这个动作一定要养成习惯,改完就存,别等重启时才发现规则丢了。

最后分享一个小技巧:如果你不确定某个用户该配哪些命令,可以先用+@all让它跑一段时间,然后用ACL LOG统计它实际用到的命令,再据此收敛权限。这个“先放后收”的思路在权限治理里很实用,比拍脑袋配规则靠谱得多。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询