很多开发者都会误解这个问题:Redis ACL 中的 &pattern 对 SUBSCRIBE 订阅操作实际上并不起作用。根本原因在于,这项规则只有在 Redis 6.2 及以上版本、并且启用了 acl-pubsub-default 时,才会参与 PUBLISH 的权限校验;而对于 SUBSCRIBE,它会完全绕过这套频道匹配机制。也就是说,如果你真正想做好 Redis 发布订阅权限控制,不能依赖 ACL 这一层,而应重点通过应用层鉴权、TLS 加密传输以及实例隔离来实现更可靠的安全控制。

Redis 原生并不支持基于频道级别的订阅权限管理,ACL 不能按照频道名称限制 SUBSCRIBE 行为——要真正实现 Redis 发布订阅权限控制,必须结合应用层拦截、TLS 加密和实例隔离三种方案共同落地。
为什么 ACL 的 &pattern 对 SUBSCRIBE 无效?
ACL 里的 &metrics:* 看起来像是可以匹配频道名称,但实际只有在 Redis 6.2+ 且启用 acl-pubsub-default 后才会生效;并且即便开启成功,它也只用于 PUBLISH 命令的频道权限校验,对 SUBSCRIBE 没有任何限制作用。实测结果包括:
ACL SETUSER reader on >pass ~* &user:123:* +SUBSCRIBE→ 订阅user:456:notify依然可以成功(说明&不参与SUBSCRIBE权限判断)ACL LIST虽然能看到规则已经存在,但SUBSCRIBE操作仍会完全绕过&的匹配逻辑- 唯一能够直接阻止订阅的 ACL 方式,是禁用命令本身:
-SUBSCRIBE,但这本质上等于把整个订阅功能一起关闭
怎样让不同用户只收到自己权限内的频道消息?
正确做法必须是在服务端完成权限鉴权,而不是单纯依赖 Redis 配置。常见实现流程如下:
- 客户端建立连接时携带
token,请求/api/v1/pubsub/channels - 后端解析 token,获取用户 ID 与角色信息,再查询数据库或缓存生成可订阅白名单,例如
["user:123:notify", "org:789:report"] - 客户端仅对白名单中的频道执行
SUBSCRIBE,同时禁止硬编码通用频道名,例如all或admin - 频道命名应当包含业务前缀与权限粒度,例如
org:789:report:update,方便后端按冒号分段提取org_id并完成权限校验
开启 TLS 是防止敏感信息泄露的底线
如果没有启用 TLS,SUBSCRIBE 与 PUBLISH 的频道名和消息内容都会以明文方式在网络中传输,中间节点可以轻易抓包获取数据。因此必须做到:
- 服务端开启
tls-port 6380,并正确配置tls-cert-file、tls-key-file、tls-ca-cert-file - 客户端通过
rediss://协议连接,并显式传入 CA 证书;如果使用自签名证书,则需设置ssl_cert_reqs=None - 关闭非 TLS 端口(注释掉
port 6379或通过防火墙 DROP),否则攻击者可能主动降级为明文连接
ACL 能真正起效的 Pub/Sub 场景只有两个
在 Redis Pub/Sub 场景中,ACL 真正有实际限制能力的操作主要只有两类:
+PUBLISH+&pattern:用于限制用户只能向符合 pattern 的频道发布消息,例如&order:*允许发送到order:123,但会拒绝发送到user:456acl-pubsub-default resetchannels(Redis 6.2+):默认拒绝所有频道访问,再通过&显式放行指定频道,避免误开放全量消息通道
需要注意的是,频道名称匹配使用的是 glob 模式,而不是正则表达式,因此 &logs:* 不会匹配 logs(因为没有冒号),也不会匹配 app:logs(因为前缀不一致),这一点在实际配置中非常容易被忽略。
