redis.conf中使用requirepass不生效?

2023年 7月 15日 28.4k 0

本文剖析下遇到的一个问题,即"设置requirepass不生效"这个小问题,本文目录如下:

requirepass字段介绍

requirepass字段是redis.conf中的一个字段,可以看下redis.conf中的注释

# IMPORTANT NOTE: starting with Redis 6 "requirepass" is just a compatibility
# layer on top of the new ACL system. The option effect will be just setting
# the password for the default user. Clients will still authenticate using
# AUTH  as usually, or more explicitly with AUTH default 
# if they follow the new protocol: both will work.
#
# The requirepass is not compatable with aclfile option and the ACL LOAD
# command, these will cause requirepass to be ignored.
#
# requirepass foobared

即这个字段是用来设置默认用户default的密码的,用户可以通过auth 或者auth default 来认证,同时说明了不能跟aclfile兼容,如果启动acl,则该字段会被忽略,会使用acl文件中的default用户,如果没有配置default用户,则会新建一个nopass的default用户并使用,哈哈,这就是为什么redis.conf配置了requirepass而不生效的原因,提前说了。

如何启用requirepass

  • 启用redis.conf中的requirepass,改为自己的密码password,同时启用logfile,注意不要启用aclfile,否则会不生效
  • 启动redis-server ./redis.conf
  • redis-cli -h localhost -p 6379访问,发现需要进行认证,输入auth password或者auth default password即可进行访问了,默认登录用户就是default用户
  • default用户的密码就是requirepass配置的密码,在initServer中会调用ACLUpdateDefaultUserPassword(server.requirepass)函数设置default用户的密码
/* Set the password for the "default" ACL user. This implements supports for
 * requirepass config, so passing in NULL will set the user to be nopass. */
void ACLUpdateDefaultUserPassword(sds password) {
    ACLSetUser(DefaultUser,"resetpass",-1);
    if (password) {
        sds aclop = sdscatlen(sdsnew(">"), password, sdslen(password));
        ACLSetUser(DefaultUser,aclop,sdslen(aclop));
        sdsfree(aclop);
    } else {
        ACLSetUser(DefaultUser,"nopass",-1);
    }
}

至于为什么启用aclfile时会不生效,请继续看

启用requirepass时requirepass不生效?

现象

requirepass是default用户的密码,配置密码后,aclfile也启用时,修改redis.conf配置后重启redis后,redis-cli -h localhost -p port 无需认证仍然可以访问,即没有生效

看下redis.conf中注释可以知道跟aclfile是不兼容的,启用aclfile时,会忽略requirepass

原因

redis.conf中同时启用requirepass和aclfile,redis在加载配置时,会读取aclfile,重新新建全局Users对象,调用ACLInitDefaultUser函数重新新建nopass的default用户,先前已加载的defaultUser对象(密码从requirepass来)不会被用到,即default用户是nopass的,但是如果acl文件中配置了default用户以及配置了密码,则还是需要认证的

sds ACLLoadFromFile(const char *filename) {
      ...
    /* The default user pointer is referenced in different places: instead
         * of replacing such occurrences it is much simpler to copy the new
         * default user configuration in the old one. */
        user *new_default = ACLGetUserByName("default",7);
        if (!new_default) {
            new_default = ACLCreateDefaultUser();  // nopass的default用户
        }

        ACLCopyUser(DefaultUser,new_default);
        ACLFreeUser(new_default);
        raxInsert(Users,(unsigned char*)"default",7,DefaultUser,NULL);
        raxRemove(old_users,(unsigned char*)"default",7,NULL);
        ACLFreeUsersSet(old_users);
        sdsfree(errors);
        return NULL;
       ...
}

解决方法

  • 不启用aclfile,只使用requirepass,即只有default用户了
  • 启用aclfile,redis-cli登录后,用config set requirepass xxx,会生效,然后重新redis-cli登录访问即可,如果需要重启redis也生效,则进行acl save(会写default的user规则到aclfile中)

注意点:config set requirepass xxx会调用updateRequirePass函数,该函数会继续调用ACLUpdateDefaultUserPassword更新default用户的密码(nopass变为有密码状态),注意redis最新版本(7.0以上)只会在更新的内容发生变化时才会调用到updateRequirePass函数,如下面的sdsConfigSet函数,在内容有变化时才返回1

configSetCommand -> performInterfaceSet -> sdsConfigSet函数

performInterfaceSet会将sdsConfigSet函数返回值作为自己的返回值,

configSetCommand函数判断performInterfaceSet返回值,如果为1,则

会调用到updateRequirePass函数

  • 使用上还是直接使用aclfile即可,将requirepass注释掉,登录后新增用户,然后acl save

总结

本文主要介绍了如何启用requirepass,以及启用requirepass为什么不会生效,从代码层面分析了不生效的原因,是因为同时启用了aclfile导致requirepass中的密码不会被用到,最后介绍了解决方法,建议使用上直接使用aclfile即可。

相关文章

JavaScript2024新功能:Object.groupBy、正则表达式v标志
PHP trim 函数对多字节字符的使用和限制
新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
为React 19做准备:WordPress 6.6用户指南
如何删除WordPress中的所有评论

发布评论