登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  数据库 >  Redis

Redis ACL 按命令和 key pattern 限制权限怎么写

来源:17golang原创

时间:2026-09-11 15:21:11 207浏览 收藏

Redis ACL 不是只给用户设置一个密码。真正要收敛权限,至少要同时写清楚“谁能登录”“能执行哪些命令”“这些命令能碰哪些 key”。最小可用的思路是先 reset 清掉旧规则,再按应用职责加入命令和 key pattern;Redis 7 及以上还可以用 %R~%W~ 把读写范围拆开。

要点速览
  • +GET 只限制命令,不代表用户能访问任何 key;还要配置 ~app:* 或更细的 key 权限。
  • ~pattern 默认同时授予读写,Redis 7 可用 %R~pattern%W~pattern 区分读写。
  • key pattern 管不到不带 key 参数的命令,FLUSHALLFLUSHDBSWAPDB 要单独移除。

先把三种权限拆开:用户、命令与 key pattern

ACL 规则是按从左到右应用的,已有用户如果直接追加规则,历史权限仍可能留下来。因此应用用户建议从 reset 开始。下面这个最小示例让 app_reader 只读 app:*,并保留认证密码由部署系统替换。

# reset 清除用户旧规则,避免历史 +@all 或 ~* 继续生效
redis-cli ACL SETUSER app_reader reset on '>replace-with-strong-password' '~app:*' +GET +MGET +EXISTS

# 查看最终规则,确认用户、命令和 key 范围都在预期内
redis-cli ACL GETUSER app_reader

这里的 +GET+MGET 是命令边界,~app:* 是 key 边界。只写命令不写 key pattern,客户端仍会因为没有匹配的 key 权限而失败;只写 ~app:* 也不会自动获得 GET 或 SET。

Redis ACL 客户端、ACL 用户、命令集合与 app key pattern 的三层权限边界静态结构图
图1:Redis ACL 的用户、命令和 key pattern 是三个相互配合但不能互相替代的权限边界。

用 selector 处理读写边界,别把 ~* 当成万能限制

如果同一个用户既要读取缓存,又要写入自己的业务 key,直接使用 ~app:* 会把读写合并。Redis 7 的 key permission 可以把两种能力拆开;selector 用括号包住一组规则,适合表达“某组命令只能作用于某组 key”。

# Redis 7+:读 selector 和写 selector 分别绑定到同一组 key
redis-cli ACL SETUSER app_rw reset on '>replace-with-strong-password' '(+@read %R~app:*)' '(+@write %W~app:*)'

# ACL CAT 可查看 read、write 等命令分类的实际成员
redis-cli ACL CAT read
redis-cli ACL CAT write

不要把 selector 理解成拒绝规则。根权限或任意一个 selector 匹配成功,就可能放行命令;所以根权限里不要残留 +@allallkeys 这类宽规则。多 key 命令还要检查每个 key 是否同时满足命令所需的读写权限。

写法含义适用提醒
~app:*匹配 key 的读写权限最简单,但范围较宽
%R~app:*只允许读取匹配 keyRedis 7 及以上
%W~app:*只允许写入匹配 keyRedis 7 及以上
resetkeys清除当前 key pattern修改用户时防止旧范围残留
Redis ACL selector 读写 key 权限与 FLUSHALL 等 keyless 命令的静态边界关系图
图2:selector 能细分读写 key 权限,但 FLUSHALL、FLUSHDB、SWAPDB 仍需单独从命令集合移除。

key pattern 管不到的命令要单独封口

key pattern 只约束命令参数中明确出现的 key。它不会限制操作整个数据库或整个 keyspace 的命令,所以“只允许 tenant1:*”并不等于“只能删除 tenant1 数据”。一个带宽权限的用户仍可能执行清空数据库的命令。

# 即使保留较宽的命令类别,也要显式移除清空和交换数据库的命令
redis-cli ACL SETUSER tenant_app reset on '>replace-with-strong-password' '~tenant1:*' +@all -FLUSHALL -FLUSHDB -SWAPDB

# 修改后再次读取规则,确认危险命令确实出现在减号列表中
redis-cli ACL GETUSER tenant_app

生产环境还应把 CONFIGMODULEACL 等管理能力按职责拆给平台账号,不要为了让业务请求通过而直接使用 +@all。如果客户端收到 NOPERM,先记录用户名、命令名和实际 key,再分别对照命令规则与 key 规则,不要先扩大到 ~*

发布前的 ACL 检查清单

  • ACL GETUSER 用户名 确认用户是 on,没有遗留 nopassallkeys+@all
  • 至少验证一条允许的 key、一条不匹配的 key,以及一条不应出现的命令。
  • 涉及 Redis 7 读写权限时,确认服务端版本和客户端对 selector 语法的支持。
  • 变更后保存 ACL 配置并安排密码轮换;不要把示例密码直接用于生产。

常见问题

只配置 +GET,为什么还是 NOPERM?

因为命令权限和 key 权限是两层条件。还需要为目标 key 配置匹配的 ~pattern 或读权限 pattern。

~app:* 能阻止 FLUSHALL 吗?

不能。FLUSHALL 没有具体 key 参数,必须使用 -FLUSHALL 单独移除,FLUSHDB 和 SWAPDB 同理。

修改 ACL SETUSER 会覆盖旧配置吗?

普通规则默认是在原有规则上追加或修改;要从干净状态重建,先把 reset 放在规则开头。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>