postgresql 源码客户端认证
发布时间:2020-12-13 17:09:54 所属栏目:百科 来源:网络整理
导读:--在使用pg中登陆数据库是第一步,其代码结构如下:--原始代码在如下文件中src/backend/libpq/auth.c--其入口函数为ClientAuthentication,其接受一个Port结构体voidClientAuthentication(Port *port){ --通过此函数解析客户的ip类型,确定其使用的是什么样
--在使用pg中登陆数据库是第一步,其代码结构如下: --原始代码在如下文件中 src/backend/libpq/auth.c --其入口函数为ClientAuthentication,其接受一个Port结构体 void ClientAuthentication(Port *port) { --通过此函数解析客户的ip类型,确定其使用的是什么样的方式进行认证,比如能过local还是ip,是md5还是trust认证等 -- hba_getauthmethod 会调用函数 check_hba() hba_getauthmethod(port); CHECK_FOR_INTERRUPTS(); --匹配pg的认证方法,比如我们最常用的md5 switch (port->hba->auth_method) { case uaReject: case uaMD5: if (Db_user_namespace) ereport(FATAL,(errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),errmsg("MD5 authentication is not supported when "db_user_namespace" is enabled"))); --提示用户输入密码并对用户输入的密码进行加密 sendAuthRequest(port,AUTH_REQ_MD5); --比较用户输入的密码与数据库中存在的密码是否一致,其会调用md5_crypt_verify函数 status = recv_and_check_password_packet(port,&logdetail); break; } --检查系统中中是否有hook,如果有,则调用 if (ClientAuthentication_hook) (*ClientAuthentication_hook) (port,status); --判断用户认证是否成功 if (status == STATUS_OK) sendAuthRequest(port,AUTH_REQ_OK); else --如果认证失败,则发送失败信息给客户端 auth_failed(port,status,logdetail); } --通过check_hba函数的foreach可知,pg是从上往下匹配pg_hba.conf的文件内容,如果为满足则其返回 --故在pg_hba.conf上面的认证方式如果与下面的认证方式会覆盖下面的认证方式 static void check_hba(hbaPort *port) { Oid roleid; ListCell *line; HbaLine *hba; /* Get the target role's OID. Note we do not error out for bad role. */ roleid = get_role_oid(port->user_name,true); --一行一行的对比pg_hba.conf的内容,直到匹配 foreach(line,parsed_hba_lines) { hba = (HbaLine *) lfirst(line); /* Check connection type */ if (hba->conntype == ctLocal) { if (!IS_AF_UNIX(port->raddr.addr.ss_family)) continue; } else { do something; } /* != ctLocal */ /* Check database and role */ if (!check_db(port->database_name,port->user_name,roleid,hba->databases)) continue; if (!check_role(port->user_name,hba->roles)) continue; /* Found a record that matched! */ port->hba = hba; return; } /* If no matching entry was found,then implicitly reject. */ hba = palloc0(sizeof(HbaLine)); hba->auth_method = uaImplicitReject; port->hba = hba; } --比较用户输入的密码与数据库中存在的密码是否一致 int md5_crypt_verify(const Port *port,const char *role,char *client_pass,char **logdetail) { --根据用户名,获取系统缓存的数据库密码 datum = SysCacheGetAttr(AUTHNAME,roleTup,Anum_pg_authid_rolpassword,&isnull); if (isnull) { ReleaseSysCache(roleTup); *logdetail = psprintf(_("User "%s" has no password assigned."),role); return STATUS_ERROR; /* user has no password */ } shadow_pass = TextDatumGetCString(datum); --比较密码是否相同 if (strcmp(crypt_client_pass,crypt_pwd) == 0) { /* * Password OK,now check to be sure we are not past rolvaliduntil */ if (isnull) retval = STATUS_OK; else if (vuntil < GetCurrentTimestamp()) { *logdetail = psprintf(_("User "%s" has an expired password."),role); retval = STATUS_ERROR; } else retval = STATUS_OK; } return retval; } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |