当前位置: 首页 > news >正文

PostgreSQL 练习 ---- psql 新增连接参数

目标

添加一个连接参数,默认为 false 。当 psql 连接时,若该连接参数非 “true” 时,用户 “u1“ 对表对象无操作权限,包括自己拥有的表。

连接机制简介

连接过程如下所述:

  • 客户端初始化一个空连接,设置连接状态为 CONNECTION_NEEDED 。
  • 然后创建 socket,与服务端建立 tcp 连接,状态设置为 CONNECTION_STARTED ,检查 socket 连接是否正常。
  • 初始化连接中的 socket 地址,修改连接状态为 CONNECTED_MODE 。
  • 给服务端发送协议号等信息,发送启动包给服务端后,设置状态为 CONNECTION_AWAITING_RESPONSE 。
  • 处理身份验证交换,等待 postmaster 消息并根据需要作出响应,最终设置状态为 CONNECTION_AUTH_OK。(后续过程再次不再细述,有兴趣可以自己查资料进行学习)。

我们重点关注启动包,因为参数的发送、解析都是通过启动包完成。启动包不止包含了连接协议,还包含了些连接选项等信息( dbname、user 等)。此次连接参数的发送解析就在启动包中。

实现

此处以添加 conninfo 为例:

确定标志为 priv_flag,默认为 false ,并设置为全局变量。确定连接参数为 char* 型的变量 privilege_flag 。

定义全局变量 priv_flag

在 src/backend/utils/init/globals.c 文件中定义

bool priv_flag = false;

并在 src/include/miscadmin.h 中声明此变量

extern bool priv_flag;

在 Port 和 conn 结构体中添加字段

主要目的是在建立连接的过程中,对该参数的赋值发送和接受,进行处理。pg_conn 为客户端存储连接状态结构体,Port 为服务端相关联结构体。

在 src/include/libpq/libpq-be.h 文件的 Port 结构体中添加 privilege_flag 字段:

char        *privilege_flag;

src/interfaces/libpq/libpq-int.h 文件中 pg_conn 结构体同理添加:

char        *privilege_flag;

在 conninfo 中添加 privilege_flag

psql 首先会对命令行 -选项 的命令进行解析,未匹配的“”引号里面的信息,会在客户端填充第一包数据之前,进行解析,此时依赖的就是 conninfo 结构体,去进行匹配。

在 src/interfaces/libpq/fe-connect.c 文件中定义的结构体 PQconninfoOptions 中添加新添参数信息。

internalPQconninfoOption 结构体定义 conninfo 参数及其回退资源。

添加新参数信息至倒数第二个成员,因最后一个为全NULL,遍历时到此停止。

	{"privilege_flag", "PRIVILEGE_FLAG", NULL, NULL,"Privilege-Flag", "", 8, /* sizeof("true") = 5 or sizeof("false") = 6 */offserof(struct pg_conn, privilege_flag)},

用以参数解析时进行匹配。

在客户端填充启动包数据

在 src/interfaces/libpq/fe-protocol3.c 文件 build_startup_packet 函数中添加相关代码。对 privilege_flag 参数的值进行填充。

	if (conn->privilege_flag && conn->privilege_flag[0])ADD_STARTUP_OPTION("privilege_flag", conn->privilege_flag);

服务端解析启动包

在 src/backend/postmaster/postmaster.c 文件的 ProcessStartupPacket 函数对第一包数据进行解析。

当读取到 privilege_flag 参数,且值为 true 时,置全局变量 priv_flag 为 true ,否则继续使用默认值。

	else if(strcmp(nameptr, "privilege_flag") == 0){port->privilege_flag = pstrdup(valptr);if(strcmp("true",port->privilege_flag) == 0){priv_flag = true;}}

设置权限检查判断

在 src/backend/catalog/aclchk.c 文件的 pg_class_aclmask 函数中,对权限检查增加逻辑判断。

当前用户为“u1”,且全局变量 priv_flag 为 false 时,在权限检查这块“去除”该用户对表对象的 insert/update/delete/truncate 权限(前提是 u1 拥有该表的这些权限)。即通过 privilege_flag 连接参数控制 u1 用户的权限。

	if(strcmp(GetUserNameFromId(roleid, false), "u1") == 0 && !priv_flag){mask &= ~(ACL_INSERT | ACL_UPDATE | ACL_DELETE | ACL_TRUNCATE);ReleaseSyscache(tuple);return mask;}

