前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Redis源码】Redis 6 ACL源码详解

【Redis源码】Redis 6 ACL源码详解

作者头像
zeekling
发布2022-08-26 19:56:44
5480
发布2022-08-26 19:56:44
举报

简介

本文主要是讲解Redis 6的ACL的实现原理。基本使用详见:Redis 6.0新特性——ACLs,以及Redis启动过程分析

启动初始化

初始化默认用户

ACL子模块在Redis启动过程中初始化,下面代码主要是初始化ACL的结构:

/* 
 * 初始化ACL子系统
 * */
void ACLInit(void) {
    Users = raxNew(); // 初始化用户信息
    UsersToLoad = listCreate();
    ACLLog = listCreate();
    ACLInitDefaultUser();
    server.requirepass = NULL; /* Only used for backward compatibility. */
}

ACLInitDefaultUser函数主要是初始化默认用户,在Redis 6当中默认用户的权限就相当于操作系统的管理员一样,拥有很大的权限,要限制远程使用默认用户连接。

/* 初始化默认用户 */
void ACLInitDefaultUser(void) {
    DefaultUser = ACLCreateUser("default",7);
    ACLSetUser(DefaultUser,"+@all",-1); // 默认用户赋予所有命令的权限
    ACLSetUser(DefaultUser,"~*",-1);// 可以操作任何key
    ACLSetUser(DefaultUser,"on",-1);// 默认开启
    ACLSetUser(DefaultUser,"nopass",-1); // 默认不需要密码
}

加载ACL用户信息

ACL数据结构初始化完成之后,通过函数 ACLLoadUsersAtStartup加载Redis配置里面的ACL用户信息。Redis ACL配置信息主要有两种方式:

  • 在redis.conf文件中通过user 配置项配置的ACL信息。比如:user worker +@list +@connection ~jobs:* on >ffa9203c493aa99
  • redis.conf中配置aclfile所配置的文件中。格式如下图所示:
通过user方式

通过加载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用户名当中是否存在空格
        if (ACLStringHasSpaces(aclrules[0],sdslen(aclrules[0]))) {
            serverLog(LL_WARNING,"Spaces not allowed in ACL usernames");
            return C_ERR;
        }
        // 创建ACL用户
        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++) {
            // 添加当前用户的所有属性
            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.
         * 用户没有开启的时候打印到日志里面
         * */
        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;
}
通过文件方式

ACLLoadFromFile函数就是从redis.conf配置的 aclfile所在的文件当中读取ACL配置信息。

ACL 控制

ACL控制主要是在从命令表中获取命令之后判断当前登录的用户是否对当前执行的命令是否有权限。判断的函数为:

int ACLCheckCommandPerm(client *c, int *keyidxptr) 

具体判断是否存在权限的函数为ACLGetUserCommandBit,主要实现如代码,其中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;
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020.11.22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简介
  • 启动初始化
    • 初始化默认用户
      • 加载ACL用户信息
        • 通过user方式
        • 通过文件方式
    • ACL 控制
    相关产品与服务
    云数据库 Redis
    腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档