PostgreSQL中的密码验证方法
假设您想在客户端/服务器协议中实现密码身份验证方法。 您将如何做到这一点以及可能出现的问题是什么? 以下是 PostgreSQL 中如何完成此操作的故事。
password
一开始,PostgreSQL 只有 pg_hba.conf 中现在称为“password”的方法。 这是你能想象到的最简单的事情:
1.客户端对服务器说:“你好,我是 Peter,我想要连接。”
2.服务器回复:“你的密码是什么?”
3.客户端提示输入密码或从其他地方获取密码并响应:“这是‘123456’。”
4.现在服务器查找实际密码。 它存储在系统目录 pg_authid 列 rolpassword 中。 服务器基本上执行 strcmp(pg_authid.rolpassword, “123456”),如果相等,它会向客户端说“OK”,会话启动将继续。
这种方法有一些明显的问题:
•密码通过网络线路以明文形式传输。 有一些外部方法可以解决这个问题,例如使用 SSL 或其他加密封装。
•密码以明文形式存储在系统目录中,最终存储在磁盘上。 这很糟糕,因为它允许数据库和系统管理员看到其他用户的密码。 当然,人们不应该重复使用密码,但事实上人们可能会这样做。 它还可以允许管理员通过使用密码以其他用户身份登录来绕过审核。 一般来说,存在明文密码是不好的,因为它最终可能会被复制或意外看到。 最好不要这样做。
•更微妙的是,密码以明文形式存在于服务器进程的内存中。 为什么这么糟糕? 因为管理员也可能可以在那里访问它。 此外,如果服务器核心转储或交换,明文密码可能最终会出现在磁盘上的某个位置。 因此,这实际上几乎与在磁盘存储中以明文形式保存密码一样糟糕。
crypt
于是又尝试了另一种方法。这是在pg_hba.conf中不再支持的“crypt”认证方式。
1.客户端再次开始:“你好,我是 Peter,我想连接。”
2.已配置为使用 crypt 方法的服务器响应:“请告诉我使用盐(salt)'ab’对你的密码进行crypt()加密后的值?” 每次连接尝试都会随机选择salt干扰串。
3.客户端获取用户的输入内容并计算 crypt(“123456”, “ab”)然后回复:“这是‘ab01FAX.bQRSU’。”
4.服务器检查 crypt(pg_authid.rolpassword, “ab”) 是否等于“ab01FAX.bQRSU”,如果是则回复“OK”。
crypt() 是一个常见且随时可用的 Unix 函数,用于进行加密,因此它是在此处使用的明显选择。 它解决了以明文形式传输密码的问题,但仍然存在一些现有问题和新问题:
•密码仍以明文形式保存在系统目录和存储中。
•原始 crypt() 使用的加密方法现已过时。 同样,盐值长度salt(2 个字节)也已过时。
•因此,类 Unix 操作系统的不同供应商已扩展了 crypt() 的调用以使用不同的加密算法,但这是以不兼容的方式完成的。crypt() 只用于加密本地使用的密码(就像最初的用途一样)是可以的,但是当您想通过网络在不同系统之间进行通信时,它就会崩溃。
•crypt() 可能在非 Unix 系统上不可用。 虽然可以提供替代品,但如果需要这样做的话,就会对使用操作系统中现成的设施的原始前提产生疑问。
md5
到此时,PostgreSQL 已经支持 SSL,因此线传输过程中的明文问题不再那么重要。 真正让人烦恼的是系统目录中的明文密码。 因此设计了一个新系统,在pg_hba.conf中称为“md5”。 它的工作原理如下:
1.客户端:“你好,我是 Peter,我想连接。”
2.服务器:“请告诉我使用盐(salt)'abcd’对你的密码进行MD5哈希后的值?” 同样,每次连接尝试时都会随机选择盐。
3.客户端获取用户输入并计算:md5(md5(“123456” + “peter”) + “abcd”)。 (我在这里使用 + 进行字符串连接。)这里,“123456”是用户输入的密码,“peter”是用户名,“abcd”是盐值。 然后客户端回复:“这是‘301eddd34d997f72bd43ba678e36a5ba’。”
4.服务器检查 md5(pg_authid.rolpassword + “abcd”) 是否等于“301eddd34d997f72bd43ba678e36a5ba”,如果是则回复“OK”。
那么这方法有什么问题呢?
•现在读到这里,使用 MD5 显然是一个危险信号。 哈希方法已过时。
•盐值salt的长度(4 字节)也已过时。
•用户名被用作存储的哈希密码的盐值。 (这是为了确保两个恰好具有相同密码的用户不会具有相同的存储哈希值。)因此,重命名用户会使存储的哈希密码失效,并且需要分配新密码。 这可能并不常见,但发生时仍然很烦人。
•如果有人碰巧从系统目录(或者可能是备份转储)中获取了存储的哈希密码的副本,他们可以使用这些密码进行登录。您不需要实际的密码。 例如,在上面的步骤 3 中,客户端可以在不知道“123456”的情况下只发送 md5(“我找到的哈希值”+“abcd”)。 (你不能使用库存 libpq 来做到这一点,但制作一个可以做到这一点的自定义版本对于专门的攻击者来说并不难。)
这里的教训是:不要设计自己的加密方法。
scram
因此,所有这些问题都必须重新考虑,目前的解决方案是在 PostgreSQL 10引入的使用公共标准的:SASL(RFC 4422)和 SCRAM(RFC 5802 和 RFC 7677)。
SASL 是一个协议框架,允许客户端和服务器协商身份验证机制。 这在电子邮件中被广泛使用:SMTP 或 IMAP 服务器可能提供名称为 PLAIN、LOGIN、CRAM-MD5 或 DIGEST-MD5 的身份验证机制,或许还有 SCRAM,尽管这种情况似乎较少见。 PostgreSQL 使用 SASL 的原因主要是因为 SCRAM 是通过 SASL 定义的,因此遵循它是有意义的。 否则 SASL 功能不会向用户公开。
SCRAM 是一种身份验证机制。 它实际上是一组身份验证机制,具有不同的可能的哈希算法。 当最初考虑在 PostgreSQL 中实现 SCRAM 时,大多数以前的 SCRAM 使用都采用 SHA-1,但它已经过时了,并且在撰写本文时也已被弃用,就像 MD5 一样。 所以PostgreSQL目前使用的算法是SHA-256,认证方式的全称是SCRAM-SHA-256。
整个过程大致如下,传输过程中的数据格式如下:
1.客户端:“你好,我是 Peter,我想连接。”
2.服务器:“我们将进行 SASL 身份验证。 选择以下方法之一:SCRAM-SHA-256”。 (目前只有一种方法,除非提供通道绑定,但为了简单起见,我在这篇博文中忽略了这一点。)
3.客户端:“我选择 SCRAM-SHA-256。 这是第一个 SASL 数据:n,n=peter,r=rOprNGfwEbeRWgbNEkqO“。 该数据根据 SCRAM 规范进行组装并封装在 SASL 协议消息中。 这里,“n=”字段包含用户名,“r=”字段包含base64编码的随机字符串。 前面的内容与通道绑定有关,我们在这里忽略它。
4.服务器:“这是一些 SASL 数据:r=rOprNGfwEbeRWgbNEkqO%hvYDpWUa2RaTCAfuxFIlj)hNlF$k0,s=W22ZaJ0SNY7soEsUEjb6gQ==, i=4096”。 “r=”字段包含客户端的随机数据以及服务器附加的附加随机数据。 此外,服务器还发送盐值 (s=) 和交互计数 (i=),这是从相关用户存储的密码中获取的。
5.客户端:“这是一些 SASL 数据:c=biws,r=rOprNGfwEbeRWgbNEkqO%hvYDpWUa2RaTCAfuxFIlj)hNlF$k0, p=dHzbZapWIk4jUhN+Ute9ytag9zjfMHgsqmmiz7AndVQ=”。 “r=”字段与之前相同。 客户端和服务器只需来回发送此消息以检查它们是否仍在与正确的对方进行通信。 “p=”字段是客户端用户提供的密码,然后使用提供的盐值和迭代计数以特定方式对其进行哈希处理。 “c=”字段用于通道绑定。
6.服务器现在会根据本地存储的数据检查此数据。 其详细内容在此省略。 如果满足,则发回:“这是最终的 SASL 数据:v=6rriTRBi23WpRR/wtup+mMhUZUn/dB5nLTJRsjl95G4=”。 这称为验证器,允许客户端检查服务器是否确实检查了密码,而不仅仅是让每个人都通过。
7.然后客户端检查验证器,如果满足条件,则会话可以继续进行。
这里涉及很多内容。这解决了我们之前讨论的所有问题,甚至包括我们还没有考虑到的一些问题:
•密码不会以明文形式传输到网络中。
•密码在系统目录或底层存储中不是明文形式。
•密码在服务器进程中永远不会以明文形式存在。 实际上,明文密码从未离开客户端。客户端以一定的方式对其进行哈希处理,服务器将其与已有的哈希信息进行比较,但服务器永远不会看到实际的密码。
•客户端发送的任何信息都不能被其他任何人用来登录,即使整个交换过程被捕获。 这是因为客户端和服务器在每次连接尝试中都使用不同的随机数据。
•每个存储的密码都使用不同的盐值进行哈希处理,因此实际上不存在不同用户存储的密码意外相同的风险。 此外,盐值与用户名或用户的其他属性无关。
•盐长度可以轻松改变。 用户只需使用不同的盐值创建新密码即可。
•可以以系统化的方式将算法添加到此设计中。 请注意,这仍然需要更改软件,并且不会完全轻松,但至少有一个明确的方法可以做到这一点。
•正如上面第7点提到的,客户端可以验证服务器是否确实检查了密码。 在客户端/服务器身份验证中,我们通常主要考虑服务器试图阻止未经授权的客户端连接。 这是因为服务器存储了未经授权的客户端可能想要获取的有价值的数据。 但相反的情况也可能发生:客户端连接到伪造的服务器并向其发送服务器不应该获得的有价值的数据。 这样的服务器会很高兴地让任何碰巧连接的客户端进入,而不实际检查密码。 SCRAM 可以防止这种情况发生。 显然,SSL/TLS 是一种更复杂、更完整的解决方案,用于检查网络中的节点是否值得信赖,SCRAM 并不意味着消除这种需要。
这就是 PostgreSQL 现在的情况。
LDAP认证和其他认证方法
PostgreSQL中还有另一组与密码相关的认证方法:
•ldap
•radius
•pam
•bsd
对于客户端和协议而言,这些方法与明文认证方式“password”是等效的。 唯一的区别是服务器不会将密码与 pg_authid 中存储的密码进行比较,而是与相应的外部服务进行比较。 例如,LDAP 身份验证的工作原理如下:
1.客户端:“你好,我是 Peter,我想连接。”
2.服务器:“您的密码是什么?”
3.客户端:“是‘123456’。”
4.现在服务器向 LDAP 服务器检查密码“123456”。 这本身就可能涉及许多细节。 如果检查成功,服务器会说“OK”。
因此,这避免了将密码以明文形式存储在数据库中,但仍然存在与此方法相关的所有其他问题。 使用 SSL 进行 PostgreSQL 连接并安全地配置 LDAP 服务器和连接可以缓解许多此类问题,但它不会像 SCRAM 那样安全。 (另一条建议是,如果目标是在组织范围内建立集中式密码存储,则可以考虑使用 Kerberos 而不是 LDAP,但那是另一个话题了。)
总结
安全和密码学是很复杂的。通过使用SCRAM,PostgreSQL采用了公认的公共标准,现在处于一个良好的状态,并且可以在未来进行适应。
PostgreSQL考试认证中心(简称:PGCCC)
相关文章:

