【Redis源碼】Redis 6 ACL源碼詳解
簡(jiǎn)介
本文主要是講解Redis 6的ACL的實(shí)現原理?;臼褂迷斠?jiàn):Redis 6.0新特性——ACLs,以及Redis啟動(dòng)過(guò)程分析。
啟動(dòng)初始化
初始化默認用戶(hù)
ACL子模塊在Redis啟動(dòng)過(guò)程中初始化,下面代碼主要是初始化ACL的結構:
/*
* 初始化ACL子系統
* */
void ACLInit(void) {
Users = raxNew(); // 初始化用戶(hù)信息
UsersToLoad = listCreate();
ACLLog = listCreate();
ACLInitDefaultUser();
server.requirepass = NULL; /* Only used for backward compatibility. */
}
ACLInitDefaultUser函數主要是初始化默認用戶(hù),在Redis 6當中默認用戶(hù)的權限就相當于操作系統的管理員一樣,擁有很大的權限,要限制遠程使用默認用戶(hù)連接。
/* 初始化默認用戶(hù) */
void ACLInitDefaultUser(void) {
DefaultUser = ACLCreateUser("default",7);
ACLSetUser(DefaultUser,"+@all",-1); // 默認用戶(hù)賦予所有命令的權限
ACLSetUser(DefaultUser,"~*",-1);// 可以操作任何key
ACLSetUser(DefaultUser,"on",-1);// 默認開(kāi)啟
ACLSetUser(DefaultUser,"nopass",-1); // 默認不需要密碼
}
加載ACL用戶(hù)信息
ACL數據結構初始化完成之后,通過(guò)函數 ACLLoadUsersAtStartup加載Redis配置里面的ACL用戶(hù)信息。Redis ACL配置信息主要有兩種方式:
- 在redis.conf文件中通過(guò)user 配置項配置的ACL信息。比如:
user worker +@list +@connection ~jobs:* on >ffa9203c493aa99 - 在
redis.conf中配置aclfile所配置的文件中。格式如下圖所示:

通過(guò)user方式
通過(guò)加載redis.conf配置文件中讀取user配置項加載ACL信息。
int ACLLoadConfiguredUsers(void) {
listIter li;
listNode *ln;
listRewind(UsersToLoad,&li);
while ((ln = listNext(&li)) != NULL) {
sds *aclrules = listNodeValue(ln);
sds username = aclrules[0];
// 檢查ACL用戶(hù)名當中是否存在空格
if (ACLStringHasSpaces(aclrules[0],sdslen(aclrules[0]))) {
serverLog(LL_WARNING,"Spaces not allowed in ACL usernames");
return C_ERR;
}
// 創(chuàng )建ACL用戶(hù)
user *u = ACLCreateUser(username,sdslen(username));
if (!u) {
u = ACLGetUserByName(username,sdslen(username));
serverAssert(u != NULL);
ACLSetUser(u,"reset",-1);
}
/* Load every rule defined for this user. */
for (int j = 1; aclrules[j]; j++) {
// 添加當前用戶(hù)的所有屬性
if (ACLSetUser(u,aclrules[j],sdslen(aclrules[j])) != C_OK) {
char *errmsg = ACLSetUserStringError();
serverLog(LL_WARNING,"Error loading ACL rule '%s' for "
"the user named '%s': %s",
aclrules[j],aclrules[0],errmsg);
return C_ERR;
}
}
/* Having a disabled user in the configuration may be an error,
* warn about it without returning any error to the caller.
* 用戶(hù)沒(méi)有開(kāi)啟的時(shí)候打印到日志里面
* */
if (u->flags & USER_FLAG_DISABLED) {
serverLog(LL_NOTICE, "The user '%s' is disabled (there is no "
"'on' modifier in the user description). Make "
"sure this is not a configuration error.",
aclrules[0]);
}
}
return C_OK;
}
通過(guò)文件方式
ACLLoadFromFile函數就是從redis.conf配置的 aclfile所在的文件當中讀取ACL配置信息。
ACL 控制
ACL控制主要是在從命令表中獲取命令之后判斷當前登錄的用戶(hù)是否對當前執行的命令是否有權限。判斷的函數為:
int ACLCheckCommandPerm(client *c, int *keyidxptr)
具體判斷是否存在權限的函數為ACLGetUserCommandBit,主要實(shí)現如代碼,其中id表示當前命令所對應的id。
int ACLGetUserCommandBit(user *u, unsigned long id) {
uint64_t word, bit;
// 計算命令在allowed_commands當中對應的bit位
if (ACLGetCommandBitCoordinates(id,&word,&bit) == C_ERR) return 0;
return (u->allowed_commands[word] & bit) != 0;
}
評論
0 評論