postgresql 源码客户端认证

本文深入解析了PostgreSQL数据库中的认证过程,包括客户端认证函数ClientAuthentication的实现细节,以及如何通过检查pg_hba.conf配置文件来确定认证方法。此外,还介绍了密码验证函数md5_crypt_verify的具体工作流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

--在使用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, roleid, 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;
}

### PostgreSQL 客户端下载与使用教程 #### 一. PostgreSQL 客户端概述 PostgreSQL 提供多种客户端工具用于连接和操作数据库。这些工具可以分为两类:命令行工具和图形化工具。 常见的命令行工具有 `psql`,它是 PostgreSQL 的默认交互式终端程序[^1]。对于需要更直观的操作体验的用户,可以选择安装第三方图形化客户端工具,比如 **pgAdmin** 或者通过 Python 库如 psycopg2 实现编程访问[^3]。 --- #### 二. 下载并安装 PostgreSQL 官方客户端 官方推荐的方式是从 PostgreSQL 官网获取最新版本的客户端软件包: 1. 访问官方网站 [https://www.postgresql.org/download/](https://www.postgresql.org/download/) 并选择适合您操作系统平台的链接。 2. 对于 Windows 用户,可以直接下载带有图形界面安装向导的一体化安装包;Linux 和 macOS 用户则可以通过包管理器或者源码编译方式完成安装。 例如,在 Ubuntu 上运行以下命令即可快速安装基础组件以及 psql 工具: ```bash sudo apt update && sudo apt install postgresql-client ``` --- #### 三. 配置环境变量以便全局调用 为了方便随时调用 `psql` 等命令行工具,请确认已将其路径添加到系统的 PATH 变量中。通常情况下,默认安装会自动处理此设置。如果没有生效,则手动编辑 `.bashrc` 文件(或其他 shell 初始化脚本),追加如下内容: ```bash export PATH=$PATH:/usr/lib/postgresql/<version>/bin/ source ~/.bashrc ``` 替换 `<version>` 为您实际安装的具体版本号。 --- #### 四. 使用 psql 连接到数据库实例 启动 psql 后可执行 SQL 查询语句以及其他元指令。基本语法结构如下所示: ```bash psql -h 主机地址 -p 端口号 -U 用户名 -d 数据库名称 ``` 假设目标是一个本地部署的标准配置服务,那么最简单的形式应该是这样的: ```bash psql -U postgres -d postgres ``` 如果遇到权限验证错误提示 “FATAL: Ident authentication failed”,可能是因为当前用户的认证方法未被允许。此时需调整服务器端配置文件 `/etc/postgresql/[version]/main/pg_hba.conf` 中对应条目改为支持密码校验模式 (`md5`) 而不是依赖 ident 协议: ``` local all postgres md5 host all all 127.0.0.1/32 md5 ``` 保存修改之后重启服务使更改立即生效: ```bash sudo service postgresql restart ``` --- #### 五. 图形化客户端——pgAdmin 的介绍与应用 除了上述提到的基础命令外,还有许多优秀的可视化应用程序可供选用,其中最为知名的就是 pgAdmin 。该产品不仅功能强大而且易于上手,特别适用于初学者学习阶段或是日常维护工作场景下频繁使用的场合。 要获得最新的稳定发行版,请前往其官网页面 [https://www.pgadmin.org/download/](https://www.pgadmin.org/download/) 查找针对不同 OS 版本优化后的分发包进行独立安装过程指导说明文档阅读完毕后再继续下一步骤动作之前先备份好重要数据以防万一丢失不可恢复情况发生哦! 一旦成功装载完成后打开主窗口界面上就会看到创建新连接选项卡位置所在处点击进入填写必要参数字段值提交建立关联关系即刻享受便捷高效的服务啦! --- #### 六. 利用 Vert.x MySQL/PostgreSQL 客户端实现异步通信 如果您正在开发基于 Java 或 Kotlin 的微服务架构项目,并希望集成高效的事件驱动框架解决方案的话,不妨考虑一下来自 Eclipse 组织旗下的开源项目 —— Vert.x 。它内置了专门面向这两种主流关系型存储引擎设计出来的专用模块能够很好地满足实时响应需求的同时还兼顾性能表现优异的特点[^2]。 下面给出一段简单示例代码展示如何初始化一个 PostgreSQL 数据池对象并通过查询接口检索记录列表返回给前端显示出来: ```java import io.vertx.core.Vertx; import io.vertx.sqlclient.PoolOptions; import io.vertx.sqlclient.SqlClient; public class Main { public static void main(String[] args) { PoolOptions options = new PoolOptions() .setMaxSize(5); SqlClient client = PgPool.pool( Vertx.vertx(), new JsonObject().put("url", "jdbc:postgresql://localhost/testdb") .put("user", "postgres") .put("password", "<your_password>"), options); String sqlQuery = "SELECT * FROM users"; client.query(sqlQuery).execute(ar -> { if (ar.succeeded()) { RowSet<Row> rows = ar.result(); System.out.println(rows.toJson()); } else { Throwable error = ar.cause(); System.err.println(error.getMessage()); } }); } } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值