PostgreSQL中的密码验证方法
假设您想在客户端/服务器协议中实现密码身份验证方法。 您将如何做到这一点以及可能出现的问题是什么? 以下是 PostgreSQL 中如何完成此操作的故事。 password 一开始,PostgreSQL 只有 pg_hba.conf 中现在称为“password”的方法。 这是你能想象到的最…...

【微信小程序】小程序之间的跳转方式总结
想要从该小程序跳转到其他小程序怎么做? 方式 小程序之间的跳转方法有: wx.navigateTo:保留当前页面,跳转到应用内的某个页面,然后从该页面返回上一页的时候使用wx.navigateBack返回。wx.switchTab:跳转…...

基于Mysqlrouter+MHA+keepalived实现高可用半同步 MySQL Cluster项目
目录 项目名称: 基于Mysqlrouter MHA keepalived实现半同步主从复制MySQL Cluster MySQL Cluster: 项目架构图: 项目环境: 项目环境安装包: 项目描述: 项目IP地址规划: 项目步骤: 一…...

Android12.0 系统限制上网系列之iptables用IOemNetd实现清除所有规则的实现
1.前言 在12.0的系统rom定制化开发中,对于系统限制网络的使用,需要在system中netd网络这块的产品要求中,会要求设置屏蔽ip地址之内的功能, liunx中iptables命令也是比较重要的,接下来就来在IOemNetd这块实现清除所有自定义规则的的相关功能 2. 系统限制上网系列之iptab…...

