背景
因为工作的一些场景,想到一个问题,在不重启redis的情况下,使用config set修改密码,修改成功后,已经建立的长连接在执行需要认证的命令时,会不会报错
实验
带着问题,我们进行了实验,正常进入,执行命令:
root@3b9d47d51ffc:/data# redis-cli
127.0.0.1:6379>
127.0.0.1:6379>
127.0.0.1:6379> auth 123456
OK
127.0.0.1:6379> get key
"value"
新开一个窗口修改密码
root@3b9d47d51ffc:/# redis-cli
127.0.0.1:6379> auth 123456
OK
127.0.0.1:6379> config set requirepass 654321
OK
127.0.0.1:6379> config get requirepass
1) "requirepass"
2) "654321"
可以看到密码已经修改成功了,我们继续在刚在的窗口执行命令
root@3b9d47d51ffc:/data# redis-cli
127.0.0.1:6379>
127.0.0.1:6379>
127.0.0.1:6379> auth 123456
OK
127.0.0.1:6379> get key
"value"
127.0.0.1:6379> get key
"value"
127.0.0.1:6379> get key
"value"
127.0.0.1:6379> get key
"value"
127.0.0.1:6379> get key
"value"
127.0.0.1:6379>
可以看到仍然可以正常执行命令。
源码探究
阅读redis源码,我们发现在执行成功auth命令之后,server把这个客户端对象中的一个是否认证的标识设置为1
void authCommand(client *c) {
if (!server.requirepass) {
addReplyError(c,"Client sent AUTH, but no password is set");
} else if (!time_independent_strcmp(c->argv[1]->ptr, server.requirepass)) {
c->authenticated = 1;
addReply(c,shared.ok);
} else {
c->authenticated = 0;
addReplyError(c,"invalid password");
}
}
然后再processCommand函数里面,只会对这个表示进行验证,不会重新校验密码
/* Check if the user is authenticated */
if (server.requirepass && !c->authenticated && c->cmd->proc != authCommand)
{
flagTransaction(c);
addReply(c,shared.noautherr);
return C_OK;
}
另外,在configSetCommand函数里面(config set requirepass实际执行的内容),修改密码只是修改了全局变量的值,并没有重置会话内变量的操作。
config_set_special_field("requirepass") {
if (sdslen(o->ptr) > CONFIG_AUTHPASS_MAX_LEN) goto badfmt;
zfree(server.requirepass);
server.requirepass = ((char*)o->ptr)[0] ? zstrdup(o->ptr) : NULL;
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。