加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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;
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读