vue2和vue3响应式原理
Object.DefineProperty配置对象的主要属性有: value:20 //添加的属性的value enumerable:true //是否可以被枚举获取到 默认:false writeable:true //value是否可以被修改 默认:false configurable:true //是否可以被删除 默认:f…...

【面试八股文】每日一题:谈谈你对线程的理解
每日一题-Java核心-谈谈你对线程的理解【面试八股文】 Java线程是Java程序中的执行单元。一个Java程序可以同时运行多个线程,每个线程可以独立执行不同的任务。线程的执行是并发的,即多个线程可以同时执行。 1. 线程的特点 Java中的线程有如下的特点 轻…...

arm开发板 GDB远程调试方法
1.前言 1.在linux下开发,免不了使用gdb调试,但是linux下开发嵌入式,都是跑在ARM板子上的,网上有很多GDB的基础教程,但是能在ARM开发板用的时候,会有各种问题。 比如:*.cpp: No such file or di…...

Linux命令(71)之unxz
linux命令之unxz 1.unxz介绍 linux命令unxz是用来解压由xz命令压缩的文件。unxz等价于xz -d 2.unxz用法 unxz [-c] filename.xz unxz常用参数 参数说明-c <目录>将压缩文件解压到指定目录 3.实例 3.1.解压zzz.txt.xz文件至当前目录 命令: unxz zzz.tx…...

