Redis
6.0之前版本只提供了一个轻量级的访问控制功能,服务端可通过requirepass
命令设置密码,客户端只需通过auth命令输入密码,认证成功后,就拥有全量命令执行权限。
这种方式十分不安全,如:
KEYS
命令,引起Redis
的短时间阻塞,严重的甚至可能触发主从切换。FLUSHALL
命令,导致Redis
数据库被清空。针对场景1和场景2,一般可以通过rename-command
命令重命名或禁用这些危险函数。但是还有另外一个问题,即多个线上业务通常共用一个Redis
实例,可能会,当然也存在数据泄露风险。用户只通过rename-command
命令是防止不了自己的key
被其他用户访问的。
为了解决上述问题,Redis 6.0
开始引入了ACL(Access Control Lists)
权限控制机制,可以方便地。基于ACL
权限控制,Redis 6.0
可以设置多个用户,允许你以细粒度的方式管理用户对Redis
的访问权限。当然,ACL
是向上兼容的,默认在不做任何配置的情况下,所有客户端都拥有全量命令执行权限,且继续支持以requirepass
配置密码的方式进行鉴权。
ACL
概述ACL
可以对不同的用户设置命令权限或数据权限,这样就能避免有些用户因误操作而导致数据丢失或降低数据泄露的风险。ACL
相关的命令配置分为3部分:ACLS
规则(语法)、用户关联命令配置、用户关联数据配置。
ACL
ACL
是使用DSL(Domain Specific Language,领域专用语言)
来定义的。ACL
的配置方式有两种:
在redis.conf
文件中通过user
配置项指定ACL
配置。注意:Redis为保持兼容性,会默认创建一个default用户。示例如下:
user trumanwong on nopass ~* +@all
在上述配置中:
user
为关键词,ACL
配置必须以user
关键字开始。trumanwong
为用户设置的用户名,其后面的内容为ACL
规则描述。查看生效规则,可使用acl list
。可以看到,ACL
规则配置有两条,其中default
用户是默认的用户,是为了向上兼容老版本的Redis
。
127.0.0.1:6379> acl list
1) "user default on nopass sanitize-payload ~* &* +@all"
2) "user trumanwong on nopass sanitize-payload ~* resetchannels +@all"
在redis.conf
文件中通过aclfile
配置项把ACL
相关配置生成.acl
文件引入加载的配置文件。在配置文件中,aclfile
默认是不开启的。通过aclfile
引入配置项的示例如下:
$ cat redis.conf
...
aclfile /usr/local/redis/users.acl
...
$ cat users.acl
user default on nopass sanitize-payload ~* &* +@all
user test on sanitize-payload #8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92 ~* resetchannels +@all -@dangerous
注意:这两种方法互不兼容,因此Redis要求使用其中一种。官方更推荐使用
aclfile
模式,因为在redis.conf
中配置了权限之后需要重启Redis
服务,才能将配置的权限加载至Redis
服务;使用aclfile
模式,可以调用acl load
命令将aclfile
中配置的ACL权限热加载进环境中。
参数说明如下:
on
:启用用户,可以以该用户身份进行认证。off
:将用户设置为非活动状态,将无法以此用户身份登录。请注意,如果用户在连接已通过身份验证后被禁用(设置为off
),则连接将继续按预期工作。要同时终止旧连接,可以CLIENT KILL [USER username]
命令断开连接,或者使用 ACL DELUSER
命令删除用户,这将导致所有经过身份验证的已删除用户的连接都被断开。nopass
表示无须密码访问,即客户端不需要用auth
认证即可使用Redis
,如果需要配置密码,就需要解除nopass
状态,详解如下:
><password>
:将此密码添加到用户的有效密码列表中。例如,>mypass
将mypass
添加到有效密码列表中。该命令会清除用户的nopass
标记。每个用户可以有任意数量的有效密码。
<<password>
:从有效密码列表中删除此密码。若该用户的有效密码列表中没有此密码,则返回错误信息。
#<hash>
:将SHA-256 Hash
值添加到用户的有效密码列表中。将该Hash
值与为用户输入的密码的Hash
值进行比较。该命令允许用户将Hash
值存储在users.acl
文件中,而不是存储明文密码;仅接受SHA-256 Hash
值,因为密码Hash
值必须为64个字符且为小写的十六进制字符。
!<hash>
:从有效密码列表中删除该Hash
值。当不知道Hash
值对应的明文是什么时,此命令很有用。
nopass
:移除该用户已设置的所有密码,并将该用户标记为nopass
(无密码)状态,即使用任何密码都可以登录。resetpass
命令可以解除nopass
状态。
resetpass
:刷新允许的密码列表并删除*nopass
状态。在resetpass
后,用户没有关联的密码,并且如果不添加一些密码(或稍后将其设置为nopass
* ) ,则无法进行身份验证。
执行以下操作:resetpass
、resetkeys
、resetchannels
、allchannels
(如果设置了 acl-pubsub-default
)、off
、clearselectors
、-@all
。即可重置用户状态为初始状态。
其中,@all
为禁止或允许所有命令。其中@
符号不是所有命令都有。+@all
表示允许用户使用所有命令,-@all
表示禁止这个用户使用所有命令。具体命令如下:
+<command>
:将命令添加到用户可以调用的命令列表中。-<command>
:将命令从用户可以调用的命令列表中移除。+@<category>
:允许用户调用<category>
类别中的所有命令,有效类别为@admin
、@set
、@sortedset
等,通过调用命令ACL CAT
查看完整列表。特殊类别@all
表示所有命令,包括当前和未来版本中存在的所有命令。-@<category>
:禁止用户调用<category>
类别中的所有命令。+<command>|first-arg
:允许禁用命令的特定第一个参数。它仅在没有子命令的命令上受支持,并且不允许像 -SELECT|1
这样的负数形式,只能以+
开头的加法。此功能已被弃用,并且将来可能会被删除。allcommands
:+@all
的别名,包括当前存在的命令及将来通过模块加载的所有命令。nocommands
:-@all
的别名,禁止用户调用所有命令。~<pattern>
:添加可以在命令中提及的键模式,支持正则匹配模式,比如~*
允许所有键,~foo*
、~bar*
表示允许这个用户访问以foo
以及bar
开头的键。%R~<pattern>
:(Redis 7.0
及以上版本可用)添加指定的读取key模式。其行为类似于常规密钥模式,但仅授予读取与给定模式匹配的密钥的权限。有关详细信息,请参阅关键权限。%W~<pattern>
:(Redis 7.0
及以上版本可用)添加指定的写入键模式。其行为类似于常规密钥模式,但仅授予写入与给定模式匹配的密钥的权限。有关详细信息,请参阅关键权限。%RW~<pattern>
:(在 Redis 7.0
及更高版本中可用) 的别名~<pattern>
。allkeys
: 的别名~*
。resetkeys
:清空之前允许的所有键模式。比如resetkeys ~objects*
,客户端只能访问以objects
开头的键,而之前配置的所有键模式都将被resetkeys
命令清空。了解这些后,我们基本就能配置出一个较完整的ACL
规则。
接下来看一下客户端操作ACL
配置的常用命令:
ACL CAT [category]
:查看类别,如果不带参数调用,该命令将显示可用的 ACL
类别。如果给出类别名称,该命令将显示指定类别中的所有 Redis
命令。
127.0.0.1:6379> acl cat
1) "keyspace"
2) "read"
3) "write"
4) "set"
5) "sortedset"
6) "list"
7) "hash"
8) "string"
9) "bitmap"
10) "hyperloglog"
11) "geo"
12) "stream"
13) "pubsub"
14) "admin"
15) "fast"
16) "slow"
17) "blocking"
18) "dangerous"
19) "connection"
20) "transaction"
21) "scripting"
ACL DELUSER username [username ...]
:删除所有指定的ACL
用户,并终止所有通过该用户认证的连接。注意:特殊default
用户无法从系统中删除,这是每个新连接进行身份验证的默认用户。用户列表中可能包含不存在的用户名,此时不对不存在的用户执行任何操作。
127.0.0.1:6379> ACL DELUSER trumanwong
(integer) 1
ACL GENPASS
:创建密码
127.0.0.1:6379> ACL GENPASS
"46faf0cf16a5f032dde1dbb200517fb6346798440f98d97f6fb55c757e49f411"
GETUSER
:该命令返回指定用户定义的所有规则。
127.0.0.1:6379> ACL GETUSER trumanwong
1) "flags"
2) 1) "on"
2) "sanitize-payload"
3) "passwords"
4) 1) "8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92"
5) "commands"
6) "+@all"
7) "keys"
8) "~*"
9) "channels"
10) ""
11) "selectors"
12) (empty array)
HELP
:查看帮助
ACL LIST
:显示Redis
当前活动的 ACL
规则。返回的数组中每一行都定义了一个不同的用户,并且格式与 redis.con
文件或外部 ACL
文件中使用的格式相同,因此可以直接剪切并粘贴 ACL LIST
命令返回的内容到外部ACL
文件中。
1) "user default on nopass sanitize-payload ~* &* +@all"
2) "user test on sanitize-payload #8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92 ~* resetchannels +@all -@dangerous"
3) "user trumanwong on sanitize-payload #8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92 ~* resetchannels +@all"
ACL LOAD
:加载aclfile
,在aclfile
中修改活新增ACL
权限之后,ACL
权限不会立即生效。用户可以在Redis
命令行中执行acl load
命令,将该aclfile
中的权限加载至Redis
服务中。
ACL SAVE
:该命令会将当前定义的ACL
从Redis
内存保存到ACL
文件中。。
ACL SETUSER username [rule [rule ...]]
:设置用户访问规则,每次设置之后一定要使用ACL SAVE
命令将ACL
权限持久化到aclfile
中,避免丢失。使用方式如下:
ACL SETUSER <username>
:用户不存在,则按默认规则创建用户,如果用户存在,则不执行任何操作。ACL SETUSER <username> <rules>
:用户不存在,则按默认规则创建用户,并增加<rules>
;用户存在,则在原有规则上增加<rules>
。USERS
:显示 Redis ACL
系统中当前配置的所有用户名列表。
127.0.0.1:6379> ACL USERS
1) "default"
2) "test"
3) "trumanwong"
ACL WHOAMI
:返回当前连接进行身份验证所用的用户名。
127.0.0.1:6379> ACL WHOAMI
"default"
ACL LOG [count | RESET]
:该命令显示最近 ACL 安全事件的列表。可选参数count
指定要显示的日志数。默认情况下返回最近十条失败事件。指定RESET
参数会清除日志。
&<pattern>
:(在Redis 6.2
及更高版本中可用)添加用户可以访问的 Pub/Sub
通道的 glob
样式模式。可以指定多个通道模式。请注意,模式匹配仅针对PUBLISH
和提到的通道进行SUBSCRIBE
,而PSUBSCRIBE
需要其通道模式与用户允许的通道模式之间进行字面匹配。
allchannels
:&*
允许用户访问所有 Pub/Sub
频道的别名。
resetchannels
:刷新允许的通道模式列表,并断开用户的 Pub/Sub
客户端(如果这些客户端不再能够访问其各自的通道和/或通道模式)。
最后,AUTH
命令在Redis 6
中进行了扩展,新加了一个username
参数,示例如下:
AUTH <username> <password>
为兼容Redis
老版本,Redis 6.0
会默认创建一个default
用户,其密码是通过require-pass
配置项配置的。在客户端通过AUTH
进行鉴权认证时,Redis
的服务端会根据auth
传入参数分情况处理:
通过Redis ACL
,我们可以轻松地实现对Redis
数据库的访问控制,保护重要数据不受未经授权的访问,根据实际需求,精细地管理用户的权限,从而提高系统的安全性和稳定性。在设计和配置ACL
时,请确保平衡安全性和便利性,以确保系统的正常运行和良好的用户体验。