测试验证

  1. 首先使用 postgres 用户登录数据库,创建 u1 用户
create user u1 with password '1qaz!QAZ';
  1. 然后创建 public 表 test ,并赋其所有权限给 u1 用户
create table public.test (id int);
insert into test values (1),(2),(3),(4),(5);
grant all ON test to u1 ;
  1. 通过 pg_class 表查看 u1 用户对表 test 的权限
    在这里插入图片描述
select relname,relacl from pg_class where relname = 'test';
  1. 使用 u1 用户进行登录。因当使用 -d、-U 参数时,“”里面的参数就会被忽略,所以使用全 conninfo 的方式进行登录。
    首先不使用 privilege_flag 参数进行连接,进行 select/insert 操作
    在这里插入图片描述
    可以看到 select 权限正常,insert 操作提示没有权限。
    接下来使用 privilege_flag=true 进行连接,再次进行 select/insert 操作:在这里插入图片描述
    可以看到,此时 insert 操作正常。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • SpringBoot中整合Mybatis
  • 自定义实现一个 Redis 客户端
  • coze 卡片使用
  • 基于k8s集群的redis-cluster集群
  • 计算机,人工智能选题
  • 自动驾驶大模型算法助力端到端顺利落地
  • Δ-Σ ADC选型时噪声性能实例详解
  • Java元组Tuple的使用
  • Qt 哈希加密之 QCryptographicHash
  • 泛微OA流程接口调用工具类
  • SpringBoot的Web开发
  • 护眼大路灯哪个牌子好?公认五款最好护眼大路灯分享
  • C++ 特性之vector详解 + 联合opencv使用
  • 数据库方式实现实时排行榜
  • http参数污染利用php小特性绕过贷齐乐waf
  • 【159天】尚学堂高琪Java300集视频精华笔记(128)
  • 10个确保微服务与容器安全的最佳实践
  • C语言笔记(第一章:C语言编程)
  • Iterator 和 for...of 循环
  • JavaScript函数式编程(一)
  • java小心机(3)| 浅析finalize()
  • Linux gpio口使用方法
  • Node项目之评分系统(二)- 数据库设计
  • puppeteer stop redirect 的正确姿势及 net::ERR_FAILED 的解决
  • Python连接Oracle
  • SegmentFault 2015 Top Rank
  • vagrant 添加本地 box 安装 laravel homestead
  • 表单中readonly的input等标签,禁止光标进入(focus)的几种方式
  • 对象管理器(defineProperty)学习笔记
  • 老板让我十分钟上手nx-admin
  • 与 ConTeXt MkIV 官方文档的接驳
  • 这几个编码小技巧将令你 PHP 代码更加简洁
  • 正则学习笔记
  • 京东物流联手山西图灵打造智能供应链,让阅读更有趣 ...
  • ​你们这样子,耽误我的工作进度怎么办?
  • # 移动硬盘误操作制作为启动盘数据恢复问题
  • #宝哥教你#查看jquery绑定的事件函数
  • #我与Java虚拟机的故事#连载07:我放弃了对JVM的进一步学习
  • $forceUpdate()函数
  • %3cli%3e连接html页面,html+canvas实现屏幕截取
  • (1)svelte 教程:hello world
  • (12)Linux 常见的三种进程状态
  • (附源码)springboot工单管理系统 毕业设计 964158
  • (介绍与使用)物联网NodeMCUESP8266(ESP-12F)连接新版onenet mqtt协议实现上传数据(温湿度)和下发指令(控制LED灯)
  • (蓝桥杯每日一题)love
  • (六)DockerCompose安装与配置
  • (论文阅读30/100)Convolutional Pose Machines
  • (贪心) LeetCode 45. 跳跃游戏 II
  • (一)springboot2.7.6集成activit5.23.0之集成引擎
  • (译) 理解 Elixir 中的宏 Macro, 第四部分:深入化
  • (转)Android学习系列(31)--App自动化之使用Ant编译项目多渠道打包
  • (转)菜鸟学数据库(三)——存储过程
  • (转)自己动手搭建Nginx+memcache+xdebug+php运行环境绿色版 For windows版
  • ... fatal error LINK1120:1个无法解析的外部命令 的解决办法
  • ..thread“main“ com.fasterxml.jackson.databind.JsonMappingException: Jackson version is too old 2.3.1