广告牌安全传感器,实时监测事故隐患尽在掌握
在现代城市中,广告牌作为商业宣传的重要媒介,已然成为城市中一道独特的风景线。然而,随着城市迅速发展,广告牌的安全问题也引起了大众关注。广告招牌一般悬挂于建筑物高处,量大面大。由于设计、材料、施工方法的缺陷&a…...

对比学习损失—InfoNCE理论理解
InfoNoise的理解 InfoNCE loss温度系数 τ \tau τ InfoNCE loss 最近在看对比学习的东西,记录点基础的东西 「对比学习」 属于无监督学习的一种,给一堆数据,没有标签,自己学习出一种特征表示。 InfoNCE 这个损失是来自于论文&am…...

贝锐蒲公英助力电子公交站牌联网远程运维,打造智慧出行新趋势
在现代城市公共交通系统中,我们随处可见电子公交站牌的身影。作为公共交通服务的核心之一,电子公交站牌的稳定运行至关重要,公交站台的实时公交状况、公共广告信息,是市民候车时关注的焦点。 某交通科技公司在承接某市智能电子站牌…...

SpringBoot + Vue 微人事(十)
职位管理前后端接口对接 先把table中的数据展示出来,table里面的数据实际上是positions里面的数据,就是要给positions:[] 赋上值 可以在methods中定义一个initPosition方法 methods:{//定义一个初始化positions的方法initPositions(){//发送一个get请求…...

【Redis】Redis哨兵模式
【Redis】Redis哨兵模式 Redis主从模式当主服务器宕机后,需要手动把一台从服务器切换为主服务器,需要人工干预费事费力,为了解决这个问题出现了哨兵模式。 哨兵模式是是一个管理多个 Redis 实例的工具,它可以实现对 Redis 的监控…...

系统架构师---软件重用、基于架构的软件设计、软件模型
目录 软件重用 构件技术 基于架构的软件设计 ABSD方法与生命周期 抽象功能需求 用例 抽象的质量和业务需求 架构选项 质量场景 约束 基于架构的软件开发模型 架构需求 需求获取 标识构件 需求评审 架构设计 架构文档 架构复审 架构实现 架构演化 前言&…...

【Web开发指南】MyEclipse XML编辑器的高级功能简介
MyEclipse v2023.1.2离线版下载 1. 在MyEclipse中编辑XML 本文档介绍MyEclipse XML编辑器中的一些可用的函数,MyEclipse XML编辑器包括高级XML编辑,例如: 语法高亮显示标签和属性内容辅助实时验证(当您输入时)文档内容的源(Sou…...

设计模式-观察者模式(观察者模式的需求衍变过程详解,关于监听的理解)
目录 前言概念你有过这样的问题吗? 详细介绍原理:应用场景: 实现方式:类图代码 问题回答监听,为什么叫监听,具体代码是哪观察者模式的需求衍变过程观察者是为什么是行为型 总结: 前言 在软件设计…...

vue+electron中实现文件下载打开wps预览
下载事件 win.webContents.downloadURL(url) 触发session的will-download事件 win.webContents.session.on(will-download, (event, downloadItem, webContents) > {// 设置文件保存路径// 如果用户没有设置保存路径,Electron将使用默认方式来确定保存路径&am…...

第4章 性能分析中的术语和指标
Linux perf和Intel VTune Profiler工具。 4.1 退休指令与执行指令 考虑到投机执行,CPU执行的指令要不退休指令多。Linux perf使用perf stat -e instruction ./a.exe即可获得退休指令的数量。 4.2 CPU利用率 CPU利用率表示在一段时间内的繁忙程度,用时…...

数字化转型能带来哪些价值?_光点科技
随着科技的迅猛发展,数字化转型已成为企业和组织的一项重要战略。它不仅改变了商业模式和运营方式,还为各行各业带来了诸多新的机遇和价值。在这篇文章中,我们将探讨数字化转型所能带来的价值。 数字化转型能够显著提升效率和生产力。通过引入…...

适用于Android™的Windows子系统Windows Subsystem fo r Android™Win11安装指南
文章目录 一、需求二、Windows Subsystem for Android™Win11简介三、安装教程1.查看BIOS是否开启虚拟化2.安装Hyper-V、虚拟机平台3.启动虚拟机管理程序(可选)4.安装适用于Android™的Windows子系统5.相关设置 一、需求 需要在电脑上进行网课APP(无客户端只有App&…...

hive高频使用的拼接函数及“避坑”
hive高频使用的拼接函数及“避坑” 说到拼接函数应用场景和使用频次还是非常高,比如一个员工在公司充当多个角色,我们在底层存数的时候往往是多行,但是应用的时候我们通常会只需要一行,角色字段进行拼接,这样join其他…...

windows ipv4 多ip地址设置,默认网关跃点和自动跃点是什么意思?(跃点数)
文章目录 Windows中的IPv4多IP地址设置以及默认网关跃点和自动跃点的含义引言IPv4和IPv6:简介多IP地址设置:Windows环境中的实现默认网关跃点:概念和作用自动跃点:何时使用?关于“跃点数”如何确定应该设置多少跃点数&…...

java_免费文本翻译API_小牛翻译
目录 前言 开始集成API 纯文本翻译接口 双语对照翻译接口 指定术语翻译接口 总结 前言 网络上对百度,有道等的文本翻译API集成的文章比较多,所以集成的第一篇选择了小牛翻译的文本翻译API。 小牛翻译文本翻译API,支持388个语种࿰…...

flink消费kafka数据,按照指定时间开始消费
kafka中根据时间戳开始消费数据 import org.apache.flink.api.java.utils.ParameterTool; import org.apache.flink.connector.kafka.source.enumerator.initializer.OffsetsInitializer; import org.apache.flink.kafka.shaded.org.apache.kafka.clients.consumer.OffsetRese…...

【SpringCloud】Feign使用
文章目录 配置maven启动类添加yml 使用添加Feign服务Controller 其他设置超时设置YML开启OpenFeign客户端超时控制(Ribbon Timeout)OpenFeign日志打印功能日志级别YML开启日志 配置 maven <dependencies><!--openfeign--><dependency&g…...

WebApIs 第五天
window对象 BOM(浏览器对象模型)定时器-延时函数JS执行机制location对象navigator对象histroy对象 本地存储 一.BOM(浏览器对象模型) ① BOM是浏览器对象模型 window 对象是一个全局对象,也可以说是JavaScript中的…...

按斤称的C++散知识
一、多线程 std::thread()、join() 的用法:使用std::thread()可以创建一个线程,同时指定线程执行函数以及参数,同时也可使用lamda表达式。 #include <iostream> #include <thread>void threadFunction(int num) {std::cout <…...

C++策略模式
1 简介: 策略模式是一种行为型设计模式,用于在运行时根据不同的情况选择不同的算法或行为。它将算法封装成一个个具体的策略类,并使这些策略类可以相互替换,以达到动态改变对象的行为的目的。 2 实现步骤: 以下是使用…...

如何在网页下载腾讯视频为本地MP4格式
1.打开腾讯视频官网地址 腾讯视频 2.搜索你想要下载的视频 3. 点击分享,选择复制通用代码 <iframe frameborder="0" src="ht...

opencv-yolov8-目标检测
import cv2 from ultralytics import YOLO# 模型加载权重model YOLO(yolov8n.pt)# 视频路径cap cv2.VideoCapture(0)# 对视频中检测到目标画框标出来 while cap.isOpened():# Read a frame from the videosuccess, frame cap.read()if success:# Run YOLOv8 inference on th…...