Redis 6 之后可以有多个用户,每个用户有自己的密码、可访问的 key 和可执行的命令。这篇不讲概念清单,直接在本机起一个实例,建用户、登录、被拒、改权限、删用户、重启,看每一步服务端真实的回答。
> ACL WHOAMI "default" > ACL LIST 1) "user default on nopass sanitize-payload ~* &* +@all" > ACL USERS 1) "default"
默认只有一个 default 用户:on nopass ~* &* +@all。所以「没设密码的 Redis」不是没有访问控制,而是访问控制里唯一的用户对所有人开放。
> ACL SETUSER alice on >secret123 ~app:* +get +set
"OK"
> ACL GETUSER alice
1) "flags"
2) 1) "on"
2) "sanitize-payload"
3) "passwords"
4) 1) "fcf730b6d95236ecd3c9fc2d92d7b6b2bb061514961aec041d6c7a7192f592e4"
5) "commands"
6) "-@all +get +set"
7) "keys"
8) "~app:*"
9) "channels"
10) ""
11) "selectors"
12) (empty array)
> AUTH alice secret123
"OK"
> ACL WHOAMI
(error) NOPERM User alice has no permissions to run the 'acl|whoami' command
> SET app:1 v
"OK"
> GET app:1
"v"
> GET other:1
(error) NOPERM No permissions to access a key
> SET other:1 v
(error) NOPERM No permissions to access a key
> DEL app:1
(error) NOPERM User alice has no permissions to run the 'del' command
> PING
(error) NOPERM User alice has no permissions to run the 'ping' command
> KEYS *
(error) NOPERM User alice has no permissions to run the 'keys' command
> ACL LIST
(error) NOPERM User alice has no permissions to run the 'acl|list' command新建用户默认 -@all:连 PING 都不行,要什么权限显式给什么。连 ACL WHOAMI 都需要单独授权(上面 alice 就被拒了)。key 越权和命令越权的报错不同:key 报 No permissions to access a key(不说是哪个 key),命令报 User alice has no permissions to run the 'del' command。
user alice on sanitize-payload #fcf730b6d95236ecd3c9fc2d92d7b6b2bb061514961aec041d6c7a7192f592e4 ~app:* resetchannels -@all +get +set
sha256("secret123") = fcf730b6d95236ecd3c9fc2d92d7b6b2bb061514961aec041d6c7a7192f592e4
ACL LIST 里的哈希与之相同: TrueACL 里只存 SHA-256 哈希(# 开头),上面把明文的 SHA-256 算出来逐字符比对是一致的。注意这是一次不加盐的快速哈希——它防的是「配置文件/ACL 文件被看到时直接读出明文」,不是防离线暴力破解;密码要够长够随机。(加盐与否是从「哈希与 sha256 一致」这个结果推出来的:一致说明没有加盐。)
> AUTH alice secret123 "OK" > ACL SETUSER alice off "OK" alice off 之后,已登录的连接 c1 继续发命令: > SET app:2 v "OK" alice off 之后,新连接登录: > AUTH alice secret123 (error) WRONGPASS invalid username-password pair or user is disabled. > ACL SETUSER alice on "OK" > AUTH alice secret123 "OK" > ACL DELUSER alice (integer) 1 DELUSER 后 c3 继续发命令:连接已被服务端断开 EOFError
off 只阻止新的登录,已登录的连接照常工作;DELUSER 会断开该用户的连接。所以「禁用某个泄露了密码的账号」应当用 DELUSER(或者 off 之后再 CLIENT KILL USER alice——这一条本文没有验证)。
> ACL SETUSER bob on >pw ~* +@all "OK" > AUTH bob pw "OK" > SET k 1 "OK" > ACL SETUSER bob -set "OK" > SET k 2 (error) NOPERM User bob has no permissions to run the 'set' command > GET k "1"
即时生效:不需要用户重新登录。撤销的是命令 -set,GET 不受影响。
> ACL SAVE "OK" users.acl 内容: user bob on sanitize-payload #30c952fab122c3f9759f02a6d95c3758b246b4fee239957b2d4fee46e26170c4 ~* resetchannels +@all -set user default on nopass sanitize-payload ~* &* +@all > ACL USERS 1) "bob" 2) "default" > ACL SETUSER carol on nopass ~* +@all "OK" > ACL SAVE (error) ERR This Redis instance is not configured to use an ACL file. You may want to specify users via the ACL SETUSER command and then issue a CONFIG REWRITE (assuming you have a Redis configuration file set) in order to store users in the Redis configuration. 没有 aclfile 的实例重启后: > ACL USERS 1) "default"
要让用户在重启后还在,用 aclfile 指定文件并执行 ACL SAVE(文件里每行一个用户,密码是哈希)。不配 aclfile 时 ACL SAVE 直接报错,重启后用 ACL SETUSER 建的用户消失。报错信息建议改用 CONFIG REWRITE 存进配置文件——那条路本文没有验证。