第6章安全性

目录

6.1一般安全问题
6.1.1安全指南
6.1.2保持密码安全
6.1.3使MySQL安全抵御攻击者
6.1.4与安全相关的mysqld选项和变量
6.1.5如何以普通用户身份运行MySQL
6.1.6 LOAD DATA LOCAL的安全问题
6.1.7客户端编程安全指南
6.2访问控制和帐户管理
6.2.1帐户用户名和密码
6.2.2 MySQL提供的权限
6.2.3拨款表
6.2.4指定帐户名称
6.2.5指定角色名称
6.2.6访问控制,阶段1:连接验证
6.2.7访问控制,第2阶段:请求验证
6.2.8添加帐户,分配权限和删除帐户
6.2.9预留账户
6.2.10使用角色
6.2.11帐户类别
6.2.12使用部分撤销权限的权限限制
6.2.13权限更改生效时
6.2.14分配帐户密码
6.2.15密码管理
6.2.16过期密码的服务器处理
6.2.17可插拔认证
6.2.18代理用户
6.2.19账户锁定
6.2.20设置帐户资源限制
6.2.21连接MySQL的问题疑难解答
6.2.22基于SQL的帐户活动审计
6.3使用加密连接
6.3.1配置MySQL使用加密连接
6.3.2加密连接的命令选项
6.3.3创建SSL和RSA证书和密钥
6.3.4 SSL库相关功能
6.3.5构建支持加密连接的MySQL
6.3.6加密连接协议和密码
6.3.7使用SSH从Windows远程连接到MySQL
6.4安全组件和插件
6.4.1认证插件
6.4.2连接控制插件
6.4.3密码验证组件
6.4.4 MySQL密钥环
6.4.5 MySQL企业审计
6.4.6审计消息组件
6.4.7 MySQL企业防火墙
6.4.8 MySQL企业数据屏蔽和去标识
6.5 FIPS支持

在考虑MySQL安装中的安全性时,您应该考虑各种可能的主题以及它们如何影响MySQL服务器和相关应用程序的安全性:

6.1一般安全问题

本节介绍了要注意的一般安全问题,以及如何使MySQL安装更安全,防止攻击或滥用。 有关MySQL用于设置用户帐户和检查数据库访问权限的访问控制系统的信息,请参见 第2.10节“安装后设置和测试”

有关经常被问及有关MySQL服务器安全性问题的一些问题的答案,请参见 第A.9节“MySQL 8.0 FAQ:安全性”

6.1.1安全指南

在连接到Internet的计算机上使用MySQL的任何人都应该阅读本节以避免最常见的安全错误。

在讨论安全性时,有必要考虑完全保护整个服务器主机(不仅仅是MySQL服务器)免受所有类型的适用攻击:窃听,更改,回放和拒绝服务。 我们没有涵盖可用性和容错的所有方面。

MySQL使用基于访问控制列表(ACL)的安全性来处理用户可以尝试执行的所有连接,查询和其他操作。 MySQL客户端和服务器之间也支持SSL加密连接。 这里讨论的许多概念都不是特定于MySQL的; 相同的一般想法适用于几乎所有应用程序。

运行MySQL时,请遵循以下准则:

  • 不要让任何人(MySQL root 帐户 除外 )访问 系统数据库中 user mysql 这很关键。

  • 了解MySQL访问权限系统的工作原理(请参见 第6.2节“访问控制和帐户管理” )。 使用 GRANT REVOKE 语句来控制对MySQL的访问。 不要授予超出必要的权限。 永远不会授予所有主机权限。

    清单:

    • 试试 mysql -u root 如果您能够在不被要求输入密码的情况下成功连接到服务器,则任何人都可以以 root 具有完全权限 的MySQL 用户 身份连接到MySQL服务器 查看MySQL安装说明,特别注意有关设置 root 密码 的信息 请参见 第2.10.4节“保护初始MySQL帐户”

    • 使用该 SHOW GRANTS 语句检查哪些帐户可以访问哪些帐户。 然后使用该 REVOKE 语句删除那些不必要的权限。

  • 不要在数据库中存储明文密码。 如果您的计算机遭到入侵,入侵者可以获取完整的密码列表并使用它们。 相反,使用 SHA2() 或一些其他单向散列函数并存储散列值。

    要防止使用彩虹表恢复密码,请不要在普通密码上使用这些功能; 相反,选择一些字符串用作salt,并使用hash(hash(密码)+ salt)值。

  • 不要从词典中选择密码。 存在破坏密码的特殊程序。 甚至像 xfish98 这样的密码 都非常糟糕。 更好的是 duag98 ,它包含相同的单词 fish ”, 但在标准的QWERTY键盘上键入了左键。 另一种方法是使用从句子中每个单词的第一个字符中获取的密码(例如, 四分和七年前 导致密码为 Fsasya )。 密码易于记忆和输入,但对于不知道该句子的人来说很难猜到。 在这种情况下,你可以另外用数字代替数字来获得短语 4分和7年前 ,产生密码 4sa7ya ,这更难以猜测。

  • 投资防火墙。 这可以保护您免受任何软件中至少50%的漏洞攻击。 将MySQL放在防火墙后面或非军事区(DMZ)。

    清单:

    • 尝试使用诸如此类的工具从Internet扫描您的端口 nmap MySQL默认使用端口3306。 不应从不受信任的主机访问此端口。 作为检查MySQL端口是否打开的简单方法,请从某个远程计算机尝试以下命令,其中 server_host 运行MySQL服务器的主机的主机名或IP地址:

      外壳> telnet server_host 3306
      

      如果 telnet 挂起或连接被拒绝,则端口被阻塞,这就是你想要的。 如果你得到一个连接和一些垃圾字符,端口是打开的,应该在防火墙或路由器上关闭,除非你真的有充分的理由保持它打开。

  • 访问MySQL的应用程序不应信任用户输入的任何数据,应使用适当的防御性编程技术编写。 请参见 第6.1.7节“客户端编程安全指南”

  • 不要通过Internet传输普通(未加密)数据。 每个有时间和能力拦截并将其用于自己目的的人都可以访问此信息。 而是使用加密协议,如SSL或SSH。 MySQL支持内部SSL连接。 另一种技术是使用SSH端口转发为通信创建加密(和压缩)隧道。

  • 学习使用 tcpdump 字符串 实用程序。 在大多数情况下,您可以通过发出如下命令来检查MySQL数据流是否未加密:

    外壳> tcpdump -l -i eth0 -w - src or dst port 3306 | strings
    

    这适用于Linux,并且应该在其他系统下进行小的修改。

    警告

    如果您没有看到明文数据,这并不总是意味着信息实际上是加密的。 如果您需要高安全性,请咨询安全专家。

6.1.2保持密码安全

密码出现在MySQL中的几个上下文中。 以下各节提供了一些指导原则,使最终用户和管理员能够确保这些密码的安全并避免泄露这些密码。 此外,该 validate_password 插件可用于对可接受的密码实施策略。 请参见 第6.4.3节“密码验证组件”

6.1.2.1密码安全最终用户指南

MySQL用户应使用以下准则来保证密码安全。

当您运行客户端程序以连接到MySQL服务器时,不建议以将其公开给其他用户发现的方式指定您的密码。 此处列出了运行客户端程序时可用于指定密码的方法,以及每种方法的风险评估。 简而言之,最安全的方法是让客户端程序提示输入密码或在受适当保护的选项文件中指定密码。

  • 使用 mysql_config_editor 实用程序,该实用程序使您可以将身份验证凭据存储在名为的加密登录路径文件中 .mylogin.cnf MySQL客户端程序稍后可以读取该文件以获取用于连接到MySQL服务器的身份验证凭据。 请参见 第4.6.7节“ mysql_config_editor - MySQL配置实用程序”

  • 在命令行上 使用 选项。 例如: -pyour_pass --password=your_pass

    外壳> mysql -u francis -pfrank db_name
    
    警告

    这很方便 但不安全 在某些系统上,您的密码对系统状态程序(例如 ps) 可见 ,其他用户可以调用它来显示命令行。 MySQL客户端通常在初始化序列期间用零覆盖命令行密码参数。 但是,仍然存在一个短暂的间隔,在该间隔期间值是可见的。 此外,在某些系统上,此覆盖策略无效,并且 ps 仍然可以看到密码 (SystemV Unix系统和其他人可能遇到这个问题。)

    如果您的操作环境设置为在终端窗口的标题栏中显示当前命令,则只要命令正在运行,密码仍然可见,即使该命令已在窗口内容区域中滚动出视图。

  • 在命令行上 使用 -p --password 选项,但未指定密码值。 在这种情况下,客户端程序以交互方式请求密码:

    外壳> mysql -u francis -p db_name
    输入密码: ********
    

    * 字符显示在您输入密码。 输入密码时不会显示密码。

    以这种方式输入密码比在命令行中指定密码更安全,因为其他用户看不到密码。 但是,这种输入密码的方法仅适用于以交互方式运行的程序。 如果要从非交互式运行的脚本调用客户端,则无法从键盘输入密码。 在某些系统上,您甚至可能会发现脚本的第一行被读取并被解释(错误地)作为您的密码。

  • 将密码存储在选项文件中。 例如,在Unix上,您可以 在主目录 [client] 中的 .my.cnf 文件 部分 列出您的密码

    [客户]
    密码= your_pass的
    

    为了确保密码安全,除了您自己之外,任何人都无法访问该文件。 要确保这一点,请将文件访问模式设置为 400 600 例如:

    外壳> chmod 600 .my.cnf
    

    要从命令行命名包含密码的特定选项文件,请使用 选项,其中 是文件的完整路径名。 例如: --defaults-file=file_name file_name

    外壳> mysql --defaults-file=/home/francis/mysql-opts
    

    第4.2.2.2节“使用选项文件” 更详细地讨论了选项文件。

  • 将密码存储在 MYSQL_PWD 环境变量中。 请参见 第4.9节“MySQL程序环境变量”

    这种指定MySQL密码的方法必须被认为是 非常不安全的 ,不应该使用。 某些版本的 ps 包含显示正在运行的进程环境的选项。 在某些系统上,如果设置 MYSQL_PWD ,则密码将暴露给运行 ps的 任何其他用户 即使在没有这种版本的 ps的系统上 ,假设用户没有其他方法可以检查过程环境也是不明智的。

在Unix上, mysql 客户端将执行语句的记录写入历史文件(参见 第4.5.1.3节“mysql客户端日志记录” )。 默认情况下,此文件已命名 .mysql_history 并在主目录中创建。 密码可以在诸如 CREATE USER 和的 SQL语句中以纯文本形式写入 ALTER USER ,因此如果使用这些语句,它们将记录在历史文件中。 要保证此文件的安全,请使用限制访问模式,方法与前面对 .my.cnf 文件 所述的方式相同

如果命令解释程序配置为维护历史记录,则保存命令的任何文件都将包含在命令行中输入的MySQL密码。 例如, bash 使用 ~/.bash_history 任何此类文件都应具有限制性访问模式。

6.1.2.2密码安全管理员指南

数据库管理员应使用以下准则来确保密码安全。

MySQL在 mysql.user 系统表中 存储用户帐户的密码 永远不应该向任何非管理帐户授予对此表的访问权限。

帐户密码可以过期,以便用户必须重置它们。 请参见 第6.2.15节“密码管理” 第6.2.16节“过期密码的服务器处理”

validate_password 插件可用于对可接受的密码强制实施策略。 请参见 第6.4.3节“密码验证组件”

有权修改插件目录( plugin_dir 系统变量 的值 )或 my.cnf 指定插件目录位置 文件的用户可以替换插件并修改插件提供的功能,包括身份验证插件。

应该保护可能写入密码的日志文件等文件。 请参见 第6.1.2.3节“密码和日志记录”

6.1.2.3密码和日志记录

口令可以写在SQL语句,如纯文本 CREATE USER GRANT SET PASSWORD 如果MySQL服务器将此类语句记录为已写入,则访问日志的任何人都可以看到其中的密码。

语句记录避免将密码写为以下语句的明文:

创建用户...通过...识别
ALTER USER ...由......识别
设置密码 ...
从头开始......密码= ......
创建服务器...选项(...密码...)
ALTER SERVER ...选项(...密码...)

这些语句中的密码被重写为不会出现在写入常规查询日志,慢查询日志和二进制日志的语句文本中。 重写不适用于其他声明。 具体而言, INSERT UPDATE 对语句 mysql.user 引用文字密码系统表中记录为是,那么你应该避免这样的语句。 (无论如何,不​​鼓励直接修改授权表。)

对于常规查询日志,可以通过使用该 --log-raw 选项 启动服务器来抑制密码重写 出于安全原因,建议不要将此选项用于生产用途。 出于诊断目的,查看服务器收到的语句的确切文本可能很有用。

默认情况下,审计日志插件生成的审计日志文件的内容未加密,可能包含敏感信息,例如SQL语句的文本。 出于安全原因,审计日志文件应写入只能由MySQL服务器访问的目录以及具有查看日志的合法理由的用户。 请参见 第6.4.5.3节“MySQL Enterprise Audit安全注意事项”

如果安装了查询重写插件,则可以重写服务器收到的语句(请参阅 查询重写插件 )。 在这种情况下,该 --log-raw 选项会影响语句记录,如下所示:

  • 如果没有 --log-raw ,服务器会记录查询重写插件返回的语句。 这可能与收到的声明不同。

  • 使用时 --log-raw ,服务器将原始语句记录为已接收。

密码重写的含义是无法解析的语句(例如,由于语法错误)不会写入通用查询日志,因为无法知道它们是无密码的。 需要记录所有语句(包括有错误的语句)的用例应使用该 --log-raw 选项,请记住这也会绕过密码重写。

只有在需要纯文本密码时才会进行密码重写。 对于具有期望密码哈希值的语法的语句,不会发生重写。 如果为此类语法错误地提供了纯文本密码,则会将密码记录为给定,而不进行重写。

要保护日志文件免受不必要的暴露,请将它们放在限制访问服务器和数据库管理员的目录中。 如果服务器记录到 mysql 数据库中的表,则仅将这些表的访问权限授予数据库管理员。

复制从属服务器将复制主服务器的密码存储在主信息存储库中,默认情况下,该信息存储库是 mysql 名为数据库 的表 slave_master_info 现在不推荐在主数据存储库的数据目录中使用文件,但仍然可以使用(请参见 第17.2.4节“复制中继和状态日志” )。 确保只能由数据库管理员访问主信息存储库。 将密码存储在主信息存储库中的替代方法是使用该 START SLAVE 语句指定用于连接到主服务器的凭据。

使用受限访问模式来保护包含日志表或包含密码的日志文件的数据库备份。

6.1.3使MySQL安全抵御攻击者

连接到MySQL服务器时,应使用密码。 密码不会通过连接以明文形式传输。

所有其他信息都以文本形式传输,任何能够观看连接的人都可以阅读。 如果客户端和服务器之间的连接通过不受信任的网络,并且您担心这一点,则可以使用压缩协议使流量更难以解密。 您还可以使用MySQL的内部SSL支持来使连接更加安全。 请参见 第6.3节“使用加密连接” 或者,使用SSH在MySQL服务器和MySQL客户端之间获得加密的TCP / IP连接。 您可以在 http://www.openssh.org/ 找到一个开源SSH客户端 ,并 在那里 比较开源和商业SSH客户端 http://en.wikipedia.org/wiki/Comparison_of_SSH_clients

要使MySQL系统安全,您应该强烈考虑以下建议:

  • 要求所有MySQL帐户都有密码。 客户端程序不一定知道运行它的人的身份。 客户端/服务器应用程序通常可以为客户端程序指定任何用户名。 例如,任何人都可以使用 MySQL的 程序为任何其他人简单地调用它作为连接 ,如果 没有密码。 如果所有帐户都有密码,则使用其他用户的帐户进行连接会变得更加困难。 mysql -u other_user db_name other_user

    有关设置密码的方法的讨论,请参见 第6.2.14节“分配帐户密码”

  • 确保在数据库目录中具有读或写权限的唯一Unix用户帐户是用于运行 mysqld 的帐户

  • 永远不要以Unix root 用户 身份运行MySQL服务器 这是非常危险的,因为具有该 FILE 权限的 任何用户 都能够使服务器创建文件 root (例如, ~root/.bashrc )。 为了防止这种情况, 除非使用该 选项 明确指定 否则 mysqld 拒绝运行 root --user=root

    mysqld 可以(而且应该)作为普通的非特权用户运行。 您可以创建一个单独的Unix帐户,以 mysql 使一切更加安全。 仅将此帐户用于管理MySQL。 以不同的Unix用户身份 启动 mysqld ,请添加一个 user 选项, [mysqld] my.cnf 选项指定用于指定服务器选项 选项文件 组中的 用户名 例如:

    的[mysqld]
    用户= MySQL的
    

    这会导致服务器以指定用户身份启动,无论是手动启动还是使用 mysqld_safe mysql.server 启动它 有关更多详细信息,请参见 第6.1.5节“如何以普通用户身份运行MySQL”

    mysqld 作为Unix用户 运行 root 并不意味着您需要更改 表中 root 用户名 user MySQL帐户的用户名与Unix帐户的用户名无关

  • 不要将 FILE 权限 授予 非管理用户。 具有此权限的任何用户都可以使用 mysqld 守护程序 的权限在文件系统中的任何位置编写文件 这包括服务器的数据目录,其中包含实现权限表的文件。 为了使 FILE -privilege操作更安全一些,生成的文件 SELECT ... INTO OUTFILE 不会覆盖现有文件,并且每个人都可以写入。

    FILE 特权还可用于读取服务器运行的Unix用户可以访问或访问的任何文件。 使用此权限,您可以将任何文件读入数据库表。 这可能会被滥用,例如,通过使用 LOAD DATA 加载 /etc/passwd 到表中,然后可以显示 SELECT

    要限制可以读取和写入文件的位置,请将 secure_file_priv 系统设置为特定目录。 请参见 第5.1.8节“服务器系统变量”

  • 加密二进制日志文件和中继日志文件。 加密有助于保护这些文件及其中包含的潜在敏感数据免受外部攻击者的滥用,以及存储它们的操作系统用户的未授权查看。 通过将 binlog_encryption 系统变量 设置为,可以在MySQL服务器上启用加密 ON 有关更多信息,请参见 第17.3.10节“加密二进制日志文件和中继日志文件”

  • 不要 向非管理用户 授予 PROCESS SUPER 特权。 mysqladmin processlist 的输出 SHOW PROCESSLIST 显示当前正在执行的任何语句的文本,因此任何被允许查看服务器进程列表的用户都可以看到其他用户发出的语句。

    mysqld 为拥有 CONNECTION_ADMIN SUPER 特权的 用户保留额外的连接 ,这样 root 即使所有正常连接都在使用 ,MySQL 用户也可以登录并检查服务器活动。

    SUPER 权限可用于终止客户端连接,通过更改系统变量的值来更改服务器操作,以及控制复制服务器。

  • 不允许对表使用符号链接。 (此功能可通过禁用 --skip-symbolic-links 选项。)如果您运行,这一点尤其重要 的mysqld root ,因为有写访问到服务器的数据目录,然后任何人都可以在系统中删除任何文件! 请参见 第8.12.2.2节“在Unix上使用MyISAM表的符号链接”

  • 应使用 第24.6节“存储对象访问控制”中 讨论的安全准则编写存储的程序和视图

  • 如果您不信任您的DNS,则应在授权表中使用IP地址而不是主机名。 在任何情况下,您都应该非常小心地使用包含通配符的主机名值创建授权表条目。

  • 如果要限制允许连接到单个帐户的连接数,可以通过 max_user_connections mysqld中 设置 变量来实现 CREATE USER ALTER USER 语句也支持资源控制选项来限制允许帐户服务器使用的程度。 请参见 第13.7.1.3节“创建用户语法” 第13.7.1.1节“更改用户语法”

  • 如果服务器可以写入插件目录,则用户可以使用可执行代码将可执行代码写入目录中的文件 SELECT ... INTO DUMPFILE 这可以通过 plugin_dir 对服务器 进行 只读或通过设置 --secure-file-priv SELECT 可以安全地 进行 写入 的目录 来防止

6.1.4与安全相关的mysqld选项和变量

下表显示 了影响安全性的 mysqld 选项和系统变量。 有关其中每个的说明,请参见 第5.1.7节“服务器命令选项” 第5.1.8节“服务器系统变量”

表6.1安全选项和变量摘要

名称 CMD线 选项文件 系统变量 状态变量 Var范围 动态
允许可疑-UDF的
automatic_sp_privileges 全球
chroot环境
DES密钥文件
local_infile 全球
old_passwords
安全用户创建
安全-AUTH 全球
- 变量 secure_auth 全球
安全文件私法 全球 没有
- 变量 secure_file_priv 全球 没有
跳过赠款表
跳过名称解析 全球 没有
- 变量 skip_name_resolve 全球 没有
跳过网络 全球 没有
- 变量 skip_networking 全球 没有
跳过出现数据库 全球 没有
- 变量 skip_show_database 全球 没有

6.1.5如何以普通用户身份运行MySQL

在Windows上,您可以使用普通用户帐户将服务器作为Windows服务运行。

在Linux上,对于使用MySQL存储库或RPM软件包执行的安装,MySQL服务器 mysqld 应由本地 mysql 操作系统用户启动。 从另一个操作系统用户开始,作为MySQL存储库的一部分包含的init脚本不支持该用户。

在Unix(或用于使用 tar.gz 软件包 执行的安装的Linux )上,MySQL服务器 mysqld 可以由任何用户启动和运行。 但是, root 出于安全原因 ,应避免以Unix 用户 身份运行服务器 要将 mysqld 更改 为以普通的非特权Unix用户身份运行 user_name ,您必须执行以下操作:

  1. 如果服务器正在运行,请停止服务器(使用 mysqladmin shutdown )。

  2. 更改数据库目录和文件,以便 user_name 具有读取和写入文件的权限(您可能需要以Unix root 用户 身份执行此 操作):

    外壳> chown -R user_name /path/to/mysql/datadir
    

    如果不这样做,服务器在运行时将无法访问数据库或表 user_name

    如果MySQL数据目录中的目录或文件是符号链接,则 chown -R 可能不会跟随符号链接。 如果没有,您还需要关注这些链接并更改它们指向的目录和文件。

  3. 以用户身份启动服务器 user_name 另一种方法是启动 mysqld 作为Unix root 用户并使用该 选项。 mysqld 启动,然后 在接受任何连接之前 切换为以Unix用户身份运行 --user=user_name user_name

  4. 要在系统启动时自动以给定用户身份启动服务器,请通过向 选项文件 服务器数据目录 中的 选项文件 添加 user 选项来 指定用户名 例如: [mysqld] /etc/my.cnf my.cnf

    的[mysqld]
    用户=user_name
    

如果你的Unix机器本身不安全,你应该 root 在授权表中 为MySQL 帐户 分配密码 否则,在该计算机上具有登录帐户的任何用户都可以 使用 选项 运行 mysql 客户端 --user=root 并执行任何操作。 (在任何情况下,最好将密码分配给MySQL帐户,但在服务器主机上存在其他登录帐户时尤其如此。)请参见 第2.10.4节“保护初始MySQL帐户”

6.1.6 LOAD DATA LOCAL的安全问题

LOAD DATA 语句可以加载位于服务器主机上的文件,或者,如果 LOCAL 指定 关键字 ,则加载 在客户端主机上。

有与两个潜在的安全问题 LOCAL 的版本 LOAD DATA

  • 从客户端主机到服务器主机的文件传输由MySQL服务器启动。 理论上,可以构建修补的服务器,该服务器将告诉客户端程序传输服务器选择的文件而不是 LOAD DATA 语句中 客户端指定的文件 这样的服务器可以访问客户端用户具有读访问权限的客户端主机上的任何文件。 (补丁服务器实际上可以回复任何语句的文件传输请求,而不仅仅是 LOAD DATA LOCAL ,因此更基本的问题是客户端不应该连接到不受信任的服务器。)

  • 在客户端从Web服务器连接的Web环境中,用户可以使用 LOAD DATA LOCAL 读取Web服务器进程具有读访问权限的任何文件(假设用户可以对SQL服务器运行任何语句)。 在此环境中,与MySQL服务器相关的客户端实际上是Web服务器,而不是由连接到Web服务器的用户运行的远程程序。

为避免出现 LOAD DATA 问题,客户应避免使用 LOCAL 为避免连接到不受信任的服务器,客户端可以通过使用 --ssl-mode=VERIFY_IDENTITY 选项和相应的CA证书 进行连接来建立安全连接并验证服务器标识

要使管理员和应用程序能够管理本地数据加载功能, LOCAL 配置的工作方式如下:

  • 在服务器端:

    • 所述 local_infile 系统变量控制服务器端 LOCAL 的能力。 根据 local_infile 设置,服务器拒绝或允许客户端 LOCAL 启用的客户端 加载本地数据 默认情况下, local_infile 已禁用。

    • 要显式地使服务器拒绝或允许 LOAD DATA LOCAL 语句(无论在构建时或运行时如何配置客户端程序和库) ,分别启用 具有 禁用或启用的 mysqld local_infile local_infile 也可以在运行时设置。

  • 在客户端:

    • CMake的 选项控制编译默认 的MySQL客户端库的能力。 因此,没有明确安排的客户端会 根据 MySQL构建时指定 设置 禁用或启用功能 ENABLED_LOCAL_INFILE LOCAL LOCAL ENABLED_LOCAL_INFILE

      默认情况下,MySQL二进制发行版中的客户端库是使用 ENABLED_LOCAL_INFILE disabled 编译的 如果从源代码编译MySQL,则 ENABLED_LOCAL_INFILE 根据未进行显式排列的客户端是否应 LOCAL 分别禁用或启用功能,将其配置为禁用或启用。

    • 使用C API的客户端程序可以通过调用 mysql_options() 禁用或启用该 MYSQL_OPT_LOCAL_INFILE 选项 显式控制加载数据加载 请参见 第28.7.7.50节“mysql_options()”

    • 对于 mysql 客户端,默认情况下禁用本地数据加载。 要显式禁用或启用它,请使用 --local-infile=0 --local-infile[=1] 选项。

    • 对于 mysqlimport 客户端,默认情况下禁用本地数据加载。 要显式禁用或启用它,请使用 --local=0 --local[=1] 选项。

    • 如果您 LOAD DATA LOCAL 在Perl脚本或 [client] 从选项文件 中读取 组的 其他程序中使用,则可以向该 组添加 local-infile 选项设置。 要防止不理解此选项的程序出现问题,请使用 loose- 前缀 指定它

      [客户]
      松和本地的infile = 0
      

      要么:

      [客户]
      松和本地的infile = 1
      
    • 在所有情况下, LOCAL 客户端 成功使用 加载操作也需要服务器允许它。

如果 LOCAL 禁用功能,则在服务器或客户端上,尝试发出 LOAD DATA LOCAL 语句 的客户端会 收到以下错误消息:

错误1148:此MySQL版本不允许使用used命令

6.1.7客户端编程安全指南

访问MySQL的应用程序不应该信任用户输入的任何数据,用户可以通过在Web表单,URL或您构建的任何应用程序中输入特殊或转义的字符序列来欺骗您的代码。 如果用户输入类似内容,请确保您的应用程序保持安全 ; DROP DATABASE mysql; 这是一个极端的例子,但是如果你没有为它们做准备,黑客可能会使用类似的技术来发生大量的安全漏洞和数据丢失。

常见的错误是仅保护字符串数据值。 记得也要检查数字数据。 如果应用程序生成查询(例如, SELECT * FROM table WHERE ID=234 当用户输入值时) 234 ,则用户可以输入该值 234 OR 1=1 以使应用程序生成查询 SELECT * FROM table WHERE ID=234 OR 1=1 结果,服务器检索表中的每一行。 这会暴露每一行并导致过多的服务器负载。 防止此类攻击的最简单方法是在数字常量周围使用单引号: SELECT * FROM table WHERE ID='234' 如果用户输入额外信息,则它们都成为字符串的一部分。 在数字上下文中,MySQL会自动将此字符串转换为数字,并从中删除任何尾随的非数字字符。

有时人们会认为,如果数据库只包含公开可用的数据,则无需受到保护。 这是不正确的。 即使允许在数据库中显示任何行,您仍应该防止拒绝服务攻击(例如,那些基于前一段中导致服务器浪费资源的技术的攻击)。 否则,您的服务器将无法响应合法用户。

清单:

  • 启用严格SQL模式以告知服务器对其接受的数据值有更多限制。 请参见 第5.1.11节“服务器SQL模式”

  • 尝试 在所有Web表单中 输入单引号和双引号( ' " )。 如果您遇到任何类型的MySQL错误,请立即调查此问题。

  • 尝试通过向它们添加 %22 " ), %23 # )和 %27 ' )来 修改动态URL

  • 尝试使用前面示例中显示的字符将动态URL中的数据类型从数字类型修改为字符类型。 您的应用程序应该可以安全抵御这些和类似的攻击

  • 尝试输入字符,空格和特殊符号,而不是数字字段中的数字。 您的应用程序应该在将它们传递给MySQL之前删除它们,否则会生成错误。 将未经检查的值传递给MySQL非常危险!

  • 在将数据传递给MySQL之前检查数据的大小。

  • 使用与用于管理目的的用户名不同的用户名将应用程序连接到数据库。 不要为您的应用程序提供他们不需要的任何访问权限。

许多应用程序编程接口提供了一种在数据值中转义特殊字符的方法。 正确使用,这可以防止应用程序用户输入导致应用程序生成具有与您想要的效果不同的语句的值:

  • MySQL C API:使用 mysql_real_escape_string_quote() API调用。

  • MySQL ++: 对查询流 使用 escape quote 修饰符。

  • PHP:使用 mysqli pdo_mysql 扩展名,而不是旧的 ext/mysql 扩展名。 首选API支持改进的MySQL身份验证协议和密码,以及带有占位符的预处理语句。 另请参阅 选择API

    如果 ext/mysql 必须使用 较旧的 扩展名,那么为了转义使用该 mysql_real_escape_string_quote() 函数而不是 mysql_escape_string() addslashes() 因为只有 mysql_real_escape_string_quote() 字符集感知; 使用(无效)多字节字符集时, 可以 绕过 其他功能

  • Perl DBI:使用占位符或 quote() 方法。

  • Ruby DBI:使用占位符或 quote() 方法。

  • Java JDBC:使用 PreparedStatement 对象和占位符。

其他编程接口可能具有类似的功能。

6.2访问控制和帐户管理

MySQL允许创建允许客户端用户连接到服务器并访问服务器管理的数据的帐户。 MySQL权限系统的主要功能是验证谁从给定主机连接用户,并与特权用户数据库如联想 SELECT INSERT UPDATE ,和 DELETE 其他功能包括为管理操作授予权限的功能。

要控制哪些用户可以连接,可以为每个帐户分配身份验证凭据,例如密码。 用户界面MySQL账户由SQL语句如 CREATE USER GRANT REVOKE 请参见 第13.7.1节“帐户管理语句”

MySQL权限系统确保所有用户只能执行允许的操作。 作为用户,当您连接到MySQL服务器时,您的身份由 您连接的主机 您指定的用户名决定 在连接后发出请求时,系统会根据您的身份和 您要执行的操作 授予权限

MySQL会同时识别您的主机名和用户名,因为没有理由认为给定的用户名属于所有主机上的同一个人。 例如, joe 连接 的用户 office.example.com 不必是与 joe 连接 的用户相同的人 home.example.com MySQL的,使您能够区分上碰巧有相同的名称不同的主机用户来处理它:你可以通过授予一组的连接权限 joe office.example.com ,并通过连接一组不同的权限 joe home.example.com 要查看给定帐户具有的权限,请使用该 SHOW GRANTS 语句。 例如:

为'joe'@'office.example.com'显示资助';
为'joe'@'home.example.com'显示资助';

在内部,服务器将特权信息存储在 mysql 系统数据库 的授权表中 MySQL服务器在启动时将这些表的内容读入内存,并根据授权表的内存中副本建立访问控制决策。

当您运行连接到服务器的客户端程序时,MySQL访问控制涉及两个阶段:

阶段1: 服务器根据您的身份接受或拒绝连接,以及您是否可以通过提供正确的密码来验证您的身份。

阶段2: 假设您可以连接,服务器会检查您发出的每个语句,以确定您是否具有足够的权限来执行它。 例如,如果尝试从数据库中的表中选择行或从数据库中删除表,则服务器会验证您是否具有 SELECT 该表的 DROP 权限 数据库 权限。

有关每个阶段所发生情况的更详细说明,请参见 第6.2.6节“访问控制,第1阶段:连接验证” 第6.2.7节“访问控制,第2阶段:请求验证” 有关诊断与权限相关的问题的帮助,请参见 第6.2.21节“连接到MySQL的问题疑难解答”

如果在连接时更改了您的权限(由您自己或其他人),则这些更改不一定会立即生效,以用于您发出的下一个语句。 有关服务器重新加载授权表的条件的详细信息,请参见 第6.2.13节“特权更改生效时”

有些事情你不能用MySQL特权系统做:

  • 您无法明确指定应拒绝给定用户访问。 也就是说,您无法明确匹配用户,然后拒绝连接。

  • 您不能指定用户具有在数据库中创建或删除表的权限,但不能指定创建或删除数据库本身的权限。

  • 密码全局适用于帐户。 您无法将密码与特定对象(如数据库,表或例程)相关联。

6.2.1帐户用户名和密码

MySQL将帐户存储在 系统数据库 user 表中 mysql 帐户是根据用户名和用户可以从中连接到服务器的客户端主机定义的。 有关 user 表中 帐户表示的信息 ,请参见 第6.2.3节“授予表”

帐户还可能具有身份验证凭据,例如密码。 凭据由帐户身份验证插件处理。 MySQL支持多种身份验证插件。 其中一些使用内置身份验证方法,而其他人则使用外部身份验证方法启用身份验证。 请参见 第6.2.17节“可插入验证”

MySQL和您的操作系统使用用户名和密码的方式有几点不同:

  • MySQL用于身份验证的用户名与Windows或Unix使用的用户名(登录名)无关。 在Unix上,大多数MySQL客户端默认尝试使用当前的Unix用户名作为MySQL用户名登录,但这只是为了方便起见。 可以轻松覆盖默认值,因为客户端程序允许使用 -u --user 选项 指定任何用户名 这意味着任何人都可以尝试使用任何用户名连接到服务器,因此除非所有MySQL帐户都有密码,否则无法以任何方式使数据库安全。 为没有密码的帐户指定用户名的任何人都可以成功连接到服务器。

  • MySQL用户名最长为32个字符。 操作系统用户名可能具有不同的最大长度。

    警告

    MySQL用户名长度限制在MySQL服务器和客户端中是硬编码的,并且试图通过修改 mysql 数据库 中表的定义来绕过它是 行不通的

    mysql 除非通过 第2.11节“升级MySQL”中 描述的过程,否则 不应 以任何方式 更改 数据库 中表的结构 尝试以任何其他方式重新定义MySQL的系统表会导致未定义和不受支持的行为。 服务器可以自由忽略由于此类修改而变得格式错误的行。

  • 要对使用内置身份验证方法的帐户的客户端连接进行身份验证,服务器将使用存储在 user 表中的 密码 这些密码与登录操作系统的密码不同。 用于登录Windows或Unix计算机 外部 密码与用于访问该计算机上的MySQL服务器的密码 之间没有必要的连接

    如果服务器使用其他插件对客户端进行身份验证,则插件实现的身份验证方法可能会也可能不会使用存储在 user 表中 的密码 在这种情况下,外部密码也可能用于向MySQL服务器进行身份验证。

  • 存储在 user 表中的密码使用特定 插件的算法进行加密。

  • 如果用户名和密码仅包含ASCII字符,则无论字符集设置如何,都可以连接到服务器。 要在用户名或密码包含非ASCII字符时启用连接,客户端应用程序应 mysql_options() 使用 MYSQL_SET_CHARSET_NAME 选项和相应的字符集名称作为参数 调用 C API函数 这会导致使用指定的字符集进行身份验证。 否则,除非服务器默认字符集与身份验证默认值中的编码相同,否则身份验证将失败。

    标准MySQL客户端程序支持一个 --default-character-set 导致如上所述 mysql_options() 调用 选项 此外,还支持字符集自动检测,如 第10.4节“连接字符集和排序”中所述 对于使用不基于C API的连接器的程序,连接器可以提供与 mysql_options() 可以使用 的连接器等效的连接器 检查连接器文档。

    前面的注释不适用于 ucs2 utf16 utf32 ,不允许作为客户端字符集。

MySQL安装过程使用初始 root 帐户 填充授权表 ,如 第2.10.4节“保护初始MySQL帐户”中所述 ,其中还讨论了如何为其分配密码。 此后,你通常建立,修改和删除MySQL账户使用语句,例如 CREATE USER DROP USER GRANT ,和 REVOKE 请参见 第6.2.8节“添加帐户,分配权限和删除帐户” 第13.7.1节“帐户管理语句”

要使用命令行客户端连接到MySQL服务器,请根据需要为要使用的帐户指定用户名和密码选项:

外壳> mysql --user=finley --password db_name

如果您更喜欢短选项,则命令如下所示:

外壳> mysql -u finley -p db_name

如果省略 命令行上 --password -p 选项 后面的密码值 (如刚才所示),则客户端会提示 输入密码值 或者,可以在命令行上指定密码:

shell> 
shell>mysql --user=finley --password=password db_namemysql -u finley -ppassword db_name

如果使用该 -p 选项,则 密码值和以下密码值 之间 必须 没有空格 -p

在命令行上指定密码应该被认为是不安全的。 请参见 第6.1.2.1节“密码安全的最终用户指南” 要避免在命令行上输入密码,请使用选项文件或登录路径文件。 请参见 第4.2.2.2节“使用选项文件” 第4.6.7节“ mysql_config_editor - MySQL配置实用程序”

有关指定用户名,密码和其他连接参数的其他信息,请参见 第4.2.3节“连接到MySQL服务器”

6.2.2 MySQL提供的权限

授予MySQL帐户的权限决定了帐户可以执行的操作。 MySQL权限在它们适用的上下文和不同操作级别上有所不同:

  • 管理权限使用户能够管理MySQL服务器的操作。 这些权限是全局的,因为它们不是特定于特定数据库的。

  • 数据库权限适用于数据库及其中的所有对象。 可以为特定数据库或全局授予这些权限,以便它们适用于所有数据库。

  • 可以为数据库中的特定对象,数据库中给定类型的所有对象(例如,数据库中的所有表)或全局的所有对象授予数据库对象(如表,索引,视图和存储例程)的权限。所有数据库中给定类型的对象。

权限在静态(内置到服务器)或动态(在运行时定义)方面也有所不同。 权限是静态还是动态会影响其授予用户帐户和角色的可用性。 有关静态和动态权限之间差异的信息,请参阅 静态与动态权限 。)

有关帐户权限的信息存储在 mysql 系统数据库 的授权表中 有关这些表的结构和内容的说明,请参见 第6.2.3节“授权表” MySQL服务器在启动时将内容读取到内存中,并在 第6.2.13节“权限更改生效时”中 指示的情况下重新加载它们 服务器基于授权表的内存中副本建立访问控制决策。

重要

一些MySQL版本引入了对授权表的更改以添加新的特权或功能。 要确保您可以利用任何新功能,请在升级MySQL时将授权表更新为当前结构。 请参见 第2.11节“升级MySQL”

以下部分总结了可用权限,提供了有关每个权限的更详细说明以及提供使用指南。

可用权限摘要

下表显示了 GRANT REVOKE 语句中 使用的静态特权名称 ,以及与授权表中的每个特权关联的列名以及特权适用的上下文。

表6.2 GRANT和REVOKE的允许静态权限

特权 授予表格列 上下文
ALL [PRIVILEGES] all privileges ”的 同义词 服务器管理
ALTER Alter_priv
ALTER ROUTINE Alter_routine_priv 存储例程
CREATE Create_priv 数据库,表或索引
CREATE ROLE Create_role_priv 服务器管理
CREATE ROUTINE Create_routine_priv 存储例程
CREATE TABLESPACE Create_tablespace_priv 服务器管理
CREATE TEMPORARY TABLES Create_tmp_table_priv
CREATE USER Create_user_priv 服务器管理
CREATE VIEW Create_view_priv 查看
DELETE Delete_priv
DROP Drop_priv 数据库,表或视图
DROP ROLE Drop_role_priv 服务器管理
EVENT Event_priv 数据库
EXECUTE Execute_priv 存储例程
FILE File_priv 服务器主机上的文件访问
GRANT OPTION Grant_priv 数据库,表或存储例程
INDEX Index_priv
INSERT Insert_priv 表或列
LOCK TABLES Lock_tables_priv 数据库
PROCESS Process_priv 服务器管理
PROXY 请参阅 proxies_priv 服务器管理
REFERENCES References_priv 数据库或表
RELOAD Reload_priv 服务器管理
REPLICATION CLIENT Repl_client_priv 服务器管理
REPLICATION SLAVE Repl_slave_priv 服务器管理
SELECT Select_priv 表或列
SHOW DATABASES Show_db_priv 服务器管理
SHOW VIEW Show_view_priv 查看
SHUTDOWN Shutdown_priv 服务器管理
SUPER Super_priv 服务器管理
TRIGGER Trigger_priv
UPDATE Update_priv 表或列
USAGE no privileges ”的 同义词 服务器管理

下表显示了 GRANT REVOKE 语句中 使用的动态权限名称 ,以及权限适用的上下文。

表6.3 GRANT和REVOKE的允许动态权限

特权 上下文
APPLICATION_PASSWORD_ADMIN 双密码管理
AUDIT_ADMIN 审核日志管理
BACKUP_ADMIN 备份管理
BINLOG_ADMIN 备份和复制管理
BINLOG_ENCRYPTION_ADMIN 备份和复制管理
CONNECTION_ADMIN 服务器管理
ENCRYPTION_KEY_ADMIN 服务器管理
FIREWALL_ADMIN 防火墙管理
FIREWALL_USER 防火墙管理
GROUP_REPLICATION_ADMIN 复制管理
PERSIST_RO_VARIABLES_ADMIN 服务器管理
REPLICATION_SLAVE_ADMIN 复制管理
RESOURCE_GROUP_ADMIN 资源组管理
RESOURCE_GROUP_USER 资源组管理
ROLE_ADMIN 服务器管理
SESSION_VARIABLES_ADMIN 服务器管理
SET_USER_ID 服务器管理
SYSTEM_USER 服务器管理
SYSTEM_VARIABLES_ADMIN 服务器管理
TABLE_ENCRYPTION_ADMIN 服务器管理
VERSION_TOKEN_ADMIN 服务器管理
XA_RECOVER_ADMIN 服务器管理

静态权限描述

与在运行时定义的动态权限相比,静态权限内置于服务器中。 以下列表描述了MySQL中可用的每个静态特权。

特定的SQL语句可能具有比此处指示的更具体的权限要求。 如果是,则有关语句的描述提供了详细信息。

动态权限说明

动态特权是在运行时定义的,与内置于服务器的静态特权形成对比。 以下列表描述了MySQL中可用的每个动态权限。

大多数动态权限在服务器启动时定义。 其他由特定服务器组件或插件定义,如权限说明中所示。 在这种情况下,除非启用了定义它的组件或插件,否则该特权不可用。

特定的SQL语句可能具有比此处指示的更具体的权限要求。 如果是,则有关语句的描述提供了详细信息。

特权授予指南

最好只向帐户授予它所需的权限。 在授予 FILE 和管理权限 时应特别小心

  • FILE 可以滥用MySQL服务器可以在服务器主机上读取的任何文件来读入数据库表。 这包括服务器数据目录中的所有世界可读文件和文件。 然后可以使用该表 SELECT 将其内容传输到客户端主机 来访问该表

  • GRANT OPTION 使用户能够将其权限授予其他用户。 具有不同权限和权限的两个用户 GRANT OPTION 可以组合权限。

  • ALTER 可用于通过重命名表来破坏权限系统。

  • SHUTDOWN 可以滥用通过终止服务器完全拒绝向其他用户提供服务。

  • PROCESS 可用于查看当前正在执行的语句的纯文本,包括设置或更改密码的语句。

  • SUPER 可用于终止其他会话或更改服务器的运行方式。

  • mysql 系统数据库本身 授予的权限 可用于更改密码和其他访问权限信息:

    • 密码以加密方式存储,因此恶意用户无法简单地读取密码以了解明文密码。 但是,对 mysql.user 系统表 authentication_string 具有写访问权限的用户 可以更改帐户的密码,然后使用该帐户连接到MySQL服务器。

    • INSERT UPDATE 授予 mysql 系统数据库使用户能够分别添加权限或修改现有权限。

    • DROP 对于 mysql 系统数据库,用户可以使用远程权限表,甚至是数据库本身。

静态与动态权限

MySQL支持静态和动态权限:

  • 静态特权内置于服务器中。 它们始终可以授予用户帐户,并且无法取消注册。

  • 动态特权可以在运行时注册和取消注册。 这会影响其可用性:无法授予尚未注册的动态权限。

例如, SELECT INSERT 权限是静态的并且始终可用,而动态权限仅在已启用实现它的服务器组件时才可用。

本节的其余部分将介绍动态权限在MySQL中的工作原理。 讨论使用术语 组件 ”, 但同样适用于插件。

注意

服务器管理员应该知道哪些服务器组件定义了动态权限。 对于MySQL发行版,定义动态权限的组件文档描述了这些权限。

第三方组件也可以定义动态权限; 管理员应该了解这些权限,而不是安装可能与服务器操作冲突或危害的组件。 例如,如果两个组件都定义了具有相同名称的权限,则一个组件与另一个组件冲突。 组件开发人员可以通过选择具有基于组件名称的前缀的权限名称来降低发生这种情况的可能性。

服务器在内存中维护已注册的动态权限集。 服务器关闭时发生取消注册。

通常,定义动态权限的服务器组件在其初始化序列期间在安装时注册它们。 卸载时,服务器组件不会取消注册其已注册的动态权限。 (这是当前的做法,而不是要求。也就是说,组件可以,但不能在任何时候取消注册它们注册的权限。)

尝试注册已注册的动态权限时不会出现警告或错误。 请考虑以下语句序列:

安装组件'my_component';
UNINSTALL COMPONENT'my_component';
安装组件'my_component';

第一个 INSTALL COMPONENT 语句注册服务器组件定义的任何权限 my_component ,但 UNINSTALL COMPONENT 不注销它们。 对于第二个 INSTALL COMPONENT 语句,发现已注册的组件权限已经注册,但不会发生警告或错误。

动态权限仅适用于全局级别。 服务器将有关当前动态权限分配的信息存储到 mysql.global_grants 系统表 中的用户帐户

  • 服务器自动注册 global_grants 在服务器启动期间 命名的权限 (除非 --skip-grant-tables 给出选项)。

  • GRANT REVOKE 语句修改的内容 global_grants

  • 列出的动态权限分配 global_grants 是持久的。 服务器关闭时不会删除它们。

示例:以下语句向用户授予 u1 控制从属服务器上的复制(包括组复制)以及修改系统变量所需的权限:

GRANT REPLICATION_SLAVE_ADMIN,GROUP_REPLICATION_ADMIN,BINLOG_ADMIN
ON *。* TO'u1'@'localhost';

授权动态特权出现在 SHOW GRANTS 语句和 INFORMATION_SCHEMA USER_PRIVILEGES 的输出 中。

对于 GRANT REVOKE 在全球范围内,静态是针对当前的一组登记的动态权限检查,如果发现不授予任何公认的命名特权。 否则,将发生错误以指示未知的权限标识符。

对于 GRANT REVOKE 意义 ALL [PRIVILEGES] 在全球范围包括所有静态全局权限,以及所有目前已登记的动态权限:

  • GRANT ALL 在全局级别授予所有静态全局特权和所有当前注册的动态特权。 在执行该 GRANT 语句 之后注册的动态权限 不会追溯授予任何帐户。

  • REVOKE ALL 在全局级别撤消所有授予的静态全局特权和所有授予的动态特权。

FLUSH PRIVILEGES 语句读取 global_grants 表以获取动态权限分配,并注册在那里找到的任何未注册权限。

有关MySQL发行版中包含的MySQL服务器和服务器组件提供的动态权限的说明,请参见 第6.2.2节“MySQL提供的权限”

将帐户从SUPER迁移到动态权限

在MySQL 8.0中,许多以前需要该 SUPER 权限的操作也与更有限范围的动态权限相关联。 (有关这些权限的说明,请参见 第6.2.2节“MySQL提供的权限” 。)通过授予关联的动态权限而不是,可以允许每个此类操作进入帐户 SUPER 此更改通过使DBA能够避免 SUPER 准确地授予 和定制用户权限 来提高安全性 SUPER 现已弃用,将在未来版本的MySQL中删除。

SUPER 发生 删除 时, SUPER 除非已授予 SUPER 帐户 迁移到适当的动态权限, 否则 以前需要的操作 将失败 使用以下说明完成该目标,以便在 SUPER 删除 之前准备好帐户

  1. 执行此查询以标识已授予的帐户 SUPER

    从INFORMATION_SCHEMA.USER_PRIVILEGES中选择GRANTEE
    WHERE PRIVILEGE_TYPE ='超级';
    
  2. 对于前面的查询标识的每个帐户,确定它需要的操作 SUPER 然后授予与这些操作对应的动态权限,并撤消 SUPER

    例如,如果 'u1'@'localhost' 需要 SUPER 二进制日志清除和系统变量修改,则这些语句会对帐户进行必要的更改:

    GRANT BINLOG_ADMIN,SYSTEM_VARIABLES_ADMIN ON *。* TO'u1'@'localhost';
    REVOKE SUPER ON *。* FROM'u1'@'localhost';
    

    修改完所有适用的帐户后, INFORMATION_SCHEMA 第一步中 查询应生成一个空结果集。

6.2.3拨款表

mysql 系统数据库包括包含关于用户帐户和他们持有的特权信息的几个授权表。 本节介绍这些表。 有关系统数据库中其他表的信息,请参见 第5.3节“mysql系统模式”

此处的讨论描述了授权表的基础结构以及服务器在与客户端交互时如何使用其内容。 但是,通常不直接修改授权表。 当您使用帐户管理语句(例如 CREATE USER GRANT )和 REVOKE 设置帐户并控制每个帐户可用的权限 时,间接会发生修改 请参见 第13.7.1节“帐户管理语句” 当您使用此类语句执行帐户操作时,服务器会代表您修改授权表。

注意

使用诸如 ,或者 不鼓励的 语句直接修改授权表 INSERT 并且风险自负。 服务器可以自由忽略由于此类修改而变得格式错误的行。 UPDATE DELETE

对于修改授权表的任何操作,服务器检查该表是否具有预期结构,否则生成错误。 要将表更新为预期结构,请执行MySQL升级过程。 请参见 第2.11节“升级MySQL”

授权表概述

这些 mysql 数据库表包含授权信息:

有关静态和动态全局权限之间差异的信息,请参阅 静态与动态权限 。)

在MySQL 8.0中,授权表使用 InnoDB 存储引擎并且是事务性的。 在MySQL 8.0之前,授权表使用了 MyISAM 存储引擎并且是非事务性的。 授权表存储引擎的这种更改使得对帐户管理语句(例如 CREATE USER 或) 的行为的伴随更改成为 可能 GRANT 以前,为多个用户命名的帐户管理语句可能会对某些用户成功,而对其他用户则失败。 现在,每个语句都是事务性的,并且对所有命名用户都成功或回滚,如果发生任何错误则无效。

每个授权表都包含范围列和特权列:

  • 范围列确定表中每行​​的范围; 也就是说,行适用的上下文。 例如,一个 user 表行,其中包含 Host User 值, 'h1.example.net' 并且 'bob' 适用于 h1.example.net 由指定用户名的客户端 从主机对服务器进行的身份验证的连接 bob 类似地, db 表行包含 Host User Db 列值 'h1.example.net' 'bob' 'reports' bob 从主机连接 h1.example.net 到访问 reports 数据库时应用。 tables_priv columns_priv 表包含范围列,指示每行适用的表或表/列组合。 procs_priv 范围列表示存储程序到各行适用。

  • 权限列指示表行授予的权限; 也就是说,它允许执行哪些操作。 服务器将各种授权表中的信息组合在一起,形成用户权限的完整描述。 第6.2.7节“访问控制,第2阶段:请求验证” ,描述了相关规则。

此外,授权表可能包含用于范围或特权评估之外的目的的列。

服务器以下列方式使用授权表:

  • user 表范围列确定是否拒绝或允许传入连接。 对于允许的连接, user 表中 授予的任何权限都 表示用户的静态全局权限。 此表中授予的任何权限 适用于 服务器上的 所有 数据库。

    警告

    因为任何静态全局特权被认为是所有数据库的特权,任何静态全局特权使用户能够看到所有的数据库名称 SHOW DATABASES 或通过检查 SCHEMATA INFORMATION_SCHEMA ,除了已经在通过局部撤销数据库级别被限制的数据库。

  • global_grants 表列出了当前对用户帐户的动态全局权限的分配。 对于每一行,作用域列确定哪个用户具有在权限列中指定的权限。

  • db 表范围列决定哪些用户可以访问哪些数据库从哪个主机。 权限列确定允许的操作。 在数据库级别授予的权限适用于数据库和数据库中的所有对象,例如表和存储的程序。

  • tables_priv columns_priv 表类似于 db 表,但是更精致:他们在申请表和列级应用而非在数据库级。 表级别授予的权限适用于表及其所有列。 在列级别授予的权限仅适用于特定列。

  • procs_priv 表适用于存储的例程(存储过程和函数)。 在例程级别授予的权限仅适用于单个过程或函数。

  • proxies_priv 表指示哪些用户可以充当其他用户的代理以及用户是否可以将该 PROXY 特权 授予 其他用户。

  • default_roles role_edges 表包含角色关系的信息。

  • password_history 表保留以前选择的密码以启用密码重用限制。 请参见 第6.2.15节“密码管理”

服务器在启动时将授权表的内容读入内存。 您可以通过发出 FLUSH PRIVILEGES 语句或执行 mysqladmin flush-privileges 来告诉它重新加载表 mysqladmin reload 命令 对授权表的更改将在 第6.2.13节“特权更改 生效时”中指示生效

修改帐户时,最好验证您的更改是否具有预期效果。 要检查给定帐户的权限,请使用该 SHOW GRANTS 语句。 例如,要确定与用户名和主机名值授予一个帐户的权限 bob pc84.example.com 使用下面的语句:

为'bob'@'pc84.example.com'展示奖学金;

要显示帐户的非特权属性,请使用 SHOW CREATE USER

SHOW CREATE USER'bob'@'pc84.example.com';

用户和数据库表

服务器 访问控制的第一和第二阶段 使用 数据库中 user db mysql (请参见 第6.2节“访问控制和帐户管理” )。 这里显示 user db 表中的列。

表6.4 user和db Table列

表名 user db
范围列 Host Host
User Db
User
权限列 Select_priv Select_priv
Insert_priv Insert_priv
Update_priv Update_priv
Delete_priv Delete_priv
Index_priv Index_priv
Alter_priv Alter_priv
Create_priv Create_priv
Drop_priv Drop_priv
Grant_priv Grant_priv
Create_view_priv Create_view_priv
Show_view_priv Show_view_priv
Create_routine_priv Create_routine_priv
Alter_routine_priv Alter_routine_priv
Execute_priv Execute_priv
Trigger_priv Trigger_priv
Event_priv Event_priv
Create_tmp_table_priv Create_tmp_table_priv
Lock_tables_priv Lock_tables_priv
References_priv References_priv
Reload_priv
Shutdown_priv
Process_priv
File_priv
Show_db_priv
Super_priv
Repl_slave_priv
Repl_client_priv
Create_user_priv
Create_tablespace_priv
Create_role_priv
Drop_role_priv
安全专栏 ssl_type
ssl_cipher
x509_issuer
x509_subject
plugin
authentication_string
password_expired
password_last_changed
password_lifetime
account_locked
Password_reuse_history
Password_reuse_time
Password_require_current
User_attributes
资源控制列 max_questions
max_updates
max_connections
max_user_connections

user plugin authentication_string 列存储身份验证插件和证书信息。

服务器使用 plugin 帐户行列中 指定的插件 来验证帐户的连接尝试。

plugin 列必须是非空的。 在启动时,在运行时 FLUSH PRIVILEGES 执行时,服务器会检查 user 表行。 对于具有空 plugin 列的 任何行 ,服务器会向此表单的错误日志写入警告:

[警告]用户输入' user_name'@'host_name '有一个空的插件
值。用户将被忽略,没有人可以使用此用户登录
了。

要将插件分配给缺少一个的帐户,请使用 ALTER USER 语句。

password_expired 列允许DBA使帐户密码到期,并要求用户重置其密码。 默认 password_expired 值为 'N' ,但可以 'Y' 使用 ALTER USER 语句 设置 帐户密码过期后,帐户在后续服务器连接中执行的所有操作都会导致错误,直到用户发出 ALTER USER 声明以建立新帐户密码。

密码过期后可以 通过将密码设置为当前值 重置 密码。 作为一个好的政策问题,最好选择不同的密码。 DBA可以通过建立适当的密码重用策略来强制执行非重用。 请参阅 密码重用策略

password_last_changed 是一个 TIMESTAMP 列,指示上次更改密码的时间。 该值为非 NULL 仅适用于使用MySQL内置的身份验证插件账户( mysql_native_password sha256_password ,或 caching_sha2_password )。 该值适用 NULL 于其他帐户,例如使用外部身份验证系统进行身份验证的帐户。

password_last_changed 通过更新 CREATE USER ALTER USER SET PASSWORD 报表,并通过 GRANT 创造一个帐户或更改帐户密码的语句。

password_lifetime 表示帐户密码生存期,以天为单位。 如果密码超过其生命周期(使用 password_last_changed 评估 ),则服务器会在客户端使用该帐户连接时认为密码已过期。 N 大于零意味着必须每天更改密码 N 值为0将禁用自动密码到期。 如果值为 NULL (缺省值),则应用全局过期策略,如 default_password_lifetime 系统变量 所定义

account_locked 指示帐户是否已锁定(请参见 第6.2.19节“帐户锁定” )。

Password_reuse_history PASSWORD HISTORY 帐户选项 的值 ,或 NULL 默认历史记录的值。

Password_reuse_time PASSWORD REUSE INTERVAL 帐户选项 的值 ,或 NULL 默认间隔的值。

Password_require_current (在MySQL 8.0.13中添加)对应于 PASSWORD REQUIRE 帐户选项 的值, 如下表所示。

表6.5允许的Password_require_current值

Password_require_current值 相应的密码请求选项
'Y' PASSWORD REQUIRE CURRENT
'N' PASSWORD REQUIRE CURRENT OPTIONAL
NULL PASSWORD REQUIRE CURRENT DEFAULT

User_attributes (在MySQL 8.0.14中添加)存储未存储在其他列中的帐户属性:

  • additional_password :辅助密码,如果有的话。 请参阅 双密码支持

  • Restrictions :限制列表,如果有的话。 部分撤销操作会增加限制。 属性值是一个元素数组,每个元素都有 Database Restrictions 键,指示受限数据库的名称及其适用的限制(请参见 第6.2.12节“使用部分撤消的权限限制” )。

如果没有适用的属性,那 User_attributes 就是 NULL

例如:具有二级密码和部分撤销数据库特权拥有帐户 additional_password Restrictions 在该列的值属性:

MySQL的> SELECT User_attributes FROM mysql.User WHERE User = 'u'\G
*************************** 1。排******************** *******
User_attributes:{“限制”:
                   [{“Database”:“mysql”,“Privileges”:[“SELECT”]}],
                  “additional_password”:“ hashed_credentials”}

要确定存在哪些属性,请使用以下 JSON_KEYS() 函数:

SELECT User,Host,JSON_KEYS(User_attributes)
FROM mysql.user WHERE User_attributes IS NOT NULL;

要提取特定属性,例如 Restrictions ,请执行以下操作:

SELECT User,Host,User_attributes  -  >>'$。Restrictions'
FROM mysql.user WHERE User_attributes  -  >>'$。Restrictions'<>'';

tables_priv和columns_priv表

在访问控制的第二阶段,服务器执行请求验证以确保每个客户端对其发出的每个请求具有足够的权限。 除了 user db grant表之外,服务器还可以查询 tables_priv columns_priv 涉及表的请求。 后面的表在表级和列级提供更精细的权限控制。 它们具有下表中显示的列。

表6.6 tables_priv和columns_priv表列

表名 tables_priv columns_priv
范围列 Host Host
Db Db
User User
Table_name Table_name
Column_name
权限列 Table_priv Column_priv
Column_priv
其他专栏 Timestamp Timestamp
Grantor

Timestamp Grantor 列被设置为当前时间戳和 CURRENT_USER 值,分别,但其他未使用的。

procs_priv表

为了验证涉及存储例程的请求,服务器可以查询该 procs_priv 表,该表具有下表中显示的列。

表6.7 procs_priv表列

表名 procs_priv
范围列 Host
Db
User
Routine_name
Routine_type
权限列 Proc_priv
其他专栏 Timestamp
Grantor

Routine_type 列是一个 ENUM 值为 'FUNCTION' 列, 'PROCEDURE' 表示行引用的例程类型。 此列允许为具有相同名称的函数和过程单独授予权限。

Timestamp Grantor 列未使用。

proxies_priv表

proxies_priv 表记录有关代理帐户的信息。 它有以下列:

  • Host User :代理帐户; 也就是说,具有 PROXY 代理帐户权限的帐户。

  • Proxied_host Proxied_user :代理帐户。

  • Grantor Timestamp :未使用。

  • With_grant :代理帐户是否可以将 PROXY 权限 授予 其他帐户。

对于能够将 PROXY 权限 授予 其他帐户的帐户,它必须在 proxies_priv 表中具有 With_grant 设置为1的行, Proxied_host Proxied_user 设置为指示可以为其授予权限的帐户。 例如, 'root'@'localhost' 在MySQL安装期间创建 帐户在 proxies_priv 表中 有一行,该行 允许 为所有用户和所有主机 授予 PROXY 权限 ''@'' 这样可以 root 设置代理用户,以及委托其他帐户设置代理用户的权限。 请参见 第6.2.18节“代理用户”

global_grants表

global_grants 表列出了当前对用户帐户的动态全局权限的分配。 该表包含以下列:

  • USER HOST :授予权限的帐户的用户名和主机名。

  • PRIV :权限名称。

  • WITH_GRANT_OPTION :帐户是否可以将权限授予其他帐户。

default_roles表

default_roles 表列出了默认用户角色。 它有以下列:

  • HOST USER :默认角色适用的帐户或角色。

  • DEFAULT_ROLE_HOST DEFAULT_ROLE_USER :默认角色。

role_edges表

role_edges 表列出了角色子图的边缘。 它有以下列:

  • FROM_HOST FROM_USER :被授予角色的帐户。

  • TO_HOST TO_USER :授予帐户的角色。

  • WITH_ADMIN_OPTION :帐户是否可以通过使用授予角色和从其他帐户撤消角色 WITH ADMIN OPTION

password_history表

password_history 表包含有关密码更改的信息。 它有以下列:

  • Host User :发生密码更改的帐户。

  • Password_timestamp :密码更改发生的时间。

  • Password :新密码哈希值。

password_history 表为每个帐户累积足够数量的非空密码,以使MySQL能够对帐户密码历史记录长度和重用间隔执行检查。 当发生密码更改尝试时,会自动修剪超出两个限制的条目。

注意

空密码不会计入密码历史记录中,并且可以随时重复使用。

如果重命名帐户,则会重命名其条目以匹配。 如果删除帐户或更改其身份验证插件,则会删除其条目。

范围列属性

授权表中的范围列包含字符串。 每个的默认值是空字符串。 下表显示了每列中允许的字符数。

表6.8授权表范围列长度

列名称 允许的最大字符数
Host Proxied_host 255(MySQL 8.0.17之前的60)
User Proxied_user 32
Db 64
Table_name 64
Column_name 64
Routine_name 64

对于访问检查的目的,进行比较 User Proxied_user authentication_string Db ,和 Table_name 的值是大小写敏感的。 的比较 Host Proxied_host Column_name ,和 Routine_name 的值是不区分大小写。

权限列属性

user db 表列出了被声明为一个单独的列每个特权 ENUM('N','Y') DEFAULT 'N' 换句话说,可以禁用或启用每个权限,默认为禁用。

tables_priv columns_priv procs_priv 表申报权限列的 SET 列。 这些列中的值可以包含表控制的权限的任意组合。 仅启用列值中列出的那些权限。

表6.9 Set-Type特权列值

表名 列名称 可能的集合元素
tables_priv Table_priv 'Select', 'Insert', 'Update', 'Delete', 'Create', 'Drop', 'Grant', 'References', 'Index', 'Alter', 'Create View', 'Show view', 'Trigger'
tables_priv Column_priv 'Select', 'Insert', 'Update', 'References'
columns_priv Column_priv 'Select', 'Insert', 'Update', 'References'
procs_priv Proc_priv 'Execute', 'Alter Routine', 'Grant'

只有 user global_grants 表指定管理权限,如 RELOAD SHUTDOWN SYSTEM_VARIABLES_ADMIN 管理操作是服务器本身的操作,并不是特定于数据库的,因此没有理由在其他授权表中列出这些特权。 因此,服务器只需要查询 user global_grants 表来确定用户是否可以执行管理操作。

FILE 权限也仅在 user 表中 指定 它本身不是管理权限,但用户在服务器主机上读取或写入文件的能力与所访问的数据库无关。

6.2.4指定帐户名称

MySQL帐户名由用户名和主机名组成。 这样可以为具有相同名称且可以从不同主机连接的用户创建帐户。 本节介绍如何编写帐户名,包括特殊值和通配符规则。

MySQL角色名称与帐户名称类似,但 第6.2.5节“指定角色名称”中 描述了一些差异

在诸如 ,和 等帐户名的 SQL语句中 CREATE USER 遵循以下规则: GRANT SET PASSWORD

  • 帐户名称语法是 'user_name'@'host_name'

  • 仅包含用户名的帐户名称相当于 例如, 相当于 'user_name'@'%' 'me' 'me'@'%'

  • 如果用户名和主机名是合法的,则不需要引用它们作为不带引号的标识符。 需要引号来指定 user_name 包含特殊字符(如空格或 - )的 host_name 字符串 ,或 包含特殊字符或通配符(例如, . % 字符串 (例如 'test-user'@'%.com' )。

  • 使用反引号( ` ),单引号( ' )或双引号( " 引用用户名和主机名作为标识符或字符串 有关字符串引用和标识符引用指南,请参见 第9.1.1节“字符串文字” 第9.2节“模式对象名称”

  • 如果引用,用户名和主机名部分必须单独引用。 也就是说,写 'me'@'localhost' ,不 'me@localhost' ; 后者实际上相当于 'me@localhost'@'%'

  • CURRENT_USER or CURRENT_USER() 函数的 引用 等同于从字面上指定当前客户端的用户名和主机名。

MySQL mysql 使用单独的用户名和主机名部分列 将帐户名存储在 系统数据库的 授权表中

  • user 表包含每个帐户的一行。 User Host 列存储用户名和主机名。 此表还指示帐户具有哪些全局权限。

  • 其他授权表指示帐户对数据库和数据库中的对象具有的特权。 这些表必须 User Host 存储帐户名称列。 这些表中的每一行与该帐户相关联 user ,具有相同的表 User Host 值。

  • 为了访问检查目的,用户值的比较是区分大小写的。 主机值的比较不区分大小写。

有关授权表的结构更多细节,请参见 第6.2.3节“授权表”

用户名和主机名具有某些特殊值或通配符约定,如下所述。

帐户名的用户名部分是非空白值,与字面上与传入连接尝试的用户名匹配,或者是与任何用户名匹配的空值(空字符串)。 具有空白用户名的帐户是匿名用户。 要在SQL语句中指定匿名用户,请使用带引号的空用户名部分,例如 ''@'localhost'

帐户名称的主机名部分可以采用多种形式,并允许使用通配符:

  • 主机值可以是主机名或IP地址(IPv4或IPv6)。 该名称 'localhost' 表示本地主机。 IP地址 '127.0.0.1' 表示IPv4环回接口。 IP地址 '::1' 表示IPv6环回接口。

  • % _ 通配符允许在主机名或IP地址的值。 这些与操作员执行的模式匹配操作具有相同的含义 LIKE 例如,主机值 '%' 匹配任何主机名,而值 '%.mysql.com' 匹配 mysql.com 域中的 任何主机 '198.51.100.%' 匹配198.51.100 C类网络中的任何主机。

    由于主机值中允许使用IP通配符值(例如, '198.51.100.%' 为了匹配子网上的每个主机),因此有人可能会尝试通过命名主机来利用此功能 198.51.100.somewhere.com 为了阻止这种尝试,MySQL不会对以数字和点开头的主机名执行匹配。 例如,如果命名了主机 1.2.example.com ,则其名称永远不会与帐户名称的主机部分匹配。 IP通配符值只能匹配IP地址,而不能匹配主机名。

  • 对于指定为IPv4地址的主机值,可以给出网络掩码以指示用于网络号的地址位数。 网络掩码表示法不能用于IPv6地址。

    语法是 例如: host_ip/netmask

    创建用户'david'@'198.51.100.0/255.255.255.0';
    

    这使得 david 能够从具有 client_ip 以下条件为真的 IP地址的任何客户端主机进行连接

    client_ipnetmask=host_ip
    

    也就是说,对于 CREATE USER 刚才显示 声明:

    client_ip &255.255.255.0 = 198.51.100.0
    

    满足此条件范围的IP地址 198.51.100.0 198.51.100.255

    网络掩码通常以设置为1的位开头,然后将位设置为0.示例:

    • 198.0.0.0/255.0.0.0 :198 A类网络上的任何主机

    • 198.51.100.0/255.255.0.0 :198.51 B类网络上的任何主机

    • 198.51.100.0/255.255.255.0 :198.51.100 C类网络上的任何主机

    • 198.51.100.1 :仅具有此​​特定IP地址的主机

服务器使用系统DNS解析程序为客户端主机名或IP地址返回的值,针对客户端主机执行帐户名中的主机值匹配。 除了使用网络掩码表示法指定帐户主机值的情况之外,服务器将此比较作为字符串匹配执行,即使对于作为IP地址给出的帐户主机值也是如此。 这意味着您应该使用DNS使用的相同格式指定帐户主机值。 以下是需要注意的问题示例:

  • 假设本地网络上的主机具有完全限定名称 host1.example.com 如果DNS返回此主机的名称查找,请 host1.example.com 在帐户主机值中使用该名称。 如果DNS返回 host1 ,请 host1 改用。

  • 如果DNS返回给定主机的IP地址 198.51.100.2 ,那将匹配帐户主机值 198.51.100.2 但不 匹配 198.051.100.2 同样,它会匹配帐户主机模式, 198.51.100.% 但不 匹配 198.051.100.%

为避免这些问题,建议您检查DNS返回主机名和地址的格式。 在MySQL帐户名中使用相同格式的值。

6.2.5指定角色名称

MySQL角色名称指的是角色,它们被命名为特权集合。 有关角色使用示例,请参见 第6.2.10节“使用角色”

角色名的语法和语义相似的账户名( 第6.2.4节“指定帐户名” )。 角色名称在这些方面与帐户名称不同:

  • 角色名称的用户部分不能为空。 因此,没有 匿名角色 类似于 匿名用户 的概念

  • 作为一个帐户名,省略了在主机部分角色名称结果主机部分 '%' 但是,与 '%' 在一个帐户名,主机部分 '%' 的角色名称没有通配符性能。 例如,对于一个名称 'me'@'%' 用作角色名,主机部分( '%' )仅仅是一个文字值; 它没有 任何主机 匹配属性。

  • 角色名称的主机部分中的网络掩码表示法没有意义。

  • 帐户名称允许 CURRENT_USER() 在多个上下文中。 角色名称不是。

mysql.user 系统表中 的一行 可以同时用作帐户和角色。 在这种情况下,任何特殊用户或主机名匹配属性都不适用于将该名称用作角色名称的上下文。 例如,您不能执行以下语句,期望它将使用具有用户部分 myrole 和任何主机名的 所有角色设置当前会话角色

SET ROLE'myrole'@'%';

相反,该语句将会话的活动角色设置为具有完全名称的角色 'myrole'@'%'

因此,通常仅使用用户名部分指定角色名称,并隐式使用主机名部分 '%' '%' 如果您打算创建一个既可用作角色又可用作允许从给定主机连接的用户帐户的名称,则 指定具有非 主机部件 的角色 非常有用。

6.2.6访问控制,阶段1:连接验证

当您尝试连接到MySQL服务器时,服务器会根据以下条件接受或拒绝连接:

  • 您的身份以及是否可以通过提供正确的密码来验证您的身份

  • 您的帐户是锁定还是解锁

服务器首先检查凭据,然后检查帐户锁定状态。 任一步骤失败都会导致服务器完全拒绝您的访问权限。 否则,服务器接受连接,然后进入阶段2并等待请求。

使用三个执行凭证检查 user 表范围列( Host User ,和 authentication_string )。 锁定状态记录在 user 表格 account_locked 列中。 仅当 某些 表行中 Host User user 与客户端主机名和用户名匹配时, 服务器才接受连接 ,客户端提供该行中指定的密码, account_locked 值为 'N' 允许 Host User 的规则 第6.2.4节“指定帐户名称”中给出 可以使用 ALTER USER 语句 更改帐户锁定

您的身份基于两条信息:

  • 您连接的客户端主机

  • 您的MySQL用户名

如果 User 列值为非空,则传入连接中的用户名必须完全匹配。 如果 User 值为空,则它匹配任何用户名。 如果 user 与传入连接匹配 表行具有空白用户名,则该用户被视为没有名称的匿名用户,而不是具有客户端实际指定名称的用户。 这意味着空白用户名用于连接持续时间内的所有进一步访问检查(即,在阶段2期间)。

authentication_string 列可以为空白。 这不是通配符,并不表示任何密码匹配。 这意味着用户必须在不指定密码的情况下进行连接。 如果服务器使用插件对客户端进行身份验证,则插件实现的身份验证方法可能会也可能不会使用 authentication_string 列中 的密码 在这种情况下,外部密码也可能用于向MySQL服务器进行身份验证。

表中的非 authentication_string user 表示加密密码。 MySQL不会将密码存储为任何人都可以看到的明文。 而是,尝试连接的用户提供的密码是加密的(使用由帐户认证插件实现的密码散列方法)。 然后在检查密码是否正确时,在连接过程中使用加密密码。 这是在没有经过连接的加密密码的情况下完成的。 请参见 第6.2.1节“帐户用户名和密码”

从MySQL的角度来看,加密密码是 真正的 密码,所以你永远不应该让任何人访问它。 特别是, 不要给非管理用户读取对 mysql 系统数据库 中表的访问权限

下表显示了表中各种组合 User Host 如何 user 应用于传入连接。

User Host 允许的连接
'fred' 'h1.example.net' fred ,连接 h1.example.net
'' 'h1.example.net' 任何用户,从中连接 h1.example.net
'fred' '%' fred ,从任何主机连接
'' '%' 任何用户,从任何主机连接
'fred' '%.example.net' fred ,从 example.net 域中的 任何主机连接
'fred' 'x.example.%' fred ,从连接 x.example.net x.example.com x.example.edu ,等; 这可能没用
'fred' '198.51.100.177' fred ,从主机与IP地址连接 198.51.100.177
'fred' '198.51.100.%' fred ,从 198.51.100 C类子网 中的任何主机连接
'fred' '198.51.100.0/255.255.255.0' 与前面的示例相同

传入连接的客户端主机名和用户名可以匹配 user 中的多个行 前述组实例证明这一点:若干条目的匹配示出从连接 h1.example.net fred

当可能存在多个匹配项时,服务器必须确定要使用哪些匹配项。 它解决了这个问题如下:

  • 只要服务器将 user 入内存,它就会对行进行排序。

  • 当客户端尝试连接时,服务器按排序顺序查看行。

  • 服务器使用与客户端主机名和用户名匹配的第一行。

服务器使用排序规则, Host 首先 对具有最具特定 值的 行进行排序 文字主机名和IP地址是最具体的。 (文字IP地址的特异性不受其是否具有网络掩码,因此 198.51.100.13 198.51.100.0/255.255.255.0 被认为是同样特异性的。)该模式 '%' 是指 任何主机 并且是最不特定。 空字符串 '' 也表示 任何主机 ”, 但后面排序 '%' 具有相同 Host 值的 行首先以 最具特定的 User 排序 (空白 User 值表示 任何用户 并且最不具体)。 对于具有相同特定 Host User 值的行,顺序是不确定的。

要查看其工作原理,请假设该 user 表如下所示:

+ ----------- + ---------- +  - 
| 主持人| 用户| ...
+ ----------- + ---------- +  - 
| %| 根| ...
| %| 杰弗里| ...
| localhost | 根| ...
| localhost | | ...
+ ----------- + ---------- +  - 

当服务器将表读入内存时,它使用刚才描述的规则对行进行排序。 排序后的结果如下所示:

+ ----------- + ---------- +  - 
| 主持人| 用户| ...
+ ----------- + ---------- +  - 
| localhost | 根| ...
| localhost | | ...
| %| 杰弗里| ...
| %| 根| ...
+ ----------- + ---------- +  - 

当客户端尝试连接时,服务器会查看已排序的行并使用找到的第一个匹配项。 对于从连接 localhost jeffrey 两个从表匹配的行的:一个具有 Host User 的值 'localhost' '' ,和一个具有值 '%' 'jeffrey' 'localhost' 行首先按排序顺序出现,因此这是服务器使用的行。

这是另一个例子。 假设 user 表格如下所示:

+ ---------------- + ---------- +  - 
| 主持人| 用户| ...
+ ---------------- + ---------- +  - 
| %| 杰弗里| ...
| h1.example.net | | ...
+ ---------------- + ---------- +  - 

排序表如下所示:

+ ---------------- + ---------- +  - 
| 主持人| 用户| ...
+ ---------------- + ---------- +  - 
| h1.example.net | | ...
| %| 杰弗里| ...
+ ---------------- + ---------- +  - 

通过连接 jeffrey h1.example.net 由第一行匹配,而通过连接 jeffrey 来自任何主机通过第二匹配。

注意

认为对于给定的用户名,当服务器尝试查找连接匹配时,首先使用显式命名该用户的所有行,这是一种常见的误解。 这不是真的。 前面的例子中示出了这一点,其中从连接 h1.example.net 通过 jeffrey 首先由包含行匹配不 'jeffrey' 作为 User 列值,而是由没有用户名的行。 因此 jeffrey ,即使他在连接时指定了用户名,也会作为匿名用户进行身份验证。

如果您能够连接到服务器,但您的权限不是您所期望的,那么您可能正在进行其他帐户的身份验证。 要了解服务器用于验证您的帐户,请使用该 CURRENT_USER() 功能。 (请参见 第12.15节“信息函数” 。)它返回一个 格式 ,表示 匹配 表行的 假设 连接并发出以下查询: user_name@host_name User Host user jeffrey

MySQL的> SELECT CURRENT_USER();
+ ---------------- +
| CURRENT_USER()|
+ ---------------- +
| @localhost |
+ ---------------- +

此处显示的结果表明匹配的 user 表行具有空白 User 列值。 换句话说,服务器将被 jeffrey 视为匿名用户。

诊断身份验证问题的另一种方法是打印出 user 表格并手动对其进行排序,以查看第一次匹配的位置。

6.2.7访问控制,第2阶段:请求验证

建立连接后,服务器进入访问控制的第2阶段。 对于通过该连接发出的每个请求,服务器确定您要执行的操作,然后检查您是否具有足够的权限来执行此操作。 这是授权表中的特权列发挥作用的地方。 这些权限可以来自任何的 user global_grants db tables_priv columns_priv ,或 procs_priv 表。 (您可能会发现参考 第6.2.3节“授权表” 很有帮助 ,它列出了每个授权表中的列。)

user global_grants 表授予全局权限。 这些表中给定帐户的行表示无论默认数据库是什么,都在全局范围内应用的帐户权限。 例如,如果 user 表授予您 DELETE 特权,则可以从服务器主机上任何数据库的任何表中删除行。 user 表中的 权限 授予 需要它们的人(例如数据库管理员) 是明智的 对于其他用户,请将 user 表中的 所有权限保留 'N' 并且仅在更具体的级别授予权限(对于特定的数据库,表,列或例程)。 也可以在全局范围内授予数据库权限,但使用部分撤销来限制它们在特定数据库上执行(请参见 第6.2.12节“使用部分撤消的权限限制” )。

db 表授予特定于数据库的权限。 此表的范围列中的值可以采用以下形式:

  • User 值与匿名用户匹配。 非空白值与字面意义相符; 用户名中没有通配符。

  • 通配符 % _ 可以在使用 Host Db 列。 这些与操作员执行的模式匹配操作具有相同的含义 LIKE 如果要在授予权限时按字面意思使用任一字符,则必须使用反斜杠对其进行转义。 例如,要将下划线字符( _ )作为数据库名称的一部分 包括在内 \_ ,请在 GRANT 语句中 指定它

  • A '%' 或空白 Host 值表示 任何主机。

  • 一个 '%' 或空白 Db 值意味着 任何数据库。

服务器将 db 入内存并在读取 user 的同时对其进行排序 服务器排序 db 基于表 Host Db User 范围列。 user 表一样,排序将最具体的值放在最前面,将最不具体的值放在最后,当服务器查找匹配的行时,它使用它找到的第一个匹配。

tables_priv columns_priv procs_priv 表授予特定表,特定列,日常特定权限。 这些表的范围列中的值可以采用以下形式:

  • 通配符 % _ 可在使用 Host 的列。 这些与操作员执行的模式匹配操作具有相同的含义 LIKE

  • A '%' 或空白 Host 值表示 任何主机。

  • Db Table_name Column_name ,和 Routine_name 列不能包含通配符或空白。

服务器排序 tables_priv columns_priv 以及 procs_priv 基于表 Host Db User 列。 这与 db 表排序 类似 ,但更简单,因为只有 Host 列可以包含通配符。

服务器使用已排序的表来验证它收到的每个请求。 对于需要管理权限(例如 SHUTDOWN RELOAD )的 请求, 服务器仅检查 user global_privilege 表,因为这些是唯一指定管理权限的表。 如果这些表中的帐户行允许所请求的操作,则服务器授予访问权限,否则拒绝访问。 例如,如果要执行 mysqladmin shutdown 但是您的 user 表行不授予 SHUTDOWN 您权限,则服务器会在不检查 db 表的 情况下拒绝访问 (后一个表中没有 Shutdown_priv 列,所以没有必要检查它。)

对于与数据库相关的请求( INSERT UPDATE 等等),服务器首先检查用户在 user 表行中 的全局特权 (减少部分撤销所施加的任何特权限制)。 如果该行允许所请求的操作,则授予访问权限。 如果 user 表中 的全局特权 不足,则服务器 表中确定用户的特定于数据库的特权 db

该服务器会在 db 表上的匹配 Host Db 以及 User 列。 Host User 列对应连接用户的主机名和MySQL用户名。 Db 列与用户想要访问的数据库匹配。 如果没有排为 Host User ,访问被拒绝。

确定 db 表行 授予的特定于数据库的权限后 ,服务器会将它们添加到 user 授予的全局权限 中。 如果结果允许所请求的操作,则授予访问权限。 否则,服务器会依次检查用户在 tables_priv columns_priv 表中 的表和列权限 ,将这些权限添加到用户的权限,并根据结果允许或拒绝访问。 对于存储例程操作,服务器使用 procs_priv 表而不是 tables_priv columns_priv

以布尔术语表示,前面关于如何计算用户权限的描述可以总结如下:

全球特权
OR(数据库权限和主机权限)
或表权限
OR列权限
或例行特权

可能不明显的是,如果最初发现全局特权不足以满足所请求的操作,则服务器稍后会将这些特权添加到数据库,表和列特权。 原因是请求可能需要多种类型的权限。 例如,如果执行 INSERT INTO ... SELECT 语句,则需要 INSERT SELECT 权限。 您的权限可能是这样的, user 表行授予一个全局权限和 db table row专门为相关数据库授予另一个。 在这种情况下,您具有执行请求所需的权限,但服务器无法单独使用全局或数据库权限。 它必须根据组合的权限做出访问控制决策。

6.2.8添加帐户,分配权限和删除帐户

要管理MySQL帐户,请使用用于此目的的SQL语句:

帐户管理语句使服务器对基础授权表进行适当的修改,这将在 第6.2.3节“授权表” 中讨论

注意

使用诸如 ,或者 不鼓励的 语句直接修改授权表 INSERT 并且风险自负。 服务器可以自由忽略由于此类修改而变得格式错误的行。 UPDATE DELETE

对于修改授权表的任何操作,服务器检查该表是否具有预期结构,否则生成错误。 要将表更新为预期结构,请执行MySQL升级过程。 请参见 第2.11节“升级MySQL”

创建帐户的另一个选择是使用GUI工具MySQL Workbench。 此外,一些第三方程序提供MySQL帐户管理功能。 phpMyAdmin 是一个这样的计划。

本节讨论以下主题:

有关此处讨论的语句的其他信息,请参见 第13.7.1节“帐户管理语句”

创建帐户和授予权限

以下示例显示如何使用 mysql 客户端程序设置新帐户。 这些示例假定MySQL root 帐户具有 CREATE USER 其授予其他帐户 权限和所有权限。

在命令行,以MySQL root 用户 身份连接到服务器 ,在密码提示符下提供相应的密码:

shell> mysql -u root -p
输入密码:(enter root password here)

连接到服务器后,您可以添加新帐户。 以下示例使用 CREATE USER GRANT 语句设置四个帐户(您可以看到 ,替换适当的密码): 'password'

创建用户'finley'@'localhost'
  识别' password';
全部授予
  上 *。*
  去'finley'@'localhost'
  WITH GRANT OPTION;

创建用户'finley'@'%.example.com'
  识别' password';
全部授予
  上 *。*
  去'finley'@'%.example.com'
  WITH GRANT OPTION;

创建用户'admin'@'localhost'
  识别' password';
GRANT RELOAD,PROCESS
  上 *。*
  TO'admin'@'localhost';

创建用户'dummy'@'localhost';

这些语句创建的帐户具有以下属性:

  • 两个帐户的用户名为 finley 两者都是具有完全全局权限的超级用户帐户,可以执行任 'finley'@'localhost' 只有从本地主机连接时才能使用 帐户。 'finley'@'%.example.com' 帐户 '%' 在主机部分中 使用 通配符,因此可用于从 example.com 域中的 任何主机进行连接

    'finley'@'localhost' 如果有匿名用户帐户,则 帐户是必需的 localhost 如果没有该 'finley'@'localhost' 帐户, finley 则从本地主机连接 时该匿名用户帐户优先 finley 并被视为匿名用户。 这样做的原因是匿名用户帐户具有 Host 'finley'@'%' 帐户 更具体的 列值 ,因此在 user 表格排序顺序中 更早出现 (有关 user 表排序的 信息 ,请参见 第6.2.6节“访问控制,第1阶段:连接验证” 。)

  • 'admin'@'localhost' 帐户只能用于 admin 从本地主机进行连接。 它被授予全局 RELOAD PROCESS 管理权限。 这些特权使 admin 用户能够执行 mysqladmin reload mysqladmin refresh mysqladmin flush- xxx 命令,以及 mysqladmin processlist 没有授予访问任何数据库的权限。 您可以使用 GRANT 语句 添加此类权限

  • 'dummy'@'localhost' 帐户没有密码(这是不安全的,不推荐)。 此帐户只能用于从本地主机进行连接。 没有授予任何权限。 假设您将使用 GRANT 语句 向帐户授予特定权限

前面的示例在全局级别授予权限。 下一个示例创建三个帐户并授予他们较低级别的访问权限; 也就是说,对于数据库中的特定数据库或对象。 每个帐户的用户名都是 custom ,但主机名部分不同:

创建用户'自定义'@'localhost'
  识别' password';
全部授予
  在银行帐户。*
  ''custom'@'localhost';

创建用户'custom'@'host47.example.com'
  识别' password';
GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
  开支。*
  到'custom'@'host47.example.com';

创建用户'custom'@'%.example.com'
  识别' password';
GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
  在customer.addresses上
  去'custom'@'%.example.com';

这三个帐户可以使用如下:

  • 'custom'@'localhost' 帐户具有访问 bankaccount 数据库的 所有数据库级权限 该帐户可用于仅从本地主机连接到服务器。

  • 'custom'@'host47.example.com' 帐户具有访问 expenses 数据库的 特定数据库级权限 该帐户可用于仅从主机连接到服务器 host47.example.com

  • 'custom'@'%.example.com' 帐户具有特定的表级权限,可以 域中的 任何主机 访问 数据库中 addresses 由于 在帐户名称的主机部分中 使用 通配符, 该帐户可用于从域中的所有计算机连接到服务器 customer example.com %

检查帐户权限和属性

要查看帐户的权限,请使用 SHOW GRANTS

MySQL的> SHOW GRANTS FOR 'admin'@'localhost';
+ ------------------------------------------------- ---- +
| admin @ localhost的补助金
+ ------------------------------------------------- ---- +
| GRANT RELOAD,PROCESS ON *。* TO'admin'@'localhost'|
+ ------------------------------------------------- ---- +

要查看帐户的非特权属性,请使用 SHOW CREATE USER

mysql> SET print_identified_with_as_hex = ON;
mysql>SHOW CREATE USER 'admin'@'localhost'\G
*************************** 1。排******************** *******
admin @ localhost的CREATE USER:CREATE USER'admin'@'localhost'
通过'caching_sha2_password'识别
AS 0x24412430303524301D0E17054E2241362B1419313C3E44326F294133734B30792F436E77764270373039612E32445250786D43594F45354532324B6169794F47457852796E32
要求无密码存款违约帐户解锁
密码历史默认
密码重复使用间隔默认值
密码要求当前默认值

启用 print_identified_with_as_hex 系统变量(从MySQL 8.0.17开始提供)会导致 SHOW CREATE USER 显示包含不可打印字符的哈希值作为十六进制字符串而不是常规字符串文字。

撤销帐户权限

要撤消帐户权限,请使用该 REVOKE 语句。 权限可以在不同级别撤销,就像可以在不同级别授予权限一样。

撤销全球特权:

全力以赴
  上 *。*
  来自'finley'@'%.example.com';

REVOKE RELOAD
  上 *。*
  来自'admin'@'localhost';

撤消数据库级权限:

REVOKE CREATE,DROP
  开支。*
  来自'custom'@'host47.example.com';

撤消表级权限:

REVOKE INSERT,UPDATE,DELETE
  在customer.addresses上
  来自'custom'@'%.example.com';

要检查权限撤销的效果,请使用 SHOW GRANTS

MySQL的> SHOW GRANTS FOR 'admin'@'localhost';
+ --------------------------------------------- +
| admin @ localhost的补助金
+ --------------------------------------------- +
| GRANT PROCESS ON *。* TO'admin'@'localhost'|
+ --------------------------------------------- +

丢弃帐户

要删除帐户,请使用该 DROP USER 语句。 例如,要删除之前创建的一些帐户:

DROP USER'finley'@'localhost';
DROP USER'finley'@'%.example.com';
DROP USER'admin'@'localhost';
DROP USER'dummy'@'localhost';

6.2.9预留账户

MySQL安装过程的一部分是数据目录初始化(请参见 第2.10.1节“初始化数据目录” )。 在数据目录初始化期间,MySQL会创建应被视为保留的用户帐户:

  • 'root'@'localhost :用于管理目的。 此帐户具有所有权限,是系统帐户,可以执行任何操作。

    严格地说,此帐户名称不是保留的,因为某些安装会将 root 帐户 重命名为 其他名称,以避免使用众所周知的名称公开具有高权限的帐户。

  • 'mysql.sys'@'localhost' :作为 DEFINER sys 架构对象。 使用该 mysql.sys 帐户可避免DBA重命名或删除 root 帐户时 出现的问题 此帐户已锁定,因此无法用于客户端连接。

  • 'mysql.session'@'localhost' :由插件内部使用以访问服务器。 此帐户已锁定,因此无法用于客户端连接。 该帐户是系统帐户。

  • 'mysql.infoschema'@'localhost' :作为 DEFINER INFORMATION_SCHEMA 意见。 使用该 mysql.infoschema 帐户可避免DBA重命名或删除root帐户时出现的问题。 此帐户已锁定,因此无法用于客户端连接。

6.2.10使用角色

MySQL角色是一组命名的特权。 与用户帐户一样,角色可以拥有授予和撤消的权限。

可以为用户帐户授予角色,该角色向帐户授予与每个角色关联的权限。 这样可以为帐户分配权限集,并为授予个人权限提供了一种方便的替代方法,既可以概念化所需的权限分配,也可以实现它们。

以下列表总结了MySQL提供的角色管理功能:

有关各个角色操作语句(包括使用它们所需的权限)的描述,请参见 第13.7.1节“帐户管理语句” 以下讨论提供了角色使用的示例。 除非另有说明,否则此处显示的SQL语句应使用具有足够管理权限的MySQL帐户执行,例如 root 帐户。

创建角色并授予他们权限

考虑这种情况:

  • 应用程序使用名为的数据库 app_db

  • 与应用程序相关联,可以为创建和维护应用程序的开发人员以及与之交互的用户提供帐户。

  • 开发人员需要对数据库的完全访问权限。 有些用户只需要读访问权限,有些用户需要读/写访问权限。

要避免单独为可能的许多用户帐户授予权限,请将角色创建为所需权限集的名称。 这样,通过授予适当的角色,可以轻松地向用户帐户授予所需的权限。

要创建角色,请使用以下 CREATE ROLE 语句:

CREATE ROLE'app_developer','app_read','app_write';

角色名称与用户帐户名称非常相似,并且由 格式 的用户部分和主机部分组成 主机部分(如果省略)默认为 用户和主机部件可以不加引号,除非它们包含特殊字符,如 与帐户名称不同,角色名称的用户部分不能为空。 有关其他信息,请参见 第6.2.5节“指定角色名称” 'user_name'@'host_name' '%' - %

要为角色​​分配权限,请 GRANT 使用与为用户帐户分配权限相同的语法 执行 语句:

全部授予app_db。* TO'app_developer';
GRANT SELECT ON app_db。* TO'app_read';
GRANT INSERT,UPDATE,DELETE ON app_db。* TO'app_write';

现在假设您最初需要一个开发人员帐户,两个需要只读访问权限的用户帐户,以及一个需要读/写访问权限的用户帐户。 使用 CREATE USER 创建帐户:

创建用户'dev1'@'localhost'IDENTIFIED BY'dev1pass';
CREATE USER'read_user1'@'localhost'IDENTIFIED BY'read_user1pass';
CREATE USER'read_user2'@'localhost'IDENTIFIED BY'read_user2pass';
创建用户'rw_user1'@'localhost'IDENTIFIED BY'rw_user1pass';

要为每个用户帐户分配所需的权限,您可以使用 GRANT 与刚才显示的相同表单的语句,但这需要枚举每个用户的个人权限。 相反,使用 GRANT 允许授予角色而不是特权 的替代 语法:

GRANT'app_developer'TO'dev1'@'localhost';
GRANT'app_read'TO'read_user1'@'localhost','read_user2'@'localhost';
GRANT'app_read','app_write'TO'rw_user1'@'localhost';

帐户 GRANT 语句 rw_user1 授予读取和写入角色,这些角色组合在一起以提供所需的读写权限。

GRANT 授予角色的帐户语法不同的语法授予权限:有一个 ON 分配的特权条款,而没有 ON 子句来分配角色。 由于语法是不同的,因此您不能在同一语句中混合使用赋予权限和角色。 (允许为帐户分配权限和角色,但必须使用单独的 GRANT 语句,每个语句的语法都与要授予的语句相适应。)从MySQL 8.0.16开始,不能将角色授予匿名用户。

创建时的角色已锁定,没有密码,并被分配了默认的身份验证插件。 ALTER USER 具有全局 CREATE USER 权限 的用户 可以稍后使用该 语句 更改这些角色属性 。)

锁定时,不能使用角色对服务器进行身份验证。 如果解锁,则可以使用角色进行身份验证。 这是因为角色和用户都是授权标识符,它们有很多共同之处,很难区分它们。 另请参见 用户和角色互换性

定义强制性角色

通过在 mandatory_roles 系统变量 的值中命名角色,可以将角色指定为必需角色 服务器将强制角色视为授予所有用户,因此不需要将其明确授予任何帐户。

要在服务器启动时指定强制角色,请 mandatory_roles 在服务器 my.cnf 文件中 定义

的[mysqld]
mandatory_roles = '基于role1,基于role2 @本地,R3 @%。example.com'

mandatory_roles 在运行时 设置和保持 ,请使用如下语句:

SET PERSIST mandatory_roles ='role1,role2 @ localhost,r3 @%。example.com';

SET PERSIST 设置正在运行的MySQL实例的值。 它还会保存该值,使其用于后续服务器重新启动。 要更改正在运行的MySQL实例的值而不保存它以便后续重新启动,请使用 GLOBAL 关键字而不是 PERSIST 请参见 第13.7.5.1节“变量赋值的SET语法”

除了 通常设置全局系统变量所需的权限 权限 之外, 设置还 mandatory_roles 需要 ROLE_ADMIN 权限 SYSTEM_VARIABLES_ADMIN SUPER

强制角色(如明确授予的角色)在激活之前不会生效(请参阅 激活角色 )。 在登录时,如果 activate_all_roles_on_login 启用 系统变量,则 对所有授予的角色 进行角色激活,否则对于设置为默认角色的角色进行角色激活。 在运行时, SET ROLE 激活角色。

在值命名的角色 mandatory_roles 不能被撤销 REVOKE 或下降 DROP ROLE DROP USER

要防止会话默认为系统会话,具有该 SYSTEM_USER 权限 的角色 不能列在 mandatory_roles 系统变量 的值中

如果 系统表中 mandatory_roles 不存在 名为in的角色, 则不会 mysql.user 将该角色授予用户。 当服务器尝试为用户激活角色时,它不会将不存在的角色视为必需角色,并会向错误日志写入警告。 如果角色稍后创建并因此变为有效,则 FLUSH PRIVILEGES 可能需要使服务器将其视为必需 角色

SHOW GRANTS 根据 第13.7.6.21节“SHOW GRANTS语法”中 描述的规则显示强制角色

检查角色权限

要验证分配给帐户的权限,请使用 SHOW GRANTS 例如:

MySQL的> SHOW GRANTS FOR 'dev1'@'localhost';
+ ------------------------------------------------- +
| dev1 @ localhost的补助金
+ ------------------------------------------------- +
| 授予*。*给'dev1` @`localhost` |
| GRANT`app_developer` @`%`to`dev1` @`localhost` |
+ ------------------------------------------------- +

但是,这会显示每个已授予的角色,而不 会将其 扩展 为角色所代表的权限。 要显示角色权限,请添加一个 USING 子句,命名要为其显示权限的已授予角色:

MySQL的> SHOW GRANTS FOR 'dev1'@'localhost' USING 'app_developer';
+ ------------------------------------------------- --------- +
| dev1 @ localhost的补助金
+ ------------------------------------------------- --------- +
| 授予*。*给'dev1` @`localhost` |
| 在`app_db`上授予所有特权。*到`dev1` @`localhost` |
| GRANT`app_developer` @`%`to`dev1` @`localhost` |
+ ------------------------------------------------- --------- +

同样验证每个其他类型的用户:

MySQL的> SHOW GRANTS FOR 'read_user1'@'localhost' USING 'app_read';
+ ------------------------------------------------- ------- +
| 资助read_user1 @ localhost |
+ ------------------------------------------------- ------- +
| 授予使用*。*给`read_user1` @`localhost` |
| GRANT SELECT ON`app_db`。* to`read_user1` @`localhost` |
| GRANT`app_read` @`%`to`read_user1` @`localhost` |
+ ------------------------------------------------- ------- +
MySQL的> SHOW GRANTS FOR 'rw_user1'@'localhost' USING 'app_read', 'app_write';
+ ------------------------------------------------- ----------------------------- +
| 为rw_user1 @ localhost |授予补助金
+ ------------------------------------------------- ----------------------------- +
| 授予使用*。*给`rw_user1` @`localhost` |
| GRANT SELECT,INSERT,UPDATE,DELETE ON` app_db`。* to`rw_user1` @`localhost` |
| GRANT`app_read` @`%`,`app_write` @`%`to`rw_user1` @`localhost` |
+ ------------------------------------------------- ----------------------------- +

SHOW GRANTS 根据 第13.7.6.21节“SHOW GRANTS语法”中 描述的规则显示强制角色

激活角色

授予用户帐户的角色可以在帐户会话中处于活动状态或非活动状态。 如果授予的角色在会话中处于活动状态,则其权限适用; 否则,他们没有。 要确定当前会话中哪些角色处于活动状态,请使用该 CURRENT_ROLE() 功能。

默认情况下,向帐户授予角色或在 mandatory_roles 系统变量值中 命名 角色不会自动导致角色在帐户会话中变为活动状态。 例如,因为在前面的讨论中到目前为止 rw_user1 还没有激活 任何 角色,如果您连接到服务器 rw_user1 并调用该 CURRENT_ROLE() 函数,结果是 NONE (没有活动角色):

MySQL的> SELECT CURRENT_ROLE();
+ ---------------- +
| CURRENT_ROLE()|
+ ---------------- +
| 没有|
+ ---------------- +

要指定每次用户连接到服务器并进行身份验证时哪些角色应处于活动状态,请使用 SET DEFAULT ROLE 要将默认设置为先前创建的每个帐户的所有已分配角色,请使用以下语句:

将DEFAULT ROLE ALL设置为
  'DEV1' @ 'localhost' 的,
  'read_user1' @ 'localhost' 的,
  'read_user2' @ 'localhost' 的,
  'rw_user1' @ '本地主机';

现在,如果您连接为 rw_user1 ,则初始值 CURRENT_ROLE() 反映新的默认角色分配:

MySQL的> SELECT CURRENT_ROLE();
+ -------------------------------- +
| CURRENT_ROLE()|
+ -------------------------------- +
| `app_read` @`%`,`app_write` @`%`|
+ -------------------------------- +

要在用户连接到服务器时自动激活所有显式授权和强制角色,请启用 activate_all_roles_on_login 系统变量。 默认情况下,禁用自动角色激活。

在会话中,用户可以执行 SET ROLE 以更改活动角色集。 例如,对于 rw_user1

MySQL的> SET ROLE NONE; SELECT CURRENT_ROLE();
+ ---------------- +
| CURRENT_ROLE()|
+ ---------------- +
| 没有|
+ ---------------- +
MySQL的> SET ROLE ALL EXCEPT 'app_write'; SELECT CURRENT_ROLE();
+ ---------------- +
| CURRENT_ROLE()|
+ ---------------- +
| `app_read` @`%`|
+ ---------------- +
MySQL的> SET ROLE DEFAULT; SELECT CURRENT_ROLE();
+ -------------------------------- +
| CURRENT_ROLE()|
+ -------------------------------- +
| `app_read` @`%`,`app_write` @`%`|
+ -------------------------------- +

第一个 SET ROLE 语句停用所有角色。 第二个 rw_user1 有效地只读。 第三个恢复默认角色。

存储的程序和视图对象的有效用户受到 DEFINER SQL SECURITY 属性的 约束,这些 属性确定执行是在调用者或定义者上下文中发生的(参见 第24.6节“存储对象访问控制” ):

  • 在调用程序上下文中执行的存储程序和视图对象使用当前会话中处于活动状态的角色执行。

  • 在定义上下文中执行的存储程序和视图对象使用其 DEFINER 属性中 命名的用户的默认角色执行 如果 activate_all_roles_on_login 启用,则此类对象将执行授予 DEFINER 用户的 所有角色 ,包括强制角色。 对于存储的程序,如果执行的角色与默认角色不同,则应执行程序体 SET ROLE 以激活所需的角色。

撤消角色或角色权限

正如角色可以授予帐户一样,可以从帐户中撤消它们:

REVOKE roleFROM user;

mandatory_roles 系统变量值中 命名的角色 无法撤消。

REVOKE 也可以应用于角色以修改授予它的权限。 这不仅会影响角色本身,还会影响授予该角色的任何帐户。 假设您要暂时使所有应用程序用户只读。 为此,请使用 REVOKE 以撤消 app_write 角色 的修改权限

REVOKE INSERT,UPDATE,DELETE ON app_db。* FROM'app_write';

实际上,这使得角色完全没有特权,正如可以看到的那样 SHOW GRANTS (这表明该语句可以与角色一起使用,而不仅仅是用户):

MySQL的> SHOW GRANTS FOR 'app_write';
+ --------------------------------------- +
| 为app_write @%|授予补助金
+ --------------------------------------- +
| 使用*。*来'app_write` @`%`|
+ --------------------------------------- +

因为从角色中撤销特权会影响谁被分配了修改角色的任何用户的权限, rw_user1 现在已经没有表修改权限( INSERT UPDATE ,和 DELETE 不再存在):

MySQL的> SHOW GRANTS FOR 'rw_user1'@'localhost'
       USING 'app_read', 'app_write';
+ ------------------------------------------------- --------------- +
| 为rw_user1 @ localhost |授予补助金
+ ------------------------------------------------- --------------- +
| 授予使用*。*给`rw_user1` @`localhost` |
| GRANT SELECT ON`app_db`。* to`rw_user1` @`localhost` |
| GRANT`app_read` @`%`,`app_write` @`%`to`rw_user1` @`localhost` |
+ ------------------------------------------------- --------------- +

实际上, rw_user1 读/写用户已成为只读用户。 对于授予该 app_write 角色的 任何其他帐户也会发生这种情况 ,说明如何使用角色使得不必修改个人帐户的权限。

要恢复角色的修改权限,只需重新授予它们:

GRANT INSERT,UPDATE,DELETE ON app_db。* TO'app_write';

现在 rw_user1 再次具有修改权限,授予该 app_write 角色的 任何其他帐户也是如此

放下角色

要删除角色,请使用 DROP ROLE

DROP ROLE'app_read','app_write';

删除角色会从授予它的每个帐户撤消该角色。

mandatory_roles 无法删除 系统变量值中 命名的角色

用户和角色互换性

正如之前所暗示的那样 SHOW GRANTS ,它显示了用户帐户或角色的授权,帐户和角色可以互换使用。

角色和用户之间的一个区别是 CREATE ROLE 创建默认锁定 CREATE USER 的授权标识符 ,而 创建默认情况下解锁的授权标识符。 但是,区别不是不可变的,因为具有适当权限的用户可以在创建角色或用户后锁定或解锁它们。

如果数据库管理员具有特定授权标识符必须是角色的首选项,则可以使用名称方案来传达此意图。 例如,您可以 r_ 为您打算成为角色的所有授权标识符 使用 前缀 ,而不使用 任何其他内容。

角色和用户之间的另一个区别在于可用于管理它们的权限:

因此, CREATE ROLE DROP ROLE 权限不会像 CREATE USER 只允许创建和删除角色的用户 那样强大 并且可能被授予权限,并且不会执行更一般的帐户操作。

关于用户和角色的权限和可互换性,您可以将用户帐户视为角色,并将该帐户授予其他用户或角色。 其结果是将帐户的权限和角色授予其他用户或角色。

这组语句演示了您可以向用户授予用户权限,向用户授予角色,向角色授予用户权限,或向角色授予角色:

创建用户'u1';
创造角色'r1';
GRANT SELECT ON db1。* TO'u1';
GRANT SELECT ON db2。* TO'r1';
创建用户'u2';
创造角色'r2';
GRANT'u1','r1'到'u2';
GRANT'u1','r1'到'r2';

每种情况下的结果是向被授予者对象授予与授予对象相关联的特权。 执行这些语句之后,每个 u2 r2 已经从用户(授予的权限 u1 )和一个角色( r1 ):

MySQL的> SHOW GRANTS FOR 'u2' USING 'u1', 'r1';
+ ------------------------------- +
| u2 @%|的补助金
+ ------------------------------- +
| 使用*。*给'u2` @`%`|
| GRANT SELECT ON`db1`。* TO`u2` @`%`|
| GRANT选择`db2`。* TO`u2` @`%`|
| GRANT`u1` @`%`,`r1` @`%`to`u2` @`%`|
+ ------------------------------- +
MySQL的> SHOW GRANTS FOR 'r2' USING 'u1', 'r1';
+ ------------------------------- +
| r2 @%|的补助金
+ ------------------------------- +
| 授予使用*。*至`r2` @`%`|
| GRANT选择`db1`。* TO`r2` @`%`|
| GRANT选择`db2`。* to`r2` @`%`|
| GRANT`u1` @`%`,`r1` @`%`to`r2` @`%`|
+ ------------------------------- +

前面的示例仅是说明性的,但用户帐户和角色的可互换性具有实际应用,例如在以下情况中:假设遗留应用程序开发项目在MySQL中的角色出现之前开始,因此与项目关联的所有用户帐户都是直接授予权限(而不是通过授予角色授予权限)。 其中一个帐户是最初被授予特权的开发人员帐户,如下所示:

创建用户'old_app_dev'@'localhost'识别'old_app_devpass';
在old_app上全部授予。*''old_app_dev'@'localhost';

如果此开发人员离开项目,则必须将权限分配给另一个用户,或者如果开发活动已扩展,则可能将多个用户分配。 以下是处理该问题的一些方法:

  • 不使用角色:更改帐户密码,以便原始开发人员无法使用它,并让新开发人员使用该帐户:

    ALTER USER'old_app_dev'@'localhost'ENFENTIFIED BY' new_password';
    
  • 使用角色:锁定帐户以防止任何人使用它来连接到服务器:

    ALTER USER'old_app_dev'@'localhost'ACCOUNT LOCK;
    

    然后将该帐户视为一个角色。 对于项目的每个新开发人员,创建一个新帐户并向其授予原始开发人员帐户:

    CREATE USER'new_app_dev1'@'localhost'ENFENTIFIED BY' new_password';
    GRANT'old_app_dev'@'localhost'TO'new_app_dev1'@'localhost';
    

    效果是将原始开发者帐户权限分配给新帐户。

6.2.11帐户类别

从MySQL 8.0.16开始,MySQL基于 SYSTEM_USER 特权 结合了用户帐户类别的概念

系统和常规账户

MySQL结合了用户帐户类别的概念,系统和常规用户根据他们是否拥有 SYSTEM_USER 权限进行 区分

  • 具有该 SYSTEM_USER 权限的用户是系统用户。

  • 没有 SYSTEM_USER 权限的用户是普通用户。

SYSTEM_USER 权限对给定用户可以应用其他权限的帐户有影响,以及用户是否受到其他帐户的保护:

  • 系统用户可以修改系统和常规帐户。 也就是说,拥有对常规帐户执行给定操作的适当权限的用户通过拥有 SYSTEM_USER 也可以对系统帐户执行操作来 启用 系统帐户只能由具有适当权限的系统用户修改,而不能由常规用户修改。

  • 具有适当权限的常规用户可以修改常规帐户,但不能修改系统帐户。 具有适当权限的系统和常规用户都可以修改常规帐户。

如果用户具有在常规帐户上执行给定操作的适当权限,则 SYSTEM_USER 允许用户还对系统帐户执行操作。 SYSTEM_USER 并不意味着任何其他特权,因此执行给定帐户操作的能力仍然取决于拥有任何其他所需特权。 例如,如果用户可以授予 常规帐户 SELECT UPDATE 权限,那么 SYSTEM_USER 用户也可以授予 SELECT UPDATE 系统帐户。

通过保护具有 SYSTEM_USER 来自 没有该 权限的帐户 权限的帐户, 系统和常规帐户之间的区别可以更好地控制某些帐户管理问题 例如,该 CREATE USER 权限不仅可以创建新帐户,还可以修改和删除现有帐户。 如果没有系统用户概念,拥有该 CREATE USER 权限 的用户 可以修改或删除任何现有帐户,包括该 root 帐户。 系统用户的概念允许限制对 root 帐户(本身是系统帐户)的 修改, 因此它们只能由系统用户进行。 定期用户 CREATE USER 权限仍然可以修改或删除现有帐户,但只能修改或删除常规帐户。

受SYSTEM_USER权限影响的操作

SYSTEM_USER 权限会影响这些操作:

  • 帐户操纵。

    帐户操作包括创建和删除帐户,授予和撤消权限,更改帐户身份验证特征(如凭据或身份验证插件)以及更改其他帐户特征(如密码到期策略)。

    SYSTEM_USER 使用帐户管理语句(例如 CREATE USER 和) 操纵系统帐户需要 权限 GRANT 要防止帐户以这种方式修改系统帐户,请将其设为常规帐户,而不是授予其 SYSTEM_USER 权限。 (但是,要完全保护系统帐户不受常规帐户的影响,您还必须保留对常规帐户 mysql 系统架构的 修改权限 。请参阅 保护系统帐户 免受常规帐户 操作 。)

  • 杀死当前会话和在其中执行的语句。

    要杀死使用该 SYSTEM_USER 权限 执行的会话或语句, SYSTEM_USER 除了任何其他所需权限外 ,您自己的会话还必须具有该 权限( CONNECTION_ADMIN SUPER

    在MySQL 8.0.16之前, CONNECTION_ADMIN 或者 SUPER 足以杀死任何会话或语句。

  • 设置 DEFINER 存储的对象。

    要将 DEFINER 存储对象 属性 设置 为具有该 SYSTEM_USER 权限 的帐户, SYSTEM_USER 除了任何其他所需权限之外 ,您还必须具有该 权限( SET_USER_ID 或者 SUPER

    在MySQL 8.0.16之前, SET_USER_ID 或者 SUPER 足以 DEFINER 为存储对象 指定任何 值。

  • 指定强制角色。

    具有该 SYSTEM_USER 权限的 角色 不能列在该值中 mandatory_roles 系统变量

    在MySQL 8.0.16之前,可以列出任何角色 mandatory_roles

系统和常规会话

在服务器内执行的会话被区分为系统或常规会话,类似于系统和常规用户之间的区别:

  • 拥有该 SYSTEM_USER 权限的会话是系统会话。

  • 不具有 SYSTEM_USER 权限的会话是常规会话。

常规会话只能执行常规用户允许的操作。 系统会话还能够执行仅允许系统用户执行的操作。

会话拥有的权限是直接授予其基础帐户的权限,以及授予会话中当前活动的所有角色的权限。 因此,会话可能是系统会话,因为其帐户已被 SYSTEM_USER 直接 授予 权限,或者因为会话已激活具有 以下 权限的角色 SYSTEM_USER 特权 授予会话中未激活的帐户的角色不会影响会话权限。

由于激活和停用角色可以更改会话拥有的权限,因此会话可以从常规会话更改为系统会话,反之亦然。 如果会话激活或停用具有该 SYSTEM_USER 权限 的角色, 则会立即在该会话中立即进行常规会话和系统会话之间的适当更改:

  • 如果常规会话使用该 SYSTEM_USER 权限 激活角色 ,则会话将成为系统会话。

  • 如果系统会话取消激活具有该 SYSTEM_USER 权限 的角色 ,则会话将成为常规会话,除非具有该 SYSTEM_USER 权限的 其他某个角色 保持活动状态。

这些操作对现有会话没有影响:

  • 如果 SYSTEM_USER 从帐户授予或撤消权限,则帐户的现有会话在常规会话和系统会话之间不会更改。 授予或撤消操作仅影响帐户后续连接的会话。

  • 由会话中调用的存储对象执行的语句以系统或父会话的常规状态执行,即使对象 DEFINER 属性命名系统帐户也是如此。

由于角色激活仅影响会话而非影响帐户,因此授予具有 SYSTEM_USER 常规帐户权限 的角色 不会保护该帐户免受常规用户的影响。 该角色仅保护已激活角色的帐户的会话,并仅保护会话,防止被常规会话杀死。

保护系统帐户免受普通帐户的操纵

帐户操作包括创建和删除帐户,授予和撤消权限,更改帐户身份验证特征(如凭据或身份验证插件)以及更改其他帐户特征(如密码到期策略)。

帐户操作可以通过两种方式完成:

  • 通过使用账户管理语句,例如 CREATE USER GRANT 这是首选方法。

  • 通过使用 INSERT 等语句直接授予表修改 UPDATE 不鼓励使用此方法,但对于 mysql 包含授权表 系统架构 具有适当权限的用户可以使用此方法

要完全保护系统帐户不被给定帐户修改,请将其设为常规帐户,并且不授予其对 mysql 架构的 修改权限

  • SYSTEM_USER 使用帐户管理语句操作系统帐户需要 权限。 要防止帐户以这种方式修改系统帐户,请通过不授予帐户使其成为常规帐户 SYSTEM_USER 这包括不授予 SYSTEM_USER 授予该帐户的任何角色。

  • mysql 即使修改帐户是常规帐户 模式的 权限也可以 通过直接修改授权表来操作系统帐户。 要限制通过常规帐户对系统帐户进行​​未经授权的直接修改,请不要将 mysql 架构的 修改权限授予 帐户(或授予该帐户的任何角色)。 如果常规帐户必须具有适用于所有模式的全局特权, mysql 则可以使用部分撤消强加的特权限制来防止模式修改。 请参见 第6.2.12节“使用部分撤消的权限限制”

注意

与扣除 SYSTEM_USER 权限(防止帐户修改系统帐户而非常规帐户)不同,隐藏 mysql 模式权限会阻止帐户修改系统帐户以及常规帐户。 这应该不是问题,因为如上所述,不鼓励直接授权表修改。

假设您要创建一个 u1 对所有模式具有所有权限 的用户 ,除了 u1 应该是普通用户而无法修改系统帐户。 假设 partial_revokes 启用 系统变量,请 u1 按如下方式 配置

创建用户u1标识' password';

全部授予*。*至u1 with GRANT OPTION;
-  GRANT ALL包括SYSTEM_USER,所以此时
-  u1可以操纵系统或常规帐户

REVOKE SYSTEM_USER ON *。* FROM u1;
- 撤销SYSTEM_USER使u1成为普通用户;
- 现在u1可以使用帐户管理语句
- 仅操纵常规帐户

REVOKE ALL ON mysql。* FROM u1;
- 这种部分撤销直接阻止了u1
- 修改授权表以操纵帐户

要阻止 mysql 帐户进行 所有 系统架构访问,请撤消对 mysql 架构的 所有权限 ,如刚才所示。 还可以允许部分 mysql 模式访问,例如只读访问。 下面的示例创建具有一个帐户 SELECT INSERT UPDATE ,和 DELETE 特权全球范围内为所有的模式,但只 SELECT mysql 模式:

创建用户u2标识' password';
GRANT SELECT,INSERT,UPDATE,DELETE ON *。* TO u2;
REVOKE INSERT,UPDATE,DELETE ON mysql。* FROM u2;

另一种可能性是撤消所有 mysql 模式权限,但授予对特定 mysql 表或列的 访问权限 即使部分撤销,也可以这样做 mysql 以下语句启用 u1 mysql 模式 内的 只读访问权限 ,但仅对 db 表的表 Host User 列进行 user

创建用户u3标识' password';
全部授予*。*至u3;
REVOKE ALL ON mysql。* FROM u3;
GRANT SELECT on mysql.db TO u3;
GRANT SELECT(主机,用户)ON mysql.user TO u3;

6.2.12使用部分撤销权限的权限限制

在MySQL 8.0.16之前,除了某些模式之外,不可能授予全局适用的权限。 从MySQL 8.0.16开始,如果 partial_revokes 启用 系统变量 ,则可以 实现。 具体而言,对于具有全局级别权限的用户, partial_revokes 可以撤消特定模式的权限,同时为其他模式保留特权。 这样强加的权限限制可能对管理具有全局权限但不允许访问某些模式的帐户有用。 例如,可以允许帐户修改除 mysql 系统架构 中的表之外的任何表

注意

为简洁起见, CREATE USER 此处显示的语句不包括密码。 对于生产用途,请始终指定帐户密码。

使用部分撤消

partial_revokes 系统变量控制权限限制是否可以放在账户。 默认情况下, partial_revokes 禁用并尝试部分撤消全局权限会产生错误:

mysql> CREATE USER u1;
mysql> GRANT SELECT, INSERT ON *.* TO u1;
mysql>REVOKE INSERT ON world.* FROM u1;
ERROR 1141(42000):在主机'%'上没有为用户'u1'定义此类授权

要允许 REVOKE 操作,请启用 partial_revokes

SET PERSIST partial_revokes = ON;

SET PERSIST 设置正在运行的MySQL实例的值。 它还会保存该值,使其用于后续服务器重新启动。 要更改正在运行的MySQL实例的值而不保存它以便后续重新启动,请使用 GLOBAL 关键字而不是 PERSIST 请参见 第13.7.5.1节“变量赋值的SET语法”

partial_revokes 启用,部分撤销成功:

mysql> REVOKE INSERT ON world.* FROM u1;
mysql>SHOW GRANTS FOR u1;
+ ------------------------------------------ +
| 为u1 @%|拨款
+ ------------------------------------------ +
| GRANT SELECT,INSERT ON *。* to`u1` @`%`|
| REVOKE INSERT ON`world`。* FROM`u1` @`%`|
+ ------------------------------------------ +

SHOW GRANTS 列出部分撤销作为 REVOKE 其输出中的语句。 结果表明 u1 具有全局 SELECT INSERT 特权,除了 INSERT 不能对 world 模式中的 表执行 也就是说, u1 world 表的 访问 是只读的。

服务器记录通过 mysql.user 系统表 中的部分撤销实现的权限限制 如果帐户已部分撤消,则其 User_attributes 列值具有以下 Restrictions 属性:

MySQL的> SELECT User, Host, User_attributes->>'$.Restrictions'
       FROM mysql.user WHERE User_attributes->>'$.Restrictions' <> '';
+ ------ + ------ + ----------------------------------- ------------------- +
| 用户| 主持人| User_attributes  -  >>'$。限制'|
+ ------ + ------ + ----------------------------------- ------------------- +
| u1 | %| [{“数据库”:“世界”,“特权”:[“INSERT”]}] |
+ ------ + ------ + ----------------------------------- ------------------- +
注意

虽然可以对任何模式进行部分撤销 mysql ,但特别是 系统模式的 特权限制 可用作防止常规帐户修改系统帐户的策略的一部分。 请参阅 通过常规帐户保护系统帐户免受操纵

部分撤销操作受以下条件限制:

  • 部分撤销必须按字面意思命名模式。 不允许 包含 % _ SQL通配符的 模式名称 (例如 myschema% )。

  • 可以使用部分撤销对不存在的模式进行限制,但前提是全局授予撤销的特权。 如果未全局授予权限,则为不存在的模式撤消该权限会产生错误。

  • 部分撤销仅适用于架构级别。 对于仅全局(例如 FILE BINLOG_ADMIN )或表,列或例程特权 应用的特权,不能使用部分撤消

如前所述,模式级特权的部分撤销在 SHOW GRANTS 输出中 显示 REVOKE 语句。 这与 SHOW GRANTS 表示 普通 架构级特权的方式不同:

  • 授予时,模式级特权由 GRANT 输出中 的自己的 语句 表示

    mysql> CREATE USER u1;
    mysql> GRANT UPDATE ON mysql.* TO u1;
    mysql> GRANT DELETE ON world.* TO u1;
    mysql>SHOW GRANTS FOR u1;
    + --------------------------------------- +
    | 为u1 @%|拨款
    + --------------------------------------- +
    | 授予使用*。*给'u1` @`%`|
    | 授予更新`mysql`。* to`u1` @`%`|
    | GRANT DELETE ON`world`。* to`u1` @`%`|
    + --------------------------------------- +
    
  • 撤消时,架构级特权会从输出中消失。 它们不作为 REVOKE 陈述 出现

    mysql> REVOKE UPDATE ON mysql.* FROM u1;
    mysql> REVOKE DELETE ON world.* FROM u1;
    mysql>SHOW GRANTS FOR u1;
    + -------------------------------- +
    | 为u1 @%|拨款
    + -------------------------------- +
    | 授予使用*。*给'u1` @`%`|
    + -------------------------------- +
    

当用户授予权限时,授予者对该权限的任何限制都由被授权者继承,除非被授权者已经拥有没有该限制的权限。 考虑以下两个用户,其中一个用户具有全局 SELECT 权限:

创建用户u1,u2;
GRANT SELECT ON *。* TO u2;

假设管理用户 admin 具有全局但部分撤销的 SELECT 权限:

mysql> CREATE USER admin;
mysql> GRANT SELECT ON *.* TO admin WITH GRANT OPTION;
mysql> REVOKE SELECT ON mysql.* FROM admin;
mysql>SHOW GRANTS FOR admin;
+ ------------------------------------------------- ----- +
| 管理员@%|的拨款
+ ------------------------------------------------- ----- +
| GRANT SELECT ON *。* TO`admin` @`%`WITH GRANT OPTION |
| REVOKE SELECT on`mysql`。* FROM`admin` @`%`|
+ ------------------------------------------------- ----- +

如果 admin 补助 SELECT 全球范围内 u1 u2 ,其结果相差为每个用户:

  • 如果 全局 admin 授予( 权限开始),则 继承 权限限制: SELECT u1 SELECT u1 admin

    mysql> GRANT SELECT ON *.* TO u1;
    mysql>SHOW GRANTS FOR u1;
    + ------------------------------------------ +
    | 为u1 @%|拨款
    + ------------------------------------------ +
    | GRANT SELECT ON *。* TO`u1` @`%`|
    | REVOKE SELECT on`mysql`。* FROM`u1` @`%`|
    + ------------------------------------------ +
    
  • 另一方面, u2 已经拥有一个 SELECT 没有限制 的全球 特权。 GRANT 只能添加到受让人现有的特权,而不是减少他们,所以如果 admin 授予 SELECT 在全球范围内 u2 u2 不继承的 admin 限制:

    mysql> GRANT SELECT ON *.* TO u2;
    mysql>SHOW GRANTS FOR u2;
    + --------------------------------- +
    | u2 @%|的补助金
    + --------------------------------- +
    | GRANT SELECT ON *。* TO`u2` @`%`|
    + --------------------------------- +
    

如果 GRANT 语句包含 子句,则应用的权限限制是由子句指定的用户/角色组合上的权限,而不是执行该语句的用户的权限限制。 有关该 子句的 信息 ,请参见 第13.7.1.6节“GRANT语法” AS user AS

授予帐户的新权限的限制将添加到该帐户的任何现有限制中:

mysql> CREATE USER u1;
mysql> GRANT SELECT, INSERT, UPDATE, DELETE ON *.* TO u1;
mysql> REVOKE INSERT ON mysql.* FROM u1;
mysql>SHOW GRANTS FOR u1;
+ ------------------------------------------------- -------- +
| 为u1 @%|拨款
+ ------------------------------------------------- -------- +
| GRANT SELECT,INSERT,UPDATE,DELETE ON *。* TO`u1` @`%`|
| REVOKE INSERT ON`mysql`。* FROM`u1` @`%`|
+ ------------------------------------------------- -------- +
mysql> REVOKE DELETE, UPDATE ON db2.* FROM u1;
mysql>SHOW GRANTS FOR u1;
+ ------------------------------------------------- -------- +
| 为u1 @%|拨款
+ ------------------------------------------------- -------- +
| GRANT SELECT,INSERT,UPDATE,DELETE ON *。* TO`u1` @`%`|
| REVOKE UPDATE,删除`db2`。* FROM`u1` @`%`|
| REVOKE INSERT ON`mysql`。* FROM`u1` @`%`|
+ ------------------------------------------------- -------- +

特权限制聚合既适用于显式部分撤销特权(如刚才所示),也适用于从执行语句的用户或 子句中 提到的用户隐式继承限制的情况 AS user

如果帐户对架构具有权限限制:

  • 该帐户无法向其他帐户授予对受限架构或其中任何对象的特权。

  • 另一个没有限制的帐户可以为受限制的帐户或其中的对象授予受限帐户的权限。 假设一个不受限制的用户执行这些语句:

    创建用户u1;
    GRANT SELECT,INSERT,UPDATE ON *。* TO u1;
    REVOKE SELECT,INSERT,UPDATE on mysql。* FROM u1;
    GRANT SELECT ON mysql.user TO u1;  -  grant table特权
    GRANT SELECT(主机,用户)ON mysql.db TO u1;  - 授予列权限
    

    生成的帐户具有这些权限,能够在受限模式中执行有限的操作:

    MySQL的> SHOW GRANTS FOR u1;
    + ------------------------------------------------- ---------- +
    | 为u1 @%|拨款
    + ------------------------------------------------- ---------- +
    | GRANT SELECT,INSERT,UPDATE ON *。* to`u1` @`%`|
    | REVOKE SELECT,INSERT,UPDATE on`mysql`。* FROM`u1` @`%`|
    | GRANT SELECT(`Host`,`User`)on`mysql` .db` to`u1` @`%`|
    | GRANT SELECT on`mysql` .user` TO`u1` @`%`|
    + ------------------------------------------------- ---------- +
    

如果帐户对全局权限有限制,则通过以下任何操作都会删除该限制:

  • 通过对权限没有限制的帐户向帐户全局授予权限。

  • 在架构级别授予权限。

  • 全球撤销特权。

考虑一个 u1 全局拥有多个权限但受到限制的用户 INSERT UPDATE 并且 DELETE

mysql> CREATE USER u1;
mysql> GRANT SELECT, INSERT, UPDATE, DELETE ON *.* TO u1;
mysql> REVOKE INSERT, UPDATE, DELETE ON mysql.* FROM u1;
mysql>SHOW GRANTS FOR u1;
+ ------------------------------------------------- --------- +
| 为u1 @%|拨款
+ ------------------------------------------------- --------- +
| GRANT SELECT,INSERT,UPDATE,DELETE ON *。* TO`u1` @`%`|
| REVOKE INSERT,UPDATE,DELETE ON`mysql`。* FROM`u1` @`%`|
+ ------------------------------------------------- --------- +

u1 从没有限制的帐户 全局授予权限 会删除权限限制。 例如,要删除 INSERT 限制:

mysql> GRANT INSERT ON *.* TO u1;
mysql>SHOW GRANTS FOR u1;
+ ------------------------------------------------- -------- +
| 为u1 @%|拨款
+ ------------------------------------------------- -------- +
| GRANT SELECT,INSERT,UPDATE,DELETE ON *。* TO`u1` @`%`|
| REVOKE UPDATE,删除`mysql`。* FROM`u1` @`%`|
+ ------------------------------------------------- -------- +

在架构级别授予权限以 u1 删除权限限制。 例如,要删除 UPDATE 限制:

mysql> GRANT UPDATE ON mysql.* TO u1;
mysql>SHOW GRANTS FOR u1;
+ ------------------------------------------------- -------- +
| 为u1 @%|拨款
+ ------------------------------------------------- -------- +
| GRANT SELECT,INSERT,UPDATE,DELETE ON *。* TO`u1` @`%`|
| REVOKE DELETE ON`mysql`。* FROM`u1` @`%`|
+ ------------------------------------------------- -------- +

撤消全局权限会删除该权限,包括对其的任何限制。 例如,要删除 DELETE 限制(以删除所有 DELETE 访问权 为代价 ):

mysql> REVOKE DELETE ON *.* FROM u1;
mysql>SHOW GRANTS FOR u1;
+ ------------------------------------------------- +
| 为u1 @%|拨款
+ ------------------------------------------------- +
| GRANT SELECT,INSERT,UPDATE ON *。* to`u1` @`%`|
+ ------------------------------------------------- +

如果帐户在全局级别和架构级别都具有权限,则必须在架构级别将其撤消两次以实现部分撤消。 假设 u1 具有这些权限, INSERT 全局和 world 模式 都保存在 哪里

mysql> CREATE USER u1;
mysql> GRANT SELECT, INSERT ON *.* TO u1;
mysql> GRANT INSERT ON world.* TO u1;
mysql>SHOW GRANTS FOR u1;
+ ----------------------------------------- +
| 为u1 @%|拨款
+ ----------------------------------------- +
| GRANT SELECT,INSERT ON *。* to`u1` @`%`|
| GRANT INSERT ON`world`。* to`u1` @`%`|
+ ----------------------------------------- +

撤销 INSERT world 会撤销模式级特权( SHOW GRANTS 不再显示模式级 GRANT 语句):

mysql> REVOKE INSERT ON world.* FROM u1;
mysql>SHOW GRANTS FOR u1;
+ ----------------------------------------- +
| 为u1 @%|拨款
+ ----------------------------------------- +
| GRANT SELECT,INSERT ON *。* to`u1` @`%`|
+ ----------------------------------------- +

撤销 INSERT world 再次执行全局权限(的部分撤销 SHOW GRANTS ,现在包括模式级 REVOKE 语句):

mysql> REVOKE INSERT ON world.* FROM u1;
mysql>SHOW GRANTS FOR u1;
+ ------------------------------------------ +
| 为u1 @%|拨款
+ ------------------------------------------ +
| GRANT SELECT,INSERT ON *。* to`u1` @`%`|
| REVOKE INSERT ON`world`。* FROM`u1` @`%`|
+ ------------------------------------------ +

部分撤销与显式模式授权

为了提供对某些模式而非其他模式的帐户的访问,部分撤销提供了在不授予全局特权的情况下显式授予模式级访问权的方法的替代方法。 这两种方法有不同的优点和缺点。

授予模式级特权而不是全局特权:

  • 添加新架构:默认情况下,现有帐户无法访问架构。 对于应该可以访问架构的任何帐户,DBA必须授予架构级访问权限。

  • 添加新帐户:DBA必须为帐户应有权访问的每个模式授予模式级访问权限。

与部分撤销一起授予全局权限:

  • 添加新架构:具有全局特权的现有帐户可以访问架构。 对于架构应该无法访问的任何此类帐户,DBA必须添加部分撤销。

  • 添加新帐户:DBA必须授予全局权限,并且必须对每个受限制的模式进行部分撤销。

对于访问仅限于少数模式的帐户,使用显式模式级别授权的方法更方便。 对于除了少数几个以外的所有模式具有广泛访问权限的帐户,使用部分撤销的方法更方便。

禁用部分撤消

启用后, partial_revokes 如果任何帐户具有权限限制 则无法禁用。 如果存在任何此类帐户,则禁用 partial_revokes 失败:

partial_revokes 在存在限制时 禁用 ,必须首先删除限制:

  1. 确定哪些帐户有部分撤销:

    SELECT User,Host,User_attributes  -  >>'$。Restrictions'
    FROM mysql.user WHERE User_attributes  -  >>'$。Restrictions'<>'';
    
  2. 对于每个此类帐户,请删除其权限限制。 假设上一步显示帐户 u1 有这些限制:

    [{“数据库”:“世界”,“权限”:[“INSERT”,“DELETE”]
    

    可以通过多种方式删除限制:

    • 全局授予权限,没有任何限制:

      GRANT INSERT,DELETE ON *。* TO u1;
      
    • 在架构级别授予权限:

      GRANT INSERT,DELETE ON world。* TO u1;
      
    • 全局撤销权限(假设不再需要它们):

      REVOKE INSERT,DELETE ON *。* FROM u1;
      
    • 删除帐户本身(假设不再需要):

      DROP USER u1;
      

删除所有权限限制后,可以禁用部分撤消:

SET PERSIST partial_revokes = OFF;

部分撤销和复制

在复制方案中,如果 partial_revokes 在任何主机上启用,则必须在所有主机上启用它。 否则, REVOKE 部分撤销全局特权的语句对发生复制的所有主机的影响不同,可能导致复制不一致或错误。

6.2.13权限更改生效时

如果 没有 选项 启动 mysqld 服务器 --skip-grant-tables ,它会在启动序列期间将所有授权表内容读入内存。 内存表在此时对访问控制有效。

如果使用帐户管理语句间接修改授权表,服务器会注意到这些更改并立即再次将授权表加载到内存中。 帐户管理声明在 第13.7.1节“帐户管理声明”中描述 实例包括 GRANT REVOKE SET PASSWORD ,和 RENAME USER

如果你修改授权表直接使用的语句,例如 INSERT UPDATE DELETE (不推荐),该变化对特权的效果检查,直到你要么告诉服务器重新加载表或重新启动它。 因此,如果直接更改授权表但忘记重新加载它们,则在 重新启动服务器之前 ,更改 不会生效 这可能会让您想知道为什么您的更改似乎没有任何区别!

要告诉服务器重新加载授权表,请执行flush-privileges操作。 这可以通过发出 FLUSH PRIVILEGES 语句或执行 mysqladmin flush-privileges mysqladmin reload 命令来完成。

授权表重新加载会影响每个现有客户端会话的权限,如下所示:

  • 表和列权限更改将随客户端的下一个请求生效。

  • 数据库权限更改将在客户端下次执行 语句 时生效 USE db_name

    注意

    客户端应用程序可以缓存数据库名称 因此,如果不实际更改为不同的数据库,这些效果可能对他们不可见。

  • 对于已连接的客户端,全局权限和密码不受影响。 这些更改仅在后续连接的会话中生效。

对会话中的活动角色集的更改将立即生效,仅适用于该会话。 SET ROLE 语句执行会话角色激活和取消激活(请参见 第13.7.1.11节“SET ROLE语法” )。

如果使用该 --skip-grant-tables 选项 启动服务器 ,则它不会读取授权表或实现任何访问​​控制。 任何用户都可以连接并执行任何操作, 这是不安全的。 为了使服务器因此开始读取表并启用访问检查,请刷新权限。

6.2.14分配帐户密码

连接到MySQL服务器的客户端所需的凭据可以包含密码。 本节介绍如何为MySQL帐户分配密码。

MySQL将凭证存储在 系统数据库 user 表中 mysql 分配或修改密码的操作仅允许具有该 CREATE USER 特权的 用户 ,或者 mysql 数据库的 INSERT 特权(创建新帐户的 UPDATE 特权,修改现有帐户的特权)。 如果 read_only 启用 系统变量,则使用帐户修改语句,例如 CREATE USER ALTER USER 另外需要 CONNECTION_ADMIN SUPER 特权。

此处的讨论仅总结了最常见的密码赋值语句的语法。 有关其他可能性的完整详细信息,请参见 第13.7.1.3节“创建用户语法” 第13.7.1.1节“ALTER USER语法” 第13.7.1.10节“SET PASSWORD语法”

MySQL使用插件来执行客户端身份验证; 请参见 第6.2.17节“可插入的身份验证” 在密码分配语句中,与帐户关联的身份验证插件执行指定的明文密码所需的任何散列。 这使MySQL能够在将密码存储在 mysql.user 系统表 之前对其进行模糊处理 对于此处描述的语句,MySQL会自动散列指定的密码。 还有语法的 CREATE USER ALTER USER 从字面上指定许可证哈希值。 有关详细信息,请参阅这些语句的说明。

要在创建新帐户时指定密码,请使用 CREATE USER 并包含 IDENTIFIED BY 子句:

创建用户'jeffrey'@'localhost'标识' password';

CREATE USER 还支持指定帐户身份验证插件的语法。 请参见 第13.7.1.3节“创建用户语法”

要为现有帐户分配或更改密码,请使用 ALTER USER 带有 IDENTIFIED BY 子句 语句

ALTER USER'jeffrey'@'localhost'ENFENTIFIED BY' password';

如果您未以匿名用户身份进行连接,则可以更改自己的密码,而无需按字面指定自己的帐户:

ALTER USER USER()通过' password' 标识;

要从命令行更改帐户密码,请使用 mysqladmin 命令:

mysqladmin -u user_name-h host_name密码“ password

此命令设置密码的帐户是 mysql.user 系统表中与 匹配 user_name User 行以及 Host 列中 连接 的客户端主机

警告

使用 mysqladmin 设置密码 应该被认为是 不安全的 在某些系统上,您的密码对系统状态程序(例如 ps) 可见 ,其他用户可以调用它来显示命令行。 MySQL客户端通常在初始化序列期间用零覆盖命令行密码参数。 但是,仍然存在一个短暂的间隔,在该间隔期间值是可见的。 此外,在某些系统上,此覆盖策略无效,并且 ps 仍然可以看到密码 (SystemV Unix系统和其他人可能遇到这个问题。)

如果您使用的是MySQL Replication,请注意,目前,复制从属设备使用的密码作为 CHANGE MASTER TO 语句的 一部分 实际上限制为32个字符; 如果密码较长,则会截断任何多余的字符。 这不是由于MySQL服务器通常施加的任何限制,而是MySQL Replication特有的问题。 (有关更多信息,请参阅Bug#43439。)

6.2.15密码管理

MySQL支持这些密码管理功能:

  • 密码过期,要求定期更改密码。

  • 密码重用限制,以防止再次选择旧密码。

  • 密码验证,要求密码更改还指定要替换的当前密码。

  • 双密码,使客户端可以使用主密码或二级密码进行连接。

  • 密码强度评估,要求强密码。

以下部分介绍了这些功能,密码强度评估除外,它使用 validate_password 插件 实现, 并在 第6.4.3节“密码验证组件”中进行了介绍

重要

MySQL使用 mysql 系统数据库中的 表实现密码管理功能 如果从早期版本升级MySQL,则系统表可能不是最新的。 在这种情况下,服务器会在启动过程中将与此类似的消息写入错误日志(具体数字可能会有所不同):

[错误] mysql.user的列数错误。预期
49,发现47.该表可能已损坏
[警告] ACL表mysql.password_history缺失。
某些操作可能会失败。

要解决此问题,请执行MySQL升级过程。 请参见 第2.11节“升级MySQL” 在此之前, 无法更改密码。

注意

这里所描述的密码管理功能仅适用于内部存储凭据的账户 mysql.user 系统表( mysql_native_password sha256_password ,或 caching_sha2_password )。 对于使用对外部凭据系统执行身份验证的插件的帐户,还必须在该系统外部处理密码管理。

密码过期策略

MySQL使数据库管理员可以手动使帐户密码过期,并建立自动密码过期的策略。 可以在全局建立到期策略,并且可以将个人帐户设置为遵循全局策略或使用特定的每帐户行为覆盖全局策略。

要手动过期帐户密码,请使用以下 ALTER USER 语句:

ALTER USER'jeffrey'@'localhost'PASSWORD EXPIRE;

此操作将密码在 mysql.user 系统表 的相应行中标记为已过期

根据策略的密码到期是自动的,并且基于密码年龄,对于给定帐户,密码年龄根据其最近密码更改的日期和时间进行评估。 mysql.user 系统表显示为每个帐户时,其上次更改口令,服务器自动将作为客户端连接的过期时间,如果它的年龄比它允许生存更大的口令。 这适用于没有明确的手动密码到期。

要全局建立自动密码到期策略,请使用 default_password_lifetime 系统变量。 其默认值为0,禁用自动密码到期。 如果值为 default_password_lifetime 正整数 N ,则表示允许的密码生存期,因此必须每天更改密码 N

例子:

  • 要建立密码具有大约六个月生命周期的全局策略,请在服务器 my.cnf 文件中 使用以下行启动服务器

    的[mysqld]
    default_password_lifetime = 180
    
  • 要建立密码永不过期的全局策略,请设置 default_password_lifetime 为0:

    的[mysqld]
    default_password_lifetime = 0
    
  • default_password_lifetime 也可以在运行时设置和持久化:

    SET PERSIST default_password_lifetime = 180;
    SET PERSIST default_password_lifetime = 0;
    

    SET PERSIST 设置正在运行的MySQL实例的值。 它还保存了用于后续服务器重启的值; 请参见 第13.7.5.1节“变量赋值的SET语法” 要更改正在运行的MySQL实例的值而不保存它以便后续重新启动,请使用 GLOBAL 关键字而不是 PERSIST

全局密码到期策略适用于尚未设置为覆盖它的所有帐户。 要为个人帐户建立策略,请使用 语句 PASSWORD EXPIRE 选项 请参见 第13.7.1.3节“创建用户语法” 第13.7.1.1节“更改用户语法” CREATE USER ALTER USER

特定于帐户的语句示例:

  • 要求密码每90天更改一次:

    创建用户'jeffrey'@'localhost'密码EXPIRE INTERVAL 90天;
    ALTER USER'jeffrey'@'localhost'PASSWORD EXPIRE INTERVAL 90天;
    

    此到期选项会覆盖该语句指定的所有帐户的全局策略。

  • 禁用密码到期:

    创建用户'jeffrey'@'localhost'密码永远不会出现;
    ALTER USER'jeffrey'@'localhost'PASSWORD EXPIRE NEVER;
    

    此到期选项会覆盖该语句指定的所有帐户的全局策略。

  • 遵循该语句指定的所有帐户的全局过期策略:

    创建用户'jeffrey'@'localhost'PASSWORD EXPIRE DEFAULT;
    ALTER USER'jeffrey'@'localhost'PASSWORD EXPIRE DEFAULT;
    

当客户端成功连接时,服务器会确定帐户密码是否已过期:

  • 服务器检查密码是否已手动过期。

  • 否则,服务器根据自动密码过期策略检查密码年龄是否大于其允许的生存期。 如果是,则服务器认为密码已过期。

如果密码已过期(无论是手动还是自动),服务器将断开客户端连接或限制允许的操作(请参见 第6.2.16节“过期密码的服务器处理” )。 受限客户端执行的操作会导致错误,直到用户建立新的帐户密码:

MySQL的> SELECT 1;
ERROR 1820(HY000):您必须使用ALTER USER重置密码
执行此语句之前的语句。

MySQL的> ALTER USER USER() IDENTIFIED BY 'password';
查询OK,0行受影响(0.01秒)

MySQL的> SELECT 1;
+ --- +
| 1 |
+ --- +
| 1 |
+ --- +
1排(0.00秒)

客户端重置密码后,服务器将恢复会话的正常访问,以及后续使用该帐户的连接。 管理用户也可以重置帐户密码,但该帐户的任何现有受限会话仍然受到限制。 使用该帐户的客户端必须断开连接并重新连接才能成功执行语句。

注意

可以 通过将密码设置为其当前值 重置 密码。 作为一个好的政策问题,最好选择不同的密码。 DBA可以通过建立适当的密码重用策略来强制执行非重用。 请参阅 密码重用策略

密码重用政策

MySQL允许对重用以前的密码进行限制。 可以根据密码更改次数,已用时间或两者来确定重用限制。 可以在全球范围内建立重用策略,并且可以将个人帐户设置为遵循全局策略或使用特定的每帐户行为覆盖全局策略。

帐户的密码历史记录包含过去分配的密码。 MySQL可以限制从此历史记录中选择新密码:

  • 如果根据密码更改次数限制帐户,则无法从指定数量的最新密码中选择新密码。 例如,如果密码更改的最小数量设置为3,则新密码不能与任何最近的3个密码相同。

  • 如果根据已用时间限制帐户,则无法从历史记录中比指定天数更新的密码中选择新密码。 例如,如果密码重用间隔设置为60,则新密码不得超过先前在过去60天内选择的密码。

注意

空密码不会计入密码历史记录中,并且可以随时重复使用。

要全局建立密码重用策略,请使用 password_history password_reuse_interval 系统变量。

例子:

  • 要禁止重复使用365天以外的最后6个密码或密码,请将这些行放在服务器 my.cnf 文件中:

    的[mysqld]
    PASSWORD_HISTORY = 6
    password_reuse_interval = 365
    
  • 要在运行时设置和持久化变量,请使用如下语句:

    SET PERSIST password_history = 6;
    SET PERSIST password_reuse_interval = 365;
    

    SET PERSIST 设置正在运行的MySQL实例的值。 它还保存了用于后续服务器重启的值; 请参见 第13.7.5.1节“变量赋值的SET语法” 要更改正在运行的MySQL实例的值而不保存它以便后续重新启动,请使用 GLOBAL 关键字而不是 PERSIST

全局密码重用策略适用于尚未设置为覆盖它的所有帐户。 要为个人帐户建立策略,请使用 语句 PASSWORD HISTORY PASSWORD REUSE INTERVAL 选项 请参见 第13.7.1.3节“创建用户语法” 第13.7.1.1节“更改用户语法” CREATE USER ALTER USER

特定于帐户的语句示例:

  • 在允许重用之前,至少需要更改5个密码:

    创建用户'jeffrey'@'localhost'密码历史5;
    ALTER USER'jeffrey'@'localhost'PASSWORD HISTORY 5;
    

    此历史记录长度选项会覆盖该语句指定的所有帐户的全局策略。

  • 在允许重用之前至少需要365天:

    创建用户'jeffrey'@'localhost'密码重新使用INTERVAL 365天;
    ALTER USER'jeffrey'@'localhost'PASSWORD REUSE INTERVAL 365天;
    

    此time-elapsed选项会覆盖该语句指定的所有帐户的全局策略。

  • 要结合这两种类型的重用限制,使用 PASSWORD HISTORY PASSWORD REUSE INTERVAL 在一起:

    创建用户'jeffrey'@'localhost'
      密码历史5
      密码重复间隔365天;
    更改用户'jeffrey'@'localhost'
      密码历史5
      密码重复间隔365天;
    

    这些选项会覆盖语句指定的所有帐户的全局策略重用限制。

  • 遵循两种类型的重用限制的全局策略:

    创建用户'jeffrey'@'localhost'
      密码历史默认
      密码重复使用间隔默认值;
    更改用户'jeffrey'@'localhost'
      密码历史默认
      密码重复使用间隔默认值;
    

密码验证 - 必需的策略

从MySQL 8.0.13开始,可以要求通过指定要替换的当前密码来验证更改帐户密码的尝试。 这使DBA能够阻止用户更改密码,而无需证明他们知道当前密码。 否则可能发生这样的改变,例如,如果一个用户暂时离开终端会话而没有退出,并且恶意用户使用该会话来改变原始用户的MySQL密码。 这可能会产生不幸的后果:

  • 在管理员重置帐户密码之前,原始用户无法访问MySQL。

  • 在密码重置发生之前,恶意用户可以使用良性用户更改的凭据访问MySQL。

可以在全球范围内建立密码验证策略,并且可以将个人帐户设置为遵循全局策略或使用特定的每帐户行为覆盖全局策略。

对于每个帐户,其 mysql.user 行指示是否存在特定于帐户的设置,需要验证密码更改尝试的当前密码。 该设置由 语句 PASSWORD REQUIRE 选项 建立 CREATE USER ALTER USER

  • 如果帐户设置是 PASSWORD REQUIRE CURRENT ,密码更改必须指定当前密码。

  • 如果帐户设置是 PASSWORD REQUIRE CURRENT OPTIONAL ,密码更改可能但不需要指定当前密码。

  • 如果帐户设置为 PASSWORD REQUIRE CURRENT DEFAULT ,则 password_require_current 系统变量确定帐户所需的验证策略:

换句话说,如果帐户设置不是 PASSWORD REQUIRE CURRENT DEFAULT ,则帐户设置优先于 password_require_current 系统变量 建立的全局策略 否则,帐户将按照 password_require_current 设置进行操作。

默认情况下,密码验证是可选的: password_require_current 已禁用,并且创建的帐户没有 PASSWORD REQUIRE 默认选项 PASSWORD REQUIRE CURRENT DEFAULT

下表显示了每个帐户设置如何与 password_require_current 系统变量值 交互 以确定帐户密码验证所需的策略。

表6.10密码验证策略

每帐户设置 password_require_current系统变量 密码更改需要当前密码?
PASSWORD REQUIRE CURRENT OFF
PASSWORD REQUIRE CURRENT ON
PASSWORD REQUIRE CURRENT OPTIONAL OFF 没有
PASSWORD REQUIRE CURRENT OPTIONAL ON 没有
PASSWORD REQUIRE CURRENT DEFAULT OFF 没有
PASSWORD REQUIRE CURRENT DEFAULT ON

注意

无论是否需要验证策略,特权用户都可以更改任何帐户密码而无需指定当前密码。 特权用户是一个谁拥有全球的 CREATE USER 特权或 UPDATE 为特权 mysql 系统数据库。

要全局建立密码验证策略,请使用 password_require_current 系统变量。 其默认值为 OFF ,因此不需要帐户密码更改指定当前密码。

例子:

  • 要建立密码更改必须指定当前密码的全局策略,请在服务器 my.cnf 文件中 使用以下行启动服务器

    的[mysqld]
    password_require_current = ON
    
  • password_require_current 在运行时 设置和持久化 ,请使用以下语句之一:

    SET PERSIST password_require_current = ON;
    SET PERSIST password_require_current = OFF;
    

    SET PERSIST 设置正在运行的MySQL实例的值。 它还保存了用于后续服务器重启的值; 请参见 第13.7.5.1节“变量赋值的SET语法” 要更改正在运行的MySQL实例的值而不保存它以便后续重新启动,请使用 GLOBAL 关键字而不是 PERSIST

全局密码验证所需策略适用于尚未设置为覆盖它的所有帐户。 要为个人帐户建立策略,请使用 语句 PASSWORD REQUIRE 选项 请参见 第13.7.1.3节“创建用户语法” 第13.7.1.1节“更改用户语法” CREATE USER ALTER USER

特定于帐户的语句示例:

  • 要求密码更改指定当前密码:

    创建用户'jeffrey'@'localhost'密码请求当前;
    更改用户'jeffrey'@'localhost'密码请求当前;
    

    此验证选项会覆盖该语句指定的所有帐户的全局策略。

  • 不要求密码更改指定当前密码(可以但不需要给出当前密码):

    创建用户'jeffrey'@'localhost'密码请求当前可选;
    更改用户'jeffrey'@'localhost'密码要求当前可选;
    

    此验证选项会覆盖该语句指定的所有帐户的全局策略。

  • 遵循该语句指定的所有帐户的全局密码验证所需策略:

    创建用户'jeffrey'@'localhost'密码请求当前默认值;
    更改用户'jeffrey'@'localhost'密码请求当前默认值;
    

当用户使用 ALTER USER or SET PASSWORD 语句 更改密码时,验证当前密码 使用的示例 ALTER USER 优先 SET PASSWORD 于此,但此处描述的原则对于两个语句都是相同的。

在password-change语句中, REPLACE 子句指定要替换的当前密码。 例子:

  • 更改当前用户的密码:

    ALTER USER USER()通过' auth_string'REPLACE' current_auth_string' 识别;
    
  • 更改指定用户的密码:

    更改用户'jeffrey'@'localhost'
      由' auth_string' 识别
      替换' current_auth_string';
    
  • 更改命名用户的身份验证插件和密码:

    更改用户'jeffrey'@'localhost'
      使用caching_sha2_password BY' auth_string' 识别
      替换' current_auth_string';
    

REPLACE 条款的作用如下:

  • REPLACE 如果需要对帐户进行密码更改以指定当前密码,则必须给出,因为验证尝试进行更改的用户实际上知道当前密码。

  • REPLACE 如果帐户的密码更改可能但不需要指定当前密码,则是可选的。

  • 如果 REPLACE 指定,则必须指定正确的当前密码,否则会发生错误。 即使 REPLACE 是可选的 也是如此

  • REPLACE 只有在更改当前用户的帐户密码时才能指定。 (这意味着在刚刚显示的示例中, jeffrey 除非当前用户是,否则 明确命名帐户的语句将 失败 jeffrey 。)即使特权用户尝试对其他用户进行更改,也是如此。 但是,这样的用户可以更改任何密码而无需指定 REPLACE

  • REPLACE 从二进制日志中省略,以避免向其写入明文密码。

双密码支持

从MySQL 8.0.14开始,允许用户帐户拥有双密码,指定为主密码和辅助密码。 双密码功能可以在以下场景中无缝地执行凭证更改:

  • 系统有大量MySQL服务器,可能涉及复制。

  • 多个应用程序连接到不同的MySQL服务器

  • 必须对应用程序用于连接服务器的帐户进行定期凭据更改。

考虑如果仅允许一个帐户使用一个帐户,必须如何在前一种类型的方案中执行凭据更改。 在这种情况下,必须密切合作,在所有服务器上进行帐户密码更改并传播时,以及更新使用该帐户的所有应用程序以使用新密码。 此过程可能涉及服务器或应用程序不可用的停机时间。

使用双密码,可以分阶段更轻松地更改凭证,无需紧密合作,无需停机:

  1. 对于每个受影响的帐户,请在服务器上建立新的主密码,并将当前密码保留为辅助密码。 这使服务器能够识别每个帐户的主密码或辅助密码,而应用程序可以使用与以前相同的密码(现在是辅助密码)继续连接到服务器。

  2. 密码更改传播到所有服务器后,使用帐户主密码修改使用任何受影响帐户进行连接的应用程序。

  3. 将所有应用程序从辅助密码迁移到主密码后,不再需要辅助密码,可以将其丢弃。 此更改传播到所有服务器后,只能使用每个帐户的主密码进行连接。 凭证更改现已完成。

MySQL实现了双密码功能,其语法可以保存和丢弃辅助密码:

  • 在分配新的主密码时 RETAIN CURRENT PASSWORD ALTER USER SET PASSWORD 语句 子句 将帐户当前密码保存为其辅助密码。

  • DISCARD OLD PASSWORD 条款用于 ALTER USER 丢弃帐户二级密码,仅保留主密码。

假设对于先前描述的凭证更改方案, 'appuser1'@'host1.example.com' 应用程序使用 名为的帐户 连接到服务器,并且帐户密码将从更改 'password_a' 'password_b'

要执行此凭据更改,请使用 ALTER USER 以下内容:

  1. 在不是复制从属服务器的每台服务器上,建立 新的 主密码,将当前密码保留为辅助密码: 'password_b' appuser1

    ALTER USER'appuser1'@'host1.example.com'
      由' password_b' 识别
      保留当前密码;
    
  2. 等待密码更改以在整个系统中复制到所有从属服务器。

  3. 修改使用该 appuser1 帐户的 每个应用程序, 以便使用密码 而不是 密码连接到服务器 'password_b' 'password_a'

  4. 此时,不再需要二级密码。 在不是复制从属服务器的每台服务器上,丢弃辅助密码:

    ALTER USER'appuser1'@'host1.example.com'
      丢弃旧密码;
    
  5. 丢弃密码更改已复制到所有从属服务器后,凭据更改完成。

RETAIN CURRENT PASSWORD DISCARD OLD PASSWORD 条款具有以下效果:

  • RETAIN CURRENT PASSWORD 保留帐户当前密码作为其辅助密码,替换任何现有的二级密码。 新密码将成为主密码,但客户端可以使用该帐户使用主密码或辅助密码连接到服务器。 (例外:如果 ALTER USER or SET PASSWORD 语句 指定的新密码 为空,则辅助密码也会变为空,即使 RETAIN CURRENT PASSWORD 已给出。)

  • 如果 RETAIN CURRENT PASSWORD 为具有空主密码的帐户 指定 ,则该语句将失败。

  • 如果帐户具有辅助密码并且您在未指定 RETAIN CURRENT PASSWORD 情况下更改其主密码 ,则辅助密码将保持不变。

  • 对于 ALTER USER ,如果更改分配给该帐户的身份验证插件,则会丢弃该二级密码。 如果更改身份验证插件并指定 RETAIN CURRENT PASSWORD ,则语句将失败。

  • 对于 ALTER USER DISCARD OLD PASSWORD 丢弃二级密码(如果存在)。 该帐户仅保留其主密码,客户端可以使用该帐户仅使用主密码连接到服务器。

修改辅助密码的语句需要以下权限:

  • APPLICATION_PASSWORD_ADMIN 要使用 适用于您自己帐户 RETAIN CURRENT PASSWORD or DISCARD OLD PASSWORD 子句 ALTER USER SET PASSWORD 语句, 特权是必需的 由于大多数用户只需要一个密码,因此需要使用该权限来操作您自己的二级密码。

  • 如果允许某个帐户操作所有帐户的辅助密码,则应授予其 CREATE USER 权限,而不是 APPLICATION_PASSWORD_ADMIN

6.2.16过期密码的服务器处理

MySQL提供密码过期功能,使数据库管理员能够要求用户重置密码。 密码可以手动过期,并根据自动过期的策略(参见 第6.2.15节“密码管理” )。

对于使用具有过期密码的帐户的每个连接,服务器要么断开客户端连接,要么将客户端限制为 沙箱模式 ,其中服务器仅允许客户端重置过期密码所需的那些操作。 服务器采取的操作取决于客户端和服务器设置,如稍后所述。

如果服务器断开客户端连接,则会返回 ER_MUST_CHANGE_PASSWORD_LOGIN 错误:

shell> mysql -u myuser -p
密码:******
ERROR 1862(HY000):您的密码已过期。要登录你必须
使用支持过期密码的客户端更改它。

如果服务器将客户端限制为沙盒模式,则在客户端会话中允许这些操作:

  • 客户端可以使用 ALTER USER 重置帐户密码 SET PASSWORD 重置密码后,服务器将恢复会话的正常访问以及使用该帐户的后续连接。

    可以 通过将密码设置为其当前值 重置 密码。 作为一个好的政策问题,最好选择不同的密码。 DBA可以通过建立适当的密码重用策略来强制执行非重用。 请参阅 密码重用策略

  • 客户端可以使用 SET 语句。

对于会话中不允许的任何操作,服务器返回 ER_MUST_CHANGE_PASSWORD 错误:

MySQL的> USE performance_schema;
ERROR 1820(HY000):您必须使用ALTER USER重置密码
执行此语句之前的语句。

MySQL的> SELECT 1;
ERROR 1820(HY000):您必须使用ALTER USER重置密码
执行此语句之前的语句。

这是 mysql 客户端的 交互式调用通常会发生的情况, 因为默认情况下这样的调用是以沙盒模式进行的。 要清除错误并恢复正常运行,请选择新密码。

对于 mysql 客户端的 非交互式调用 (例如,在批处理模式下),如果密码过期,服务器通常会断开客户端的连接。 要允许非交互式 mysql 调用保持连接以便可以更改密码(使用刚才描述的语句),请将该 --connect-expired-password 选项 添加 mysql 命令。

如前所述,服务器是否断开过期密码客户端或将其限制为沙箱模式取决于客户端和服务器设置的组合。 以下讨论描述了相关设置及其交互方式。 该讨论仅适用于密码过期的帐户。 如果客户端使用非激活密码进行连接,则服务器会正​​常处理客户端。

在客户端,给定客户端指示它是否可以处理过期密码的沙箱模式。 对于使用C客户端库的客户端,有两种方法可以执行此操作:

  • 在连接之前 MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS 标志 传递 mysql_options() 给:

    arg = 1;
    result = mysql_options(mysql,
                           MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS,
                           &ARG);
    

    MySQL的 客户端允许 MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS ,如果调用交互或 --connect-expired-password 选项中给出。

  • 在连接时 CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS 标志 传递 mysql_real_connect()

    mysql = mysql_real_connect(mysql,
                               主机,用户,密码,db,
                               port,unix_socket,
                               CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS);
    

其他MySQL连接器有自己的约定,用于指示处理沙箱模式的准备情况。 请参阅您感兴趣的连接器的文档。

在服务器端,如果客户端指示它可以处理过期的密码,则服务器将其置于沙箱模式。

如果客户端未指示它可以处理过期的密码(或使用不能如此指示的旧版客户端库),则服务器操作取决于 disconnect_on_expired_password 系统变量 的值

6.2.17可插拔认证

当客户端连接到MySQL服务器时,服务器使用客户端和客户端主机提供的用户名从 mysql.user 系统表中 选择适当的帐户行 然后,服务器对客户端进行身份验证,从帐户行确定哪个身份验证插件适用于客户端:

  • 如果服务器找不到插件,则会发生错误并拒绝连接尝试。

  • 否则,服务器调用该插件来验证用户,并且插件向服务器返回状态,指示用户是否提供了正确的密码并且是否允许连接。

可插入身份验证可实现以下重要功能:

  • 选择身份验证方法。  可插入身份验证使DBA可以轻松选择和更改用于单个MySQL帐户的身份验证方法。

  • 外部认证。  可插入身份验证使客户端可以使用适用于存储除 mysql.user 系统表 之外的凭据的身份验证方法的凭据连接到MySQL服务器 例如,可以创建插件以使用外部身份验证方法,如PAM,Windows登录ID,LDAP或Kerberos。

  • 代理用户:  如果允许用户连接,则认证插件可以向服务器返回与连接用户名不同的用户名,以指示连接用户是另一个用户(代理用户)的代理。 当连接持续时,出于访问控制的目的,代理用户被视为具有代理用户的特权。 实际上,一个用户冒充另一个用户。 有关更多信息,请参见 第6.2.18节“代理用户”

注意

如果使用该 --skip-grant-tables 选项 启动服务器, 即使已加载,也不会使用身份验证插件,因为服务器不执行客户端身份验证并允许任何客户端连接。 因为这是不安全的,如果使用该 --skip-grant-tables 选项 启动服务器 ,它会 --skip-networking 自动 启用 以防止远程连接。

可用的身份验证插件

MySQL 8.0提供了这些身份验证插件:

  • 一个执行本机身份验证的插件; 也就是说,基于在MySQL中引入可插入身份验证之前使用的密码哈希方法的身份验证。 mysql_native_password 插件基于此本机密码哈希方法实现身份验证。 请参见 第6.4.1.1节“本机可插入认证”

  • 使用SHA-256密码散列执行身份验证的插件。 这比本机身份验证提供的加密更强。 请参见 第6.4.1.2节“SHA-256可插拔认证” 第6.4.1.3节“高速缓存SHA-2可插入认证”

  • 客户端插件,无需散列或加密即可将密码发送到服务器。 此插件与服务器端插件结合使用,这些插件需要完全按照客户端用户提供的密码访问。 请参见 第6.4.1.4节“客户端明文可插拔认证”

  • 一个使用PAM(可插入身份验证模块)执行外部身份验证的插件,使MySQL Server能够使用PAM对MySQL用户进行身份验证。 此插件也支持代理用户。 请参见 第6.4.1.5节“PAM可插拔认证”

  • 一个在Windows上执行外部身份验证的插件,使MySQL Server能够使用本机Windows服务来验证客户端连接。 已登录Windows的用户可以根据其环境中的信息从MySQL客户端程序连接到服务器,而无需指定其他密码。 此插件也支持代理用户。 请参见 第6.4.1.6节“Windows可插入验证”

  • 使用LDAP(轻量级目录访问协议)执行身份验证的插件,通过访问X.500等目录服务来验证MySQL用户。 这些插件也支持代理用户。 请参见 第6.4.1.7节“LDAP可插入认证”

  • 一个插件,阻止所有客户端连接到任何使用它的帐户。 此插件的用例包括永远不允许直接登录的代理帐户,但只能通过代理帐户和帐户访问,这些帐户和帐户必须能够以提升的权限执行存储的程序和视图,而不会将这些权限暴露给普通用户。 请参见 第6.4.1.8节“无登录可插入认证”

  • 一个插件,用于验证从本地主机通过Unix套接字文件连接的客户端。 请参见 第6.4.1.9节“Socket Peer-Credential Pluggable Authentication”

  • 一个测试插件,用于检查帐户凭据并将成功或失败记录到服务器错误日志中。 此插件旨在用于测试和开发目的,并作为如何编写身份验证插件的示例。 请参见 第6.4.1.10节“测试可插拔认证”

注意

有关使用可插入身份验证的当前限制的信息,包括哪些连接器支持哪些插件,请参见 第C.9节“可插入身份验证的限制”

第三方连接器开发人员应阅读该部分,以确定连接器可以利用可插入身份验证功能的程度以及采取哪些步骤以使其更加合规。

如果您有兴趣编写自己的身份验证插件,请参见 第29.2.4.9节“编写身份验证插件”

身份验证插件使用

本节提供有关安装和使用身份验证插件的一般说明。 有关给定插件的特定说明,请参见 第6.4.1节“身份验证插件” 中描述该插件的 部分

通常,可插入身份验证在服务器端和客户端使用一对相应的插件,因此您使用给定的身份验证方法,如下所示:

  • 如有必要,请安装包含相应插件的插件库或库。 在服务器主机上,安装包含服务器端插件的库,以便服务器可以使用它来验证客户端连接。 同样,在每个客户端主机上,安装包含客户端插件的库以供客户端程序使用。 无需安装内置的身份验证插件。

  • 对于您创建的每个MySQL帐户,请指定用于身份验证的相应服务器端插件。 如果帐户要使用默认身份验证插件,则帐户创建语句无需明确指定插件。 default_authentication_plugin 系统变量配置默认的身份验证插件。

  • 当客户端连接时,服务器端插件告诉客户端程序使用哪个客户端插件进行身份验证。

如果帐户使用的身份验证方法是服务器和客户端程序的默认方法,则服务器无需与客户端通信使用哪个客户端插件,并且客户端/服务器协商中的往返可以是避免。

对于标准MySQL客户端,例如 mysql mysqladmin 可以在命令行上指定 选项,作为程序可以使用哪个客户端插件的提示,尽管如果服务器端插件与服务器端插件相关联,服务器将覆盖此选项。用户帐户需要不同的客户端插件。 --default-auth=plugin_name

如果客户端程序找不到客户端插件库文件,请指定一个 选项以指示插件库目录位置。 --plugin-dir=dir_name

Authentication Plugin客户端/服务器兼容性

可插入身份验证可以灵活地选择MySQL帐户的身份验证方法,但在某些情况下,由于客户端和服务器之间的身份验证插件不兼容,无法建立客户端连接。

成功的客户端连接到给定服务器上给定帐户的一般兼容性原则是客户端和服务器都必须支持 帐户所需 的身份验证 方法 由于身份验证方法是由身份验证插件实现的,因此客户端和服务器都必须支持 帐户所需 的身份验证 插件

身份验证插件不兼容性可能以各种方式出现。 例子:

  • 使用5.7.22或更低版本的MySQL 5.7客户端连接到使用身份验证的MySQL 8.0服务器帐户 caching_sha2_password 这失败是因为5.7客户端无法识别MySQL 8.0中引入的插件。 (当 caching_sha2_password MySQL客户端库和客户端程序中添加了客户端支持 时,此问题在MySQL 5.7及5.7.23中得到解决 。)

  • 使用MySQL 5.5客户端连接到使用身份验证的MySQL 5.6服务器帐户 sha256_password 这失败是因为5.5客户端无法识别MySQL 5.6中引入的插件。

  • 使用MySQL 5.7客户端连接到使用身份验证的5.7之前的服务器帐户 mysql_old_password 由于多种原因,这会失败。 首先,这种连接需要 --secure-auth=0 ,这不再是受支持的选项。 即使它受支持,5.7客户端也无法识别该插件,因为它已在MySQL 5.7中删除。

  • 使用MySQL 5.7客户端从社区分发连接到MySQL 5.7企业服务器帐户,该帐户使用一个仅限企业版的LDAP身份验证插件进行身份验证。 此操作失败,因为社区客户端无权访问Enterprise插件。

通常,当从同一MySQL发行版在客户端和服务器之间建立连接时,不会出现这些兼容性问题。 当来自不同MySQL系列的客户端和服务器之间建立连接时,可能会出现问题。 当MySQL引入新的身份验证插件或删除旧的身份验证插件时,这些问题是开发过程中固有的。 为尽量减少不兼容的可能性,请定期定期升级服务器,客户端和连接器。

身份验证插件连接器 - 编写注意事项

存在MySQL客户端/服务器协议的各种实现。 libmysqlclient C API客户端库是一个实现。 一些MySQL连接器(通常不是用C编写的连接器)提供自己的实现。 但是,并非所有协议实现都以相同的方式处理插件身份验证。 本节介绍协议实现者应考虑的身份验证问题。

在客户端/服务器协议中,服务器告诉连接客户端它认为哪个认证插件是默认的。 如果客户端使用的协议实现尝试加载默认插件并且客户端上不存在该插件,则加载操作将失败。 如果默认插件不是客户端尝试连接的帐户实际需要的插件,则这是不必要的失败。

如果客户端/服务器协议实现没有自己的默认身份验证插件的概念,并且总是尝试加载服务器指定的默认插件,那么如果该插件不可用,它将失败并显示错误。

为了避免这个问题,客户端使用的协议实现应该有自己的默认插件,并且应该将它作为它的第一选择(或者,如果无法加载服务器指定的默认插件,则可以使用它作为默认值) 。 例:

  • 在MySQL 5.7中, libmysqlclient 使用默认选项 mysql_native_password 或通过 MYSQL_DEFAULT_AUTH 选项 指定的插件 mysql_options()

  • 当5.7客户端尝试连接到8.0服务器时,服务器 caching_sha2_password 将其 指定 为其默认的身份验证插件,但客户端仍然会发送凭据详细信息 mysql_native_password 或通过其指定的任何内容 MYSQL_DEFAULT_AUTH

  • 客户端加载服务器指定的插件的唯一时间是更改插件请求,但在这种情况下,它可以是任何插件,具体取决于用户帐户。 在这种情况下,客户端必须尝试加载插件,如果该插件不可用,则错误不是可选的。

6.2.18代理用户

MySQL服务器使用身份验证插件验证客户端连接。 验证给定连接的插件可以请求将连接(外部)用户视为不同的用户以进行特权检查。 这使外部用户成为第二个用户的代理; 也就是说,假设第二个用户的权限:

  • 外部用户是 代理用户 (可以冒充或被称为另一个用户的用户)。

  • 第二个用户是 代理用户 代理用户 可以承担其身份和特权的用户)。

本节介绍代理用户功能的工作原理。 有关身份验证插件的一般信息,请参见 第6.2.17节“可插入身份验证” 有关特定插件的信息,请参见 第6.4.1节“身份验证插件” 有关编写支持代理用户的身份验证插件的信息,请参见 第29.2.4.9.4节“在身份验证插件中实现代理用户支持”

注意

作为代理用户的替代方案,您可能会发现角色提供了一种将用户映射到特定命名权限集的合适方法。 请参见 第6.2.10节“使用角色”

代理用户支持的要求

对于给定身份验证插件的代理,必须满足以下条件:

  • 必须通过插件本身或代表插件的MySQL服务器来支持代理。 在后一种情况下,可能需要明确启用服务器支持; 请参阅 代理用户映射的服务器支持

  • 必须将外部代理用户的帐户设置为由插件进行身份验证。 使用该 CREATE USER 语句将帐户与身份验证插件相关联,或 ALTER USER 更改其插件。

  • 代理用户的帐户必须存在并被授予代理用户承担的权限。 使用 CREATE USER GRANT 语句。

  • 代理用户帐户必须具有 PROXY 代理帐户 权限。 请使用此 GRANT 语句。

  • 对于连接到代理帐户的客户端将被视为代理用户,身份验证插件必须返回与客户端用户名不同的用户名,以指示代理帐户的用户名,该用户名定义代理所承担的权限用户。

    或者,对于由服务器提供代理映射的插件,代理用户是 PROXY 由代理用户持有 特权 确定的

代理机制允许仅将外部客户端用户名映射到代理用户名。 没有规定映射主机名:

  • 当客户端连接到服务器时,服务器根据客户端程序传递的用户名和客户端连接的主机确定正确的帐户。

  • 如果该帐户是代理帐户,则服务器会尝试使用身份验证插件返回的用户名和代理帐户的主机名来查找代理帐户的匹配项。 代理帐户中的主机名将被忽略。

请考虑以下帐户定义:

- 创建代理帐户
创建用户'employee_ext'@'localhost'
  使用my_auth_plugin识别
  AS'my_auth_string';

- 创建代理帐户并授予其权限
创建用户'员工'@'localhost'
  识别' employee_password';
全部授予
  员工。*
  ''employee'@'localhost';

- 授予代理帐户代理帐户的PROXY权限
授予代理权
  在'员工'@'localhost'
  到'employee_ext'@'localhost';

当客户端 employee_ext 从本地主机 连接时 ,MySQL使用名为的插件 my_auth_plugin 执行身份验证。 假设 根据内容 和可能通过咨询某些外部认证系统 my_auth_plugin 返回 employee 服务器 的用户名 'my_auth_string' 名称 employee 不同 employee_ext ,因此返回 employee 用作服务器的请求 ,以便将 employee_ext 权限检查作为 employee 本地用户 处理 外部 用户。

在这种情况下, employee_ext 是代理用户并且 employee 是代理用户。

服务器 通过检查 (代理用户) 是否具有 (代理用户)的 特权来 验证 用户是否 employee 可以进行 代理身份验证 如果未授予此权限,则会发生错误。 否则, 假定的权限 服务器 根据授予的权限 检查客户端会话期间执行的语句 在这种情况下, 可以访问 数据库中的 employee_ext employee_ext PROXY employee employee_ext employee employee_ext employee employee_ext employees

发生代理时, 可以使用 USER() CURRENT_USER() 函数来查看连接用户(代理用户)与其权限在当前会话(代理用户)期间应用的帐户之间的区别。 对于刚刚描述的示例,这些函数返回以下值:

MySQL的> SELECT USER(), CURRENT_USER();
+ ------------------------ + -------------------- +
| USER()| CURRENT_USER()|
+ ------------------------ + -------------------- +
| employee_ext @ localhost | employee @ localhost |
+ ------------------------ + -------------------- +

CREATE USER 创建代理用户帐户的 IDENTIFIED WITH 语句中,为支持代理的身份验证插件命名 子句可选地后跟一个 子句 ,该 子句指定服务器在用户连接时传递给插件的字符串。 如果存在,该字符串提供的信息有助于插件确定如何将代理(外部)客户端用户名映射到代理用户名。 每个插件都取决于是否需要该 子句。 如果是这样,身份验证字符串的格式取决于插件打算如何使用它。 有关其接受的身份验证字符串值的信息,请参阅给定插件的文档。 AS 'auth_string' AS

授予和撤销PROXY权限

PROXY 需要 特权才能使外部用户能够以另一个用户的身份进行连接。 要授予此权限,请使用该 GRANT 语句。 例如:

授权' proxied_user'去' proxy_user';

该语句在 mysql.proxies_priv 授权表中 创建一行

在连接时, proxy_user 必须表示有效的外部认证的MySQL用户,并且 proxied_user 必须代表有效的本地认证用户。 否则,连接尝试失败。

相应的 REVOKE 语法是:

REVOKE PROXY ON''FROM proxied_user' proxy_user';

MySQL GRANT REVOKE 语法扩展照常工作。 例子:

- 向多个帐户授予PROXY
授权'a'到'b','c','d';

- 撤销多个帐户的PROXY
REVOKE PROXY'''从'b','c','d';

- 授予PROXY账户并启用账户授予
- 代理帐户代理
通过授予选项授予'a'到'd'的授权;

- 将PROXY授予匿名帐户
授权''''''''';

PROXY 特权可以在这些情况下被授予:

  • 通过具有用户 GRANT PROXY ... WITH GRANT OPTION proxied_user

  • 通过 proxied_user 对自身:值 USER() 必须完全匹配 CURRENT_USER() proxied_user ,同时为用户名和账户名的主机名部分。

root 在MySQL安装期间创建 的初始 帐户具有 对所有用户和所有主机 PROXY ... WITH GRANT OPTION 特权 ''@'' 这样可以 root 设置代理用户,以及委托其他帐户设置代理用户的权限。 例如, root 可以这样做:

创建用户'admin'@'localhost'
  通过'测试'识别;
授予代理权
  上 ''@''
  TO'admin'@'localhost'
  WITH GRANT OPTION;

这些语句创建了一个 admin 可以管理所有 GRANT PROXY 映射 用户 例如, admin 可以这样做:

授予莎莉的权利;

默认代理用户

要指定某些或所有用户应使用给定的身份验证插件进行连接,请创建一个 空白 MySQL帐户( ''@'' ),将其与该插件关联,然后让插件返回真实身份验证的用户名(如果与空白用户不同)。 例如,假设存在一个名为 ldap_auth 实现LDAP身份验证 的插件 ,并将连接用户映射到开发人员或经理帐户。 要设置用户对这些帐户的代理,请使用以下语句:

- 创建默认代理帐户
用ldap_auth创建用户'''''
  AS'O = Oracle,OU = MySQL';

- 创建代理帐户
创建用户'开发者'@'localhost'
  识别' developer_password';
创建用户'经理'@'localhost'
  识别' manager_password';

- 为代理帐户的默认代理帐户授予PROXY权限
授予代理权
  在'经理'@'localhost'
  至 ''@'';
授予代理权
  ON'开发者'@'localhost'
  至 ''@'';

现在假设客户端连接如下:

shell> mysql --user=myuser --password ...
输入密码:myuser_password

服务器将找不到 myuser 定义为MySQL用户。 但是,因为有一个空白的用户帐户( ''@'' 相匹配的客户端用户名和主机名),该服务器验证针对该帐户的客户端:服务器调用 ldap_auth 身份验证插件和传球 myuser ,并 myuser_password 把它作为用户名和密码。

如果 ldap_auth 插件在LDAP目录中 myuser_password 找不到正确的密码 myuser ,则身份验证失败,服务器拒绝连接。

如果密码正确并且 ldap_auth 发现它 myuser 是开发人员,则会将用户名返回 developer 给MySQL服务器,而不是 myuser 将不同于 myuser 信号 的客户端用户名的用户名返回 到应将其 myuser 视为代理的服务器。 服务器验证 ''@'' 可以进行身份​​验证 developer (因为该帐户 PROXY 有权这样做)并接受连接。 会话继续 myuser 具有 developer 代理用户 的特权 (这些权限应由DBA使用 GRANT 语句设置,未显示。) USER() CURRENT_USER() 函数返回这些值:

MySQL的> SELECT USER(), CURRENT_USER();
+ ------------------ + --------------------- +
| USER()| CURRENT_USER()|
+ ------------------ + --------------------- +
| myuser @ localhost | developer @ localhost |
+ ------------------ + --------------------- +

如果插件改为在 myuser 作为管理器 的LDAP目录中找到 ,则它将 manager 作为用户名 返回 ,并且会话继续 myuser 具有特权 manager

MySQL的> SELECT USER(), CURRENT_USER();
+ ------------------ + ------------------- +
| USER()| CURRENT_USER()|
+ ------------------ + ------------------- +
| myuser @ localhost | 经理@ localhost |
+ ------------------ + ------------------- +

为简单起见,外部身份验证不能是多级的: 在前面的示例中 ,并未考虑凭证 developer 和那些 凭证 manager 但是,如果客户端尝试直接作为 developer manager 帐户 进行连接和身份验证,则仍会使用它们 ,这就是为这些代理帐户分配密码的原因。

确保代理帐户无法直接使用的其他方法:

默认代理用户和匿名用户冲突

如果您打算创建默认代理用户,请检查其他现有的 匹配任何用户 帐户,这些帐户优先于默认代理用户,因为它们可能会阻止该用户按预期工作。

在前面的讨论中,默认代理用户帐户 '' 在主机部分中具有匹配任何主机的部分。 如果您设置了默认代理用户,请注意检查非代理帐户是否存在同一用户部分和 '%' 主机部分,因为它 '%' 也匹配任何主机,但优先于 '' 服务器用于对帐户行进行排序的规则内部(参见 第6.2.6节“访问控制,第1阶段:连接验证” )。

假设MySQL安装包括以下两个帐户:

- 创建默认代理帐户
创建用户 ''@''
  通过some_plugin识别
  AS'seat_auth_string';
- 创建匿名帐户
创建用户 ''@'%'
  识别' some_password';

第一个帐户( ''@'' )用作默认代理用户,用于验证与其他帐户不匹配的用户的连接。 第二个帐户( ''@'%' )是一个匿名用户帐户,例如,可能已创建该帐户,以使没有自己帐户的用户能够匿名连接。

两个帐户都具有相同的用户part( '' ),匹配任何用户。 每个帐户都有一个与任何主机匹配的主机部分。 尽管如此,在帐户匹配优先级的连接尝试,因为匹配规则不大不小的主机 '%' 的前面 '' 对于与任何更具体的帐户不匹配的帐户,服务器会尝试针对 ''@'%' (匿名用户)而不是 ''@'' (默认代理用户) 对其进行身份验证 因此,永远不会使用默认代理帐户。

要避免此问题,请使用以下策略之一:

  • 删除匿名帐户,使其不与默认代理用户冲突。 如果您想将每个连接与指定用户相关联,这可能是个好主意。

  • 使用在匿名用户之前匹配的更具体的默认代理用户。 例如,要仅允许 localhost 代理连接,请使用 ''@'localhost'

    创建用户''@'localhost'
      通过some_plugin识别
      AS'seat_auth_string';
    

    此外,修改任何 GRANT PROXY 语句 ''@'localhost' 而不是 ''@'' 代理用户。

    请注意,此策略会阻止匿名用户连接 localhost

  • 使用指定的默认帐户而不是匿名默认帐户。 有关此技术的示例,请参阅使用该 authentication_windows 插件 的说明 请参见 第6.4.1.6节“Windows可插入身份验证”

  • 创建多个代理用户,一个用于本地连接,另一个用于 其他所有 (远程连​​接)。 当本地用户具有来自远程用户的不同权限时,这尤其有用。

    创建代理用户:

    - 为本地连接创建代理用户
    创建用户''@'localhost'
      通过some_plugin识别
      AS'seat_auth_string';
    - 为远程连接创建代理用户
    创建用户 ''@'%'
      通过some_plugin识别
      AS'seat_auth_string';
    

    创建代理用户:

    - 为本地连接创建代理用户
    创建用户'开发者'@'localhost'
      识别' some_password';
    - 为远程连接创建代理用户
    创建用户'开发者'@'%'
      识别' some_password';
    

    为相应的代理用户授予每个代理用户的代理权限:

    授予代理权
      ON'开发者'@'localhost'
      去'''localhost';
    授予代理权
      ON'开发者'@'%'
      至 ''@'%';
    

    最后,为本地和远程代理用户(未显示)授予适当的权限。

    假设 some_plugin / 'some_auth_string' 组合导致 some_plugin 将客户端用户名映射到 developer 本地连接与 ''@'localhost' 代理用户 匹配, 代理用户映射到 'developer'@'localhost' 代理用户。 远程连接与 ''@'%' 代理用户 匹配, 代理用户映射到 'developer'@'%' 代理用户。

服务器支持代理用户映射

一些身份验证插件为自己实现代理用户映射(例如,PAM和Windows身份验证插件)。 默认情况下,其他身份验证插件不支持代理用户。 其中,有些人可以要求MySQL服务器本身根据授予的代理权限映射代理用户: mysql_native_password sha256_password 如果 check_proxy_users 启用 系统变量,则服务器会对发出此类请求的任何身份验证插件执行代理用户映射:

服务器执行的代理用户映射受以下限制:

  • 即使 PROXY 授予 了关联的 权限 ,服务器也不会代理匿名用户或从匿名用户代理

  • 如果为单个帐户授予了多个代理帐户的代理权限,则服务器代理用户映射是不确定的。 因此,不鼓励为多个代理帐户授予单个帐户代理权限。

代理用户系统变量

两个系统变量有助于跟踪代理登录过程:

  • proxy_user :此值 NULL 是否未使用代理。 否则,它表示代理用户帐户。 例如,如果客户端通过 ''@'' 代理帐户进行 身份验证 ,则此变量设置如下:

    MySQL的> SELECT @@proxy_user;
    + -------------- +
    | @@ proxy_user |
    + -------------- +
    | ''@''|
    + -------------- +
    
  • external_user :有时,身份验证插件可能会使用外部用户对MySQL服务器进行身份验证。 例如,使用Windows本机身份验证时,使用Windows API进行身份验证的插件不需要传递给它的登录ID。 但是,它仍使用Windows用户标识进行身份验证。 插件可以使用 external_user 只读会话变量 将此外部用户ID(或其前512个UTF-8字节)返回给服务器 如果插件未设置此变量,则其值为 NULL

6.2.19账户锁定

MySQL支持使用 语句 ACCOUNT LOCK ACCOUNT UNLOCK 子句 锁定和解锁用户帐户 CREATE USER ALTER USER

  • 与之一起使用时 CREATE USER ,这些子句指定新帐户的初始锁定状态。 如果没有任何一个子句,则帐户将以解锁状态创建。

  • 与之一起使用时 ALTER USER ,这些子句指定现有帐户的新锁定状态。 如果没有任何一个子句,则帐户锁定状态保持不变。

帐户锁定状态记录在 系统表 account_locked 列中 mysql.user 输出来 SHOW CREATE USER 指示帐户是锁定还是解锁。

如果客户端尝试连接到锁定的帐户,则尝试失败。 服务器递增 Locked_connects 状态变量, 变量指示连接到锁定帐户的尝试次数,返回 ER_ACCOUNT_HAS_BEEN_LOCKED 错误,并将消息写入错误日志:

用户' user_name'@' 拒绝访问host_name
帐户被锁定。

锁定帐户不会影响使用假定锁定帐户身份的代理用户进行连接。 它也不会影响执行存储程序或视图的能力,这些程序或视图具有 DEFINER 命名锁定帐户 子句。 也就是说,锁定帐户不会影响使用代理帐户或存储的程序或视图的能力。

帐户锁定功能取决于 系统表中 是否存在 account_locked mysql.user 对于早于5.7.6的MySQL版本的升级,请执行MySQL升级过程以确保此列存在。 请参见 第2.11节“升级MySQL” 对于没有 account_locked 列的非 升级安装, 服务器会将所有帐户视为已解锁,并使用 ACCOUNT LOCK ACCOUNT UNLOCK 子句会产生错误。

6.2.20设置帐户资源限制

限制客户端使用MySQL服务器资源的一种方法是将全局 max_user_connections 系统变量设置为非零值。 这限制了任何给定帐户可以同时进行的连接数,但对连接后客户端可以执行的操作没有限制。 此外,设置 max_user_connections 无法管理个人帐户。 MySQL管理员都对这两种控件都很感兴趣。

为了解决这些问题,MySQL允许使用这些服务器资源限制个人帐户:

  • 帐户每小时可以发出的查询数

  • 帐户每小时可以发布的更新次数

  • 帐户每小时可以连接到服务器的次数

  • 帐户与服务器同时连接的数量

客户端可以发出的任何语句都会计入查询限制。 只有修改数据库或表的语句才会计入更新限制。

此上下文中 帐户 对应于 mysql.user 系统表中 的行 也就是说,根据 适用于连接 表行 中的 User Host 来评估 user 连接。 例如,帐户 'usera'@'%.example.com' 对应于 user 表中具有 User 和的 Host 值的行, usera 以及 %.example.com 允许 usera example.com 域中的 任何主机进行连接 在这种情况下,服务器将此行中的资源限制共同应用于 域中 usera 任何主机的 所有连接, example.com 因为所有此类连接都使用相同的帐户。

在MySQL 5.0之前 ,根据用户连接的实际主机评估 帐户 可以通过使用该 --old-style-user-limits 选项 启动服务器来选择这种较旧的记帐方法 在这种情况下,如果 usera 同时从 host1.example.com 连接 host2.example.com ,则服务器将帐户资源限制分别应用于每个连接。 如果 usera 再次连接 host1.example.com ,则服务器将该连接的限制与该主机的现有连接一起应用。

要在帐户创建时为帐户建立资源限制,请使用该 CREATE USER 语句。 要修改现有帐户的限制,请使用 ALTER USER 提供一个 WITH 子句,命名每个资源是有限的。 每个限制的默认值为零(无限制)。 例如,要创建可以访问 customer 数据库但只能以有限方式 访问 数据库 的新帐户 ,请发出以下语句:

mysql> CREATE USER 'francis'@'localhost' IDENTIFIED BY 'frank'
    - >     WITH MAX_QUERIES_PER_HOUR 20
    - >          MAX_UPDATES_PER_HOUR 10
    - >          MAX_CONNECTIONS_PER_HOUR 5
    - >         MAX_USER_CONNECTIONS 2;

限制类型不必全部在 WITH 子句中命名,但命名的那些可以按任何顺序存在。 每个每小时限制的值应该是一个表示每小时计数的整数。 对于 MAX_USER_CONNECTIONS ,限制是一个整数,表示帐户的最大同时连接数。 如果此限制设置为零,则全局 max_user_connections 系统变量值确定同时连接的数量。 如果 max_user_connections 也为零,则帐户没有限制。

要修改现有帐户的限制,请使用 ALTER USER 语句。 以下语句将查询限制更改为 francis 100:

MySQL的> ALTER USER 'francis'@'localhost' WITH MAX_QUERIES_PER_HOUR 100;

该语句仅修改指定的限制值,否则保留帐户不变。

要删除限制,请将其值设置为零。 例如,要删除每小时 francis 可以连接的 次数限制 ,请使用以下语句:

MySQL的> ALTER USER 'francis'@'localhost' WITH MAX_CONNECTIONS_PER_HOUR 0;

如前所述,帐户的同时连接限制由 MAX_USER_CONNECTIONS 限制和 max_user_connections 系统变量确定。 假设全局 max_user_connections 值为10,并且三个帐户具有指定的个别资源限制,如下所示:

ALTER USER'user1'@'localhost'WITH MAX_USER_CONNECTIONS 0;
ALTER USER'user2'@'localhost'WITH MAX_USER_CONNECTIONS 5;
ALTER USER'user3'@'localhost'WITH MAX_USER_CONNECTIONS 20;

user1 连接限制为10(全局 max_user_connections 值),因为它的 MAX_USER_CONNECTIONS 限制为零。 user2 并且分别 user3 具有5和20的连接限制,因为它们具有非零 MAX_USER_CONNECTIONS 限制。

服务器在 user 与该帐户对应 表行中 存储帐户的资源限制 max_questions max_updates max_connections 列存储每小时限制和 max_user_connections 列存储 MAX_USER_CONNECTIONS 限制。 (参见 第6.2.3节“授权表” 。)

当任何帐户对其使用任何资源具有非零限制时,将进行资源使用计数。

在服务器运行时,它会计算每个帐户使用资源的次数。 如果帐户在过去一小时内达到其连接数限制,则服务器将拒绝该帐户的其他连接,直到该小时为止。 同样,如果帐户达到其查询或更新数量的限制,服务器将拒绝进一步的查询或更新,直到小时结束。 在所有这些情况下,服务器都会发出相应的错误消息。

资源计数发生在每个帐户,而不是每个客户。 例如,如果您的帐户的查询限制为50,则无法通过与服务器建立两个同时的客户端连接来将限制增加到100。 在两个连接上发出的查询一起计算。

可以为所有帐户全局重置当前每小时资源使用计数,也可以针对给定帐户单独重置当前每小时资源使用计数:

  • 要将所有帐户的当前计数重置为零,请发出 FLUSH USER_RESOURCES 声明。 还可以通过重新加载授权表来重置计数(例如,使用 FLUSH PRIVILEGES 语句或 mysqladmin reload 命令)。

  • 通过再次设置其任何限制,可以将个人帐户的计数重置为零。 指定等于当前分配给帐户的值的限制值。

每小时计数器重置不会影响 MAX_USER_CONNECTIONS 限制。

服务器启动时,所有计数从零开始。 计数不会通过服务器重启而延续。

对于 MAX_USER_CONNECTIONS 限制,如果帐户当前已打开允许的最大连接数,则可能出现边缘情况: 如果服务器尚未完全处理断开连接,则 连接快速断开连接可能导致错误( ER_TOO_MANY_USER_CONNECTIONS ER_USER_LIMIT_REACHED )连接发生的时间。 当服务器完成断开连接处理时,将再次允许另一个连接。

6.2.21连接MySQL的问题疑难解答

如果在尝试连接到MySQL服务器时遇到问题,以下各项描述了可以采取的一些操作过程来解决问题。

  • 确保服务器正在运行。 如果不是,客户端无法连接到它。 例如,如果尝试连接到服务器失败并显示以下消息之一,则一个原因可能是服务器未运行:

    shell> mysql
    ERROR 2003:无法连接到MySQL服务器' host_name'(111)
    外壳> mysql
    ERROR 2002:无法通过套接字连接到本地MySQL服务器
    '/tmp/mysql.sock'(111)
    
  • 可能是服务器正在运行,但您尝试使用与服务器正在侦听的TCP / IP端口,命名管道或Unix套接字文件不同的TCP / IP端口进行连接。 要在调用客户端程序时更正此问题,请指定一个 --port 选项以指示正确的端口号,或 指定一个 选项以指示 --socket 正确的命名管道或Unix套接字文件。 要找出套接字文件的位置,可以使用以下命令:

    外壳> netstat -ln | grep mysql
    
  • 确保服务器尚未配置为忽略网络连接或(如果您尝试远程连接)尚未配置为仅在其网络接口上本地侦听。 如果服务器已启动 --skip-networking ,则根本不接受TCP / IP连接。 如果服务器是在 bind_address 系统变量设置为的情况 下启动的 127.0.0.1 ,则它将仅在环回接口上本地侦听TCP / IP连接,并且不接受远程连接。

  • 检查以确保没有防火墙阻止访问MySQL。 可以根据正在执行的应用程序或MySQL用于通信的端口号(默认为3306)来配置防火墙。 在Linux或Unix下,检查IP表(或类似)配置以确保端口未被阻止。 在Windows下,可能需要配置ZoneAlarm或Windows防火墙等应用程序,以阻止MySQL端口。

  • 必须正确设置授权表,以便服务器可以使用它们进行访问控制。 对于某些分发类型(例如Windows上的二进制分发版或Linux上的RPM分发版),安装过程会初始化MySQL数据目录,包括 mysql 包含授权表 系统数据库。 对于不执行此操作的分发,必须手动初始化数据目录。 有关详细信息,请参见 第2.10节“安装后设置和测试”

    要确定是否需要初始化授权表,请 mysql 在数据目录下 查找 目录。 (数据目录通常名为 data var 位于MySQL安装目录下。)确保 user.MYD mysql 数据库目录中 有一个文件 如果没有,请初始化数据目录。 执行此操作并启动服务器后,您应该能够连接到服务器。

  • 全新安装后,如果您尝试以 root 不使用密码的 身份登录服务器 ,则可能会收到以下错误消息。

    外壳> mysql -u root 
    ERROR 1045(28000):用户'root'@'localhost'拒绝访问(使用密码:NO)
    

    这意味着在安装期间已经分配了root密码,并且必须提供该密码。 有关 可以分配密码的不同方法 请参见 第2.10.4节“保护初始MySQL帐户” ,在某些情况下, 请参阅 如何查找密码。 如果需要重置root密码,请参见 第B.4.3.2节“如何重置root密码”中的说明 找到或重置密码后,请 root 使用 --password (或 -p )选项 再次登录

    外壳> mysql -u root -p 
    输入密码: 
    

    但是, root 如果您使用 mysqld 初始化MySQL ,则服务器将允许您连接 而不使用密码 --initialize-insecure 有关详细信息 请参见 第2.10.1节“初始化数据目录” )。 这是一个安全风险,因此您应该为该 root 帐户 设置密码 ; 有关说明,请参见 第2.10.4节“保护初始MySQL帐户”

  • 如果您已将现有MySQL安装更新到较新版本,那么您是否执行了MySQL升级过程? 如果没有,请这样做。 添加新功能时,授权表的结构会偶尔发生变化,因此在升级之后,应始终确保表具有当前结构。 有关说明,请参见 第2.11节“升级MySQL”

  • 如果客户端程序在尝试连接时收到以下错误消息,则表示服务器期望密码的格式比客户端能够生成的格式更新:

    外壳> mysql
    客户端不支持请求的身份验证协议
    由服务器; 考虑升级MySQL客户端
    
  • 请记住,客户端程序使用选项文件或环境变量中指定的连接参数。 如果客户端程序在您未在命令行中指定它们时似乎发送了错误的默认连接参数,请检查所有适用的选项文件和您的环境。 例如,如果 Access denied 在没有任何选项的情况下运行客户端时 获得 ,请确保未在任何选项文件中指定旧密码!

    您可以通过使用该 --no-defaults 选项 调用客户端程序来禁止使用选项文件 例如:

    外壳> mysqladmin --no-defaults -u root version
    

    客户端使用的选项文件在 第4.2.2.2节“使用选项文件” 中列出 第4.9节“MySQL程序环境变量” 中列出了 环境变量

  • 如果您收到以下错误,则表示您使用的 root 密码 不正确

    外壳> mysqladmin -u root -pxxxx ver
    用户'root'@'localhost'拒绝访问(使用密码:YES)
    

    如果即使您未指定密码也会发生上述错误,则表示某些选项文件中列出了错误的密码。 尝试 --no-defaults 上一项中描述 选项。

    有关更改密码的信息,请参见 第6.2.14节“分配帐户密码”

    如果丢失或忘记了 root 密码,请参见 第B.4.3.2节“如何重置root密码”

  • localhost 是本地主机名的同义词,如果未明确指定主机,它也是客户端尝试连接的默认主机。

    您可以使用 --host=127.0.0.1 选项明确命名服务器主机。 这将与本地 mysqld 服务器 建立TCP / IP连接 您还可以通过指定 --host 使用本地主机的实际主机名的选项来 使用TCP / IP 在这种情况下,必须 user 在服务器主机上的表行中 指定主机名 ,即使您在与服务器相同的主机上运行客户端程序也是如此。

  • Access denied 错误消息告诉您尝试登录的对象,您尝试连接的客户端主机以及您是否使用了密码。 通常, user 表中 应该有一行 与错误消息中给出的主机名和用户名完全匹配。 例如,如果您收到包含的错误消息 using password: NO ,则表示您尝试在没有密码的情况下登录。

  • 如果 Access denied 在尝试连接到数据库时出错 ,则 可能存在问题 通过执行 并发出以下SQL语句来检查: mysql -u user_name user mysql -u root mysql

    SELECT * FROM user;
    

    结果应该包含一行,其中 Host User 列匹配客户端的主机名和MySQL用户名。

  • 如果尝试从运行MySQL服务器的主机以外的主机进行连接时发生以下错误,则表示 user 表中 没有 Host 与客户端主机匹配的值的

    Host ...不允许连接到此MySQL服务器
    

    您可以通过为尝试连接时使用的客户端主机名和用户名的组合设置帐户来解决此问题。

    如果您不知道要连接的计算机的IP地址或主机名,则应 表中添加 一行 '%' 作为 Host 列值 user 尝试从客户端计算机连接后,使用 SELECT USER() 查询来查看您的连接方式。 然后 '%' user 表行中的 更改 为日志中显示的实际主机名。 否则,您的系统将处于不安全状态,因为它允许来自任何主机的连接以获取给定的用户名。

    在Linux上,可能发生此错误的另一个原因是您使用的二进制MySQL版本使用与 glibc 您使用 不同版本的 库进行 编译 在这种情况下,您应该升级操作系统 glibc ,或者下载MySQL版本的源代码发行版并 自行 编译。 源RPM通常很容易编译和安装,所以这不是一个大问题。

  • 如果在尝试连接时指定主机名,但是获取未显示主机名或IP地址的错误消息,则表示尝试将客户端主机的IP地址解析为MySQL服务器时出错一个名字:

    外壳> mysqladmin -u root -pxxxx -h some_hostname ver
    用户'root'@''访问被拒绝(使用密码:YES)
    

    如果您尝试连接as root 并获得以下错误,则表示您的 user 表中没有 User 列值为的行, 'root' 并且 mysqld 无法解析客户端的主机名:

    访问被拒绝用户''@'未知'
    

    这些错误表明存在DNS问题。 要修复它,请执行 mysqladmin flush-hosts 以重置内部DNS主机缓存。 请参见 第8.12.4.2节“DNS查找优化和主机缓存”

    一些永久解决方案是:

    • 确定DNS服务器的问题并进行修复。

    • 在MySQL授权表中指定IP地址而不是主机名。

    • /etc/hosts 在Unix或 \windows\hosts Windows 为客户端计算机名称添加条目

    • 使用该 选项 启动 mysqld --skip-name-resolve

    • 使用该 选项 启动 mysqld --skip-host-cache

    • 在Unix上,如果您在同一台计算机上运行服务器和客户端,请连接到 localhost 对于连接 localhost ,MySQL程序尝试使用Unix套接字文件连接到本地服务器,除非指定了连接参数以确保客户端建立TCP / IP连接。 有关更多信息,请参见 第4.2.3节“连接到MySQL服务器”

    • 在Windows上,如果在同一台计算机上运行服务器和客户端,并且服务器支持命名管道连接,请连接到主机名 . (句点)。 连接 . 使用命名管道而不是TCP / IP。

  • 如果 mysql -u root 有效但 结果 本地主机的实际主机名 哪里 ), 表中 的主机可能没有正确的名称 这里的常见问题是 表行 中的 指定了非限定主机名,但系统的名称解析例程返回完全限定的域名(反之亦然)。 举例来说,如果你有一排主机 表,但是你的DNS告诉MySQL你的主机名是 ,行也不行。 尝试在 包含主机IP地址 表中 添加一行 作为 mysql -h your_hostname -u root Access denied your_hostname user Host user 'pluto' user 'pluto.example.com' user Host 列值。 (或者,您可以 user 使用 Host 包含通配符 表中 添加一行 (例如, 'pluto.%' )。但是,使用以 Host 值结尾 % 不安全的 建议使用!)

  • 如果 有效但 没有,则您没有授予对指定数据库的给定用户的访问权限 mysql -u user_name mysql -u user_name some_db some_db

  • 如果 在服务器主机上执行时有效,但 在远程客户端主机上执行时无效 则表示尚未从远程主机启用对服务器的访问权限。 mysql -u user_name mysql -h host_name -u user_name

  • 如果您无法弄清楚为什么会得到 Access denied ,请从 user 表中 删除 所有 Host 包含通配符值的行(包含 '%' '_' 字符的 )。 一个非常常见的错误是使用 Host = '%' User = 插入一个新行 ,认为这使您可以指定 从同一台计算机进行连接。 这不起作用的原因是默认权限包括带 = = 的行 因为该行的 比特定的更具体 'some_user' localhost Host 'localhost' User '' Host 'localhost' '%' ,连接时优先使用新行 localhost 正确的步骤是插入一个第二行与 Host = 'localhost' User = ,或删除的行 = = 删除行后,请记住发出 声明以重新加载授权表。 另请参见 第6.2.6节“访问控制,第1阶段:连接验证” 'some_user' Host 'localhost' User '' FLUSH PRIVILEGES

  • 如果您能够连接到MySQL服务器,但 Access denied 在发出 SELECT ... INTO OUTFILE LOAD DATA 声明 收到 消息 ,则 user 表中的 不会 FILE 启用 权限。

  • 如果直接更改授权表(例如,通过using INSERT UPDATE DELETE 语句)并且您的更改似乎被忽略,请记住您必须执行 FLUSH PRIVILEGES 语句或 mysqladmin flush-privileges 命令以使服务器重新加载权限表。 否则,在下次重新启动服务器之前,您的更改将无效。 请记住,在 root 使用 UPDATE 语句 更改 密码 后,在刷新权限之前,您无需指定新密码,因为服务器不知道您已更改密码了!

  • 如果您的权限在会话中间似乎已更改,则可能是MySQL管理员已更改它们。 重新加载授权表会影响新的客户端连接,但它也会影响现有连接,如 第6.2.13节“特权更改生效时”所示

  • 如果您有Perl,PHP,Python或ODBC程序的访问问题,请尝试使用 连接到服务器 如果您能够使用 mysql 客户端 进行连接 ,则问题在于您的程序,而不是访问权限。 密码和密码 之间没有空格 ;您也可以使用 语法指定密码。如果您使用 没有密码值 选项,MySQL会提示您输入密码。) mysql -u user_name db_name mysql -u user_name -pyour_pass db_name -p --password=your_pass -p --password

  • 出于测试目的, 使用该 选项 启动 mysqld 服务器 --skip-grant-tables 然后,您可以更改MySQL授权表并使用该 SHOW GRANTS 语句检查您的修改是否具有所需的效果。 如果对更改感到满意,请执行 mysqladmin flush-privileges 以告知 mysqld 服务器重新加载权限。 这使您可以开始使用新的授权表内容,而无需停止并重新启动服务器。

  • 如果其他一切都失败了,请 使用调试选项 启动 mysqld 服务器(例如, --debug=d,general,query )。 这将打印有关尝试连接的主机和用户信息,以及有关所发出的每个命令的信息。 请参见 第29.5.4节“DBUG包”

  • 如果您对MySQL授权表有任何其他问题,并且认为必须将问题发布到邮件列表,请始终提供MySQL授权表的转储。 您可以使用 mysqldump mysql 命令 转储表 要提交错误报告,请参见 第1.7节“如何报告错误或问题”中的说明 在某些情况下,你可能需要重新启动 mysqld的 --skip-grant-tables 运行 的mysqldump

6.2.22基于SQL的帐户活动审计

应用程序可以使用以下准则来执行基于SQL的审计,该审计将数据库活动与MySQL帐户联系起来。

MySQL帐户对应于 mysql.user 系统表中的 当客户端成功连接时,服务器会将客户端验证到此表中的特定行。 此行中 User Host 列值唯一标识帐户,并对应于 在SQL语句中写入帐户名称 格式。 'user_name'@'host_name'

用于验证客户端的帐户确定客户端具有哪些权限。 通常, CURRENT_USER() 可以调用 函数来确定这对于客户端用户来说是哪个帐户。 其值由 帐户 表行的 User Host 列构成 user

但是,在某些情况下,该 CURRENT_USER() 值不对应于客户端用户,而是对应于不同的帐户。 当权限检查不基于客户端帐户时,会发生这种情况:

  • 存储的例程(过程和函数)定义了 SQL SECURITY DEFINER 特征

  • SQL SECURITY DEFINER 特征 定义的视图

  • 触发器和事件

在这些上下文中,对 DEFINER 帐户 进行权限检查 CURRENT_USER() 引用该帐户,而不是引用调用存储的例程或视图的客户端或引发触发器的用户的帐户。 要确定调用用户,可以调用该 USER() 函数,该函数返回一个值,该值指示客户端提供的实际用户名以及客户端连接的主机。 但是,此值不一定直接对应于 user 表中 的帐户 ,因为该 USER() 值从不包含通配符,而帐户值(由返回的 CURRENT_USER() )可能包含用户名和主机名通配符。

例如,空白用户名与任何用户匹配,因此帐户 ''@'localhost' 允许客户端以本地主机的匿名用户身份使用任何用户名进行连接。 在这种情况下,如果客户端 user1 从本地主机 连接 USER() CURRENT_USER() 返回不同的值:

MySQL的> SELECT USER(), CURRENT_USER();
+ ----------------- + ---------------- +
| USER()| CURRENT_USER()|
+ ----------------- + ---------------- +
| user1 @ localhost | @localhost |
+ ----------------- + ---------------- +

帐户的主机名部分也可以包含通配符。 如果主机名包含 '%' '_' 模式字符或使用网络掩码表示法,则该帐户可用于从多个主机连接的客户端,该 CURRENT_USER() 值不会指示哪个 主机 例如,该帐户 'user2'@'%.example.com' 可用于 user2 example.com 域中的 任何主机进行连接 如果 user2 连接 remote.example.com USER() CURRENT_USER() 返回不同的值:

MySQL的> SELECT USER(), CURRENT_USER();
+ -------------------------- + --------------------- +
| USER()| CURRENT_USER()|
+ -------------------------- + --------------------- +
| user2@remote.example.com | user2@%.example.com |
+ -------------------------- + --------------------- +

如果应用程序必须 USER() 为用户审核 调用 (例如,如果它从触发器内部进行审核),但也必须能够将该 USER() 值与 user 表中 的帐户 相关联 ,则必须避免在 User Host 中包含通配符的帐户 具体来说,不允许 User 为空(创建匿名用户帐户),并且不允许在 Host 值中使用 模式字符或网络掩码表示法 所有帐户必须具有非空 User 值和字 Host 面值。

对于前面的示例, 应更改 ''@'localhost' 'user2'@'%.example.com' 帐户不使用通配符:

RENAME USER''@'localhost'TO'user1'@'localhost';
RENAME USER'user2'@'%.example.com'TO'user2'@'remote.example.com';

如果 user2 必须能够从 example.com 域中的 多个主机进行连接 ,则每个主机应该有一个单独的帐户。

要从 CURRENT_USER() USER() 值中 提取用户名或主机名部分 ,请使用以下 SUBSTRING_INDEX() 函数:

MySQL的> SELECT SUBSTRING_INDEX(CURRENT_USER(),'@',1);
+ --------------------------------------- +
| SUBSTRING_INDEX(CURRENT_USER(),'@',1)|
+ --------------------------------------- +
| user1 |
+ --------------------------------------- +

MySQL的> SELECT SUBSTRING_INDEX(CURRENT_USER(),'@',-1);
+ ---------------------------------------- +
| SUBSTRING_INDEX(CURRENT_USER(),'@', -  1)|
+ ---------------------------------------- +
| localhost |
+ ---------------------------------------- +

6.3使用加密连接

通过MySQL客户端和服务器之间的未加密连接,有权访问网络的人可以查看所有流量并检查客户端和服务器之间发送或接收的数据。

当您必须以安全的方式通过网络移动信息时,未加密的连接是不可接受的。 要使任何类型的数据不可读,请使用加密。 加密算法必须包含安全元素,以抵御多种已知攻击,例如更改加密消息的顺序或重放数据两次。

MySQL支持使用TLS(传输层安全性)协议在客户端和服务器之间建立加密连接。 TLS有时被称为SSL(安全套接字层),但MySQL实际上并不使用SSL协议进行加密连接,因为它的加密很弱(请参见 第6.3.6节“加密连接协议和密码” )。

TLS使用加密算法来确保可以信任通过公共网络接收的数据。 它具有检测数据更改,丢失或重放的机制。 TLS还包含使用X.509标准提供身份验证的算法。

X.509可以识别互联网上的某个人。 在基本术语中,应该有一些称为 证书颁发机构 (或CA)的 实体 ,它将电子证书分配给需要它们的任何人。 证书依赖于具有两个加密密钥(公钥和密钥)的非对称加密算法。 证书所有者可以将证书提供给另一方作为身份证明。 证书由其所有者的公钥组成。 使用该公钥加密的任何数据只能使用由证书所有者持有的相应密钥解密。

可以使用OpenSSL或wolfSSL编译MySQL以获得加密连接支持。 有关这些软件包的比较,请参见 第6.3.4节“SSL库相关功能”。 有关每个软件包支持的加密协议和密码的信息,请参见 第6.3.6节“加密连接协议和密码”

默认情况下,如果服务器支持加密连接,MySQL程序将尝试使用加密进行连接,如果无法建立加密连接,则会回退到未加密的连接。 有关影响加密连接使用的选项的信息,请参见 第6.3.1节“配置MySQL以使用加密连接” 第6.3.2节“加密连接的命令选项”

MySQL基于每个连接执行加密,并且对给定用户使用加密可以是可选的或强制的。 这使您可以根据各个应用程序的要求选择加密或未加密的连接。 有关如何要求用户使用加密连接的信息,请参见 第13.7.1.3节“创建用户语法” REQUIRE 中对 CREATE USER 语句 子句 的讨论 另见的描述 系统变量在 第5.1.8节,“服务器系统变量” require_secure_transport

可以在主复制服务器和从属复制服务器之间使用加密连接。 请参见 第17.3.9节“设置复制以使用加密连接”

有关使用MySQL C API的加密连接的信息,请参见 第28.7.22节“C API加密连接支持”

也可以使用SSH连接内的加密连接到MySQL服务器主机。 有关示例,请参见 第6.3.7节“使用SSH从Windows远程连接到MySQL”

6.3.1配置MySQL使用加密连接

有几个选项可用于指示是否使用加密连接,以及指定适当的证书和密钥文件。 本节提供有关为加密连接配置服务器和客户端的一般指导:

有关建立加密连接的选项的完整列表,请参见 第6.3.2节“加密连接的命令选项” 有关创建任何所需证书和密钥文件的说明,请参见 第6.3.3节“创建SSL和RSA证书和密钥”

加密连接也可以在这些上下文中使用:

加密连接的服务器端启动配置

在服务器端,该 --ssl 选项指定服务器允许但不需要加密连接。 默认情况下启用此选项,因此无需显式指定。

要要求客户端使用加密连接进行连接,请启用 require_secure_transport 系统变量。 请参阅将 加密连接配置为必需

服务器端的这些选项指定服务器在允许客户端建立加密连接时使用的证书和密钥文件:

  • --ssl-ca :证书颁发机构(CA)证书文件的路径名。 --ssl-capath 类似但指定CA证书文件目录的路径名。)

  • --ssl-cert :服务器公钥证书文件的路径名。 可以将此证书发送到客户端,并根据其拥有的CA证书进行身份验证。

  • --ssl-key :服务器私钥文件的路径名。

例如,要为服务器启用加密连接,请在 my.cnf 文件中 使用这些行启动它, 根据需要更改文件名:

的[mysqld]
SSL的CA = ca.pem
SSL证书=服务器cert.pem
SSL的密钥=服务器key.pem

要另外指定客户端需要使用加密连接,请启用 require_secure_transport 系统变量:

的[mysqld]
SSL的CA = ca.pem
SSL证书=服务器cert.pem
SSL的密钥=服务器key.pem
require_secure_transport = ON

每个证书和密钥选项都以PEM格式命名文件。 如果需要创建所需的证书和密钥文件,请参见 第6.3.3节“创建SSL和RSA证书和密钥” 使用OpenSSL编译的MySQL服务器可以在启动时自动生成缺少的证书和密钥文件。 请参见 第6.3.3.1节“使用MySQL创建SSL和RSA证书和密钥” 或者,如果您有MySQL源代码分发,则可以使用其 mysql-test/std_data 目录中 的演示证书和密钥文件来测试您的设置

服务器执行证书和密钥文件自动发现。 如果 --ssl 启用(可能同时 --ssl-cipher )并且 给出 其他 选项 以明确配置加密连接,则服务器会尝试在启动时自动启用加密连接支持: --ssl-xxx

  • 如果服务器发现有效的证书和命名的密钥文件 ca.pem server-cert.pem 以及 server-key.pem 在数据目录中,它能够通过客户端加密的连接支持。 (这些文件不需要自动生成;重要的是它们具有这些名称并且是有效的。)

  • 如果服务器在数据目录中找不到有效的证书和密钥文件,它将继续执行但不支持加密连接。

如果服务器自动启用加密连接支持,它会将注释写入错误日志。 如果服务器发现CA证书是自签名的,则会向错误日志写入警告。 (如果服务器自动创建证书,则证书是自签名的,或者使用 mysql_ssl_rsa_setup 手动创建 证书 。)

MySQL还为服务器端SSL控制提供了以下选项:

  • --ssl-cipher :用于连接加密的允许密码列表。

  • --ssl-crl :包含证书吊销列表的文件的路径名。 --ssl-crlpath 类似但指定证书吊销列表文件的目录的路径名。)

的值 选项中设置相应的系统变量的(值 ,等等)。 --ssl-xxx ssl_ca ssl_cert ssl_key

要明确指定服务器允许加密连接的加密协议和密码套件,请使用 tls_version tls_ciphersuites 系统变量; 请参见 第6.3.6节“加密连接协议和密码” 例如,您可以设置 tls_version 为阻止客户端使用安全性较低的协议。

加密连接的服务器端运行时配置

某些加密相关的系统变量可以在运行时设置: require_secure_transport 和(从MySQL 8.0.16开始) tls_version tls_ciphersuites 如果更改为 SET GLOBAL ,则新值适用于更改后建立的连接,并仅应用于服务器重新启动。 如果更改为 SET PERSIST ,则新值也适用于后续服务器重新启动。 请参见 第13.7.5.1节“变量赋值的SET语法”

此外,从MySQL 8.0.16开始,服务器用于新连接的SSL上下文在运行时可重新配置。 例如,此功能可能很有用,可以避免重新启动已运行太久以至于其SSL证书已过期的MySQL服务器。

服务器根据上下文相关的系统变量在启动时具有的值创建初始SSL上下文。 它还初始化一组与上下文相关的状态变量,以指示上下文中使用的值。 下表显示了定义SSL上下文的系统变量以及指示当前活动上下文值的相应状态变量。


要在运行时重新配置SSL上下文,请使用以下过程:

  1. 设置应更改为其新值的任何与SSL上下文相关的系统变量。

  2. 执行 ALTER INSTANCE RELOAD TLS 此语句从SSL上下文相关系统变量的当前值重新配置活动SSL上下文。 它还设置与上下文相关的状态变量以反映新的活动上下文值。 该声明需要 CONNECTION_ADMIN 特权。

  3. 执行 ALTER INSTANCE RELOAD TLS 使用新SSL上下文 后建立的新连接 现有连接不受影响。 如果应终止现有连接,请使用该 KILL 语句。

由于重新配置过程的工作方式,每对系统和状态变量的成员可能会暂时具有不同的值:

  • ALTER INSTANCE RELOAD TLS 更改SSL上下文 之前对系统变量的 更改。 此时,这些更改对新连接没有影响,并且相应的上下文相关系统和状态变量可能具有不同的值。 这使您可以对系统变量进行任何更改,然后在 ALTER INSTANCE RELOAD TLS 完成所有系统变量更改后, 以原子方式更新活动SSL上下文

  • 之后 ALTER INSTANCE RELOAD TLS ,相应的系统和状态变量具有相同的值。 在下次更改系统变量之前,这一点仍然有效。

在某些情况下, ALTER INSTANCE RELOAD TLS 本身可能足以重新配置SSL上下文,而无需更改任何系统变量。 假设名为的文件中的证书 ssl_cert 已过期。 用未映射的证书替换现有文件内容就足够了,并执行 ALTER INSTANCE RELOAD TLS 以使新文件内容被读取并用于新连接。

默认情况下, RELOAD TLS 如果配置值不允许创建新的SSL上下文 ,则 操作将回滚并显示错误,并且无效。 先前的上下文值继续用于新连接。

如果 NO ROLLBACK ON ERROR 给出 了可选 子句并且无法创建新上下文,则不会发生回滚。 而是生成警告,并为新连接禁用SSL。

服务器端 --ssl 选项仅在服务器启动时才会影响服务器是否接受SSL连接。 它被忽略,并且对...的操作没有影响 ALTER INSTANCE RELOAD TLS 例如,您可以使用 --ssl=0 禁用SSL连接来启动服务器,然后重新配置SSL并执行 ALTER INSTANCE RELOAD TLS 以在运行时启用SSL连接。

ALTER INSTANCE RELOAD TLS 仅更改服务器本身用于新连接的SSL上下文。 它不会影响其他已启用的服务器插件或组件(如X插件或组复制)使用的SSL上下文。

注意

在MySQL 8.0.16之前,SSL上下文相关的系统变量不是动态的。 它们可以在服务器启动时设置,但之后无法更改。 因此,这些系统变量确定服务器用于所有新连接的SSL上下文值。

加密连接的客户端配置

默认情况下,如果服务器支持加密连接,MySQL客户端程序将尝试建立加密连接,并通过以下 --ssl-mode 选项 进一步控制

  • 如果没有 --ssl-mode 选项,客户端将尝试使用加密进行连接,如果无法建立加密连接,则会回退到未加密的连接。 这也是具有显式 --ssl-mode=PREFFERED 选项 的行为

  • 使用时 --ssl-mode=REQUIRED ,客户端需要加密连接,如果无法建立,则会失败。

  • 使用 --ssl-mode=DISABLED ,客户端使用未加密的连接。

  • 使用 --ssl-mode=VERIFY_CA --ssl-mode=VERIFY_IDENTITY ,客户端需要加密连接,并对服务器CA证书和(与 VERIFY_IDENTITY 证书 中的服务器主机名执行验证。

如果在 require_secure_transport 服务器端启用 系统变量以使服务器需要加密连接, 则尝试建立未加密的连接会失败 请参阅将 加密连接配置为必需

客户端上的以下选项标识客户端在建立到服务器的加密连接时使用的证书和密钥文件。 它们类似于在服务器端使用的选项,但 --ssl-cert --ssl-key 识别客户端公钥和私钥:

  • --ssl-ca :证书颁发机构(CA)证书文件的路径名。 如果使用此选项,则必须指定服务器使用的相同证书。 --ssl-capath 类似但指定CA证书文件目录的路径名。)

  • --ssl-cert :客户端公钥证书文件的路径名。

  • --ssl-key :客户端私钥文件的路径名。

为了提供相对于默认加密提供的安全性的额外安全性,客户端可以提供与服务器使用的CA证书匹配的CA证书,并启用主机名身份验证。 通过这种方式,服务器和客户端将信任放在同一个CA证书中,并且客户端会验证它所连接的主机是否为预期的主机:

注意

主机名身份验证 VERIFY_IDENTITY 不适用于服务器自动创建的自签名证书 也不能使用 mysql_ssl_rsa_setup 手动使用 (请参见 第6.3.3.1节“使用MySQL创建SSL和RSA证书和密钥” )。 此类自签名证书不包含服务器名称作为Common Name值。

主机名身份验证也不适用于使用通配符指定公用名的证书,因为该名称将逐字比较到服务器名称。

MySQL还为客户端SSL控制提供了以下选项:

根据客户端使用的MySQL帐户的加密要求,客户端可能需要指定使用加密连接到MySQL服务器的某些选项。

假设您要使用没有特殊加密要求的帐户或使用 CREATE USER 包含该 REQUIRE SSL 子句 语句 创建的帐户进行连接 假设服务器支持加密连接,客户端可以使用加密连接,没有 --ssl-mode 选项或显式 --ssl-mode=PREFFERED 选项:

MySQL的

要么:

mysql --ssl-mode = PREFERRED

对于使用 REQUIRE SSL 子句 创建的帐户 ,如果无法建立加密连接,则连接尝试将失败。 对于没有特殊加密要求的帐户,如果无法建立加密连接,则尝试将回退到未加密的连接。 如果无法获得加密连接以防止回退和失败,请按以下方式连接:

mysql --ssl-mode = REQUIRED

如果帐户具有更严格的安全要求,则必须指定其他选项以建立加密连接:

  • 对于使用 REQUIRE X509 子句 创建的帐户 ,客户端必须至少指定 --ssl-cert --ssl-key 此外, 建议使用 --ssl-ca (或 --ssl-capath ),以便验证服务器提供的公共证书。 例如:

    mysql --ssl-ca = ca.pem \
          --ssl-cert = client-cert.pem \
          --ssl密钥=客户端 -  key.pem
    
  • 对于使用 REQUIRE ISSUER or REQUIRE SUBJECT 子句 创建的帐户 ,加密要求与for相同 REQUIRE X509 ,但证书必须分别与帐户定义中指定的问题或主题匹配。

有关该 REQUIRE 子句的 其他信息 ,请参见 第13.7.1.3节“CREATE USER语法”

要防止使用加密并覆盖其他 选项,请使用以下命令调用客户端程序 --ssl-xxx --ssl-mode=DISABLED

mysql --ssl-mode = DISABLED

要确定当前与服务器的连接是否使用加密,请检查 Ssl_cipher 状态变量 的会话值 如果值为空,则表示连接未加密。 否则,连接被加密,值表示加密密码。 例如:

MySQL的> SHOW SESSION STATUS LIKE 'Ssl_cipher';
+ --------------- + --------------------------- +
| Variable_name | 价值|
+ --------------- + --------------------------- +
| Ssl_cipher | DHE-RSA-AES128-GCM-SHA256 |
+ --------------- + --------------------------- +

对于 mysql 客户端,另一种方法是使用 STATUS or \s 命令并检查 SSL 行:

MySQL的> \s
...
SSL:未使用
...

要么:

MySQL的> \s
...
SSL:使用的密码是DHE-RSA-AES128-GCM-SHA256
...

将加密连接配置为必需

对于某些MySQL部署,使用加密连接(例如,满足法规要求)不仅是可取的,而且是强制性的。 本节讨论使您能够执行此操作的配置设置。 这些控制级别可用:

  • 您可以将服务器配置为要求客户端使用加密连接进行连接。

  • 您可以调用单个客户端程序以要求加密连接,即使服务器允许但不需要加密。

  • 您可以将单个MySQL帐户配置为仅在加密连接上可用。

要要求客户端使用加密连接进行连接,请启用 require_secure_transport 系统变量。 例如,将这些行放在服务器 my.cnf 文件中:

的[mysqld]
require_secure_transport = ON

或者,要在运行时设置并保持该值,请使用以下语句:

SET PERSIST require_secure_transport = ON;

SET PERSIST 设置正在运行的MySQL实例的值。 它还会保存该值,使其用于后续服务器重新启动。 请参见 第13.7.5.1节“变量赋值的SET语法”

require_secure_transport 启用,到服务器的客户端连接都需要使用某种形式的安全传输,而服务器只允许使用SSL的TCP / IP连接,或使用一个套接字文件(在Unix)连接或共享内存(在Windows上)。 服务器拒绝不安全的连接尝试,该尝试因 ER_SECURE_TRANSPORT_REQUIRED 错误 而失败

调用的客户端程序,使得它需要加密连接服务器是否需要加密,使用 --ssl-mode 的选项值 REQUIRED VERIFY_CA VERIFY_IDENTITY 例如:

mysql --ssl-mode = REQUIRED
mysqldump --ssl-mode = VERIFY_CA
mysqladmin --ssl-mode = VERIFY_IDENTITY

要将MySQL帐户配置为仅在加密连接上可用,请 REQUIRE CREATE USER 创建帐户 语句中 包含一个 子句 ,在该子句中指定所需的加密特征。 例如,要要求加密连接并使用有效的X.509证书,请使用 REQUIRE X509

CREATE USER'jeffrey'@'localhost'REQUIRE X509;

有关该 REQUIRE 子句的 其他信息 ,请参见 第13.7.1.3节“CREATE USER语法”

要修改没有加密要求的现有帐户,请使用该 ALTER USER 语句。

6.3.2加密连接的命令选项

本节介绍指定是使用加密连接的选项,证书和密钥文件的名称以及与加密连接支持相关的其他参数。 可以在命令行或选项文件中提供这些选项。 有关建议用法的示例以及如何检查连接是否已加密,请参见 第6.3.1节“配置MySQL以使用加密连接”

有关使用MySQL C API的加密连接的信息,请参见 第28.7.22节“C API加密连接支持”

表6.12加密连接选项摘要

格式 描述 介绍
--skip-SSL 不要使用加密连接
--ssl 启用加密连接
--ssl-CA 包含受信任的SSL证书颁发机构列表的文件
--ssl-capath 包含受信任的SSL证书颁发机构证书文件的目录
--ssl证书 包含X.509证书的文件
--ssl-密码 用于连接加密的允许密码列表
--ssl-CRL 包含证书吊销列表的文件
--ssl-crlpath 包含证书吊销列表文件的目录
--ssl-FIPS模式 是否在客户端启用FIPS模式 8.0.11
--ssl键 包含X.509密钥的文件
--ssl模式 与服务器连接的安全状态
--tls-密码套件 允许加密连接的TLSv1.3密码套件 8.0.16
--tls版本 允许加密连接的协议

  • --ssl

    注意

    --ssl MySQL 8.0中删除了 客户端 选项。 对于客户端程序,请 --ssl-mode 改用。

    在服务器端,该 --ssl 选项指定服务器允许但不需要加密连接。 默认情况下,该选项在服务器端启用。 --ssl 其他 选项 暗示了 这些选项的描述中所示。 --ssl-xxx

    --ssl 以否定的形式选项表示加密应该 使用,并覆盖其他 选项。 将选项指定为 或同义词( )。 --ssl-xxx --ssl=0 --skip-ssl --disable-ssl

    要加密的连接指定其他参数,至少使用 --ssl-cert --ssl-key 在服务器侧和 --ssl-ca 客户端侧。 请参见 第6.3.1节“配置MySQL以使用加密连接” 该部分还描述了证书和密钥文件自动生成和自动发现的服务器功能。

  • --ssl-ca=file_name

    PEM格式的证书颁发机构(CA)证书文件的路径名。 在服务器端,此选项意味着 --ssl

    要在建立与服务器的加密连接时告诉客户端不要验证服务器证书,请同时指定 --ssl-ca nor --ssl-capath 服务器仍然根据为客户端帐户建立的任何适用要求验证客户端,并且它仍然使用 服务器端指定的 任何 --ssl-ca --ssl-capath 选项值。

  • --ssl-capath=dir_name

    包含PEM格式的受信任SSL证书颁发机构(CA)证书文件的目录的路径名。 在服务器端,此选项意味着 --ssl

    要在建立与服务器的加密连接时告诉客户端不要验证服务器证书,请同时指定 --ssl-ca nor --ssl-capath 服务器仍然根据为客户端帐户建立的任何适用要求验证客户端,并且它仍然使用 服务器端指定的 任何 --ssl-ca --ssl-capath 选项值。

    对此选项的支持取决于用于编译MySQL的SSL库。 请参见 第6.3.4节“SSL库相关功能”

  • --ssl-cert=file_name

    PEM格式的SSL公钥证书文件的路径名。 在客户端,这是客户端公钥证书。 在服务器端,这是服务器公钥证书。 在服务器端,此选项意味着 --ssl

  • --ssl-cipher=cipher_list

    用于连接加密的允许密码列表。 如果支持列表中的密码,则加密连接将不起作用。 在服务器端,此选项意味着 --ssl

    为了获得最大的可移植性, cipher_list 应该是一个由冒号分隔的一个或多个密码名称的列表。 例子:

    --ssl-密码= AES128-SHA
    --ssl-密码= DHE-RSA-AES128-GCM-SHA256:AES128-SHA
    

    OpenSSL支持更灵活的语法来指定密码,如 https://www.openssl.org/docs/manmaster/man1/ciphers.html上 的OpenSSL文档中所述 wolfSSL没有,因此尝试使用扩展语法失败,因为使用wolfSSL编译的MySQL分发。

    有关MySQL支持哪些加密密码的信息,请参见 第6.3.6节“加密连接协议和密码”

  • --ssl-crl=file_name

    包含证书吊销的文件的路径名以PEM格式列出。 在服务器端,此选项意味着 --ssl

    如果既未 给出 --ssl-crl --ssl-crlpath 给出,则即使CA路径包含证书吊销列表,也不执行CRL检查。

    对此选项的支持取决于用于编译MySQL的SSL库。 请参见 第6.3.4节“SSL库相关功能”

  • --ssl-crlpath=dir_name

    包含PEM格式的证书吊销列表文件的目录的路径名。 在服务器端,此选项意味着 --ssl

    如果既未 给出 --ssl-crl --ssl-crlpath 给出,则即使CA路径包含证书吊销列表,也不执行CRL检查。

    对此选项的支持取决于用于编译MySQL的SSL库。 请参见 第6.3.4节“SSL库相关功能”

  • --ssl-fips-mode={OFF|ON|STRICT}

    控制是否在客户端启用FIPS模式。 --ssl-fips-mode 选项与其他选项的不同之处在于 ,它不用于建立加密连接,而是用于影响允许的加密操作。 请参见 第6.5节“FIPS支持” --ssl-xxx

    --ssl-fips-mode 允许 这些 值:

    • OFF :禁用FIPS模式。

    • ON :启用FIPS模式。

    • STRICT :启用 严格 FIPS模式。

    注意

    如果OpenSSL的FIPS对象模块不可用时,对于唯一的允许值 --ssl-fips-mode OFF 在这种情况下,设置 --ssl-fips-mode ON STRICT 导致客户端在启动时生成警告并在非FIPS模式下运行。

  • --ssl-key=file_name

    PEM格式的SSL私钥文件的路径名。 在客户端,这是客户端私钥。 在服务器端,这是服务器私钥。 在服务器端,此选项意味着 --ssl

    如果密钥文件受密码短语保护,则程序会提示用户输入密码短语。 密码必须以交互方式提供; 它不能存储在文件中。 如果密码不正确,程序将继续,就好像它无法读取密钥一样。

    为了更好的安全性,请使用RSA密钥大小至少为2048位的证书。

  • --ssl-mode=mode

    此选项仅适用于客户端程序,而不适用于服务器。 它指定与服务器的连接的安全状态。 允许使用以下选项值:

    • PREFERRED :如果服务器支持加密连接,则建立加密连接;如果无法建立加密连接,则回退到未加密连接。 如果 --ssl-mode 未指定, 则为默认值

      默认情况下禁用Unix套接字上 PREFERRED 的加密连接 ,因此 不会建立加密连接。 要对Unix套接字连接强制执行加密,请使用 REQUIRED 或以上。

    • REQUIRED :如果服务器支持加密连接,则建立加密连接。 如果无法建立加密连接,则连接尝试将失败。

    • VERIFY_CA :Like REQUIRED ,但另外根据配置的CA证书验证服务器证书颁发机构(CA)证书。 如果未找到有效的匹配CA证书,则连接尝试将失败。

    • VERIFY_IDENTITY :喜欢 VERIFY_CA ,但另外通过检查客户端用于连接服务器的主机名与服务器发送给客户端的证书中的标识来执行主机名身份验证:

      • 从MySQL 8.0.12开始,如果客户端使用OpenSSL 1.0.2或更高版本,则客户端会检查它用于连接的主机名是否与服务器证书中的“使用者备用名称”值或“公用名”值匹配。

      • 否则,客户端会检查它用于连接的主机名是否与服务器证书中的Common Name值匹配。

      如果不匹配,连接将失败。 对于加密连接,此选项有助于防止中间人攻击。

      注意

      主机名身份验证 VERIFY_IDENTITY 不适用于服务器自动创建的自签名证书 也不能使用 mysql_ssl_rsa_setup 手动使用 (请参见 第6.3.3.1节“使用MySQL创建SSL和RSA证书和密钥” )。 此类自签名证书不包含服务器名称作为Common Name值。

      主机名身份验证也不适用于使用通配符指定公用名的证书,因为该名称将逐字比较到服务器名称。

    • DISABLED :建立未加密的连接。

    --ssl-mode 选项与CA证书选项交互,如下所示:

    要求MySQL帐户使用加密连接,请使用 CREATE USER 创建带有 REQUIRE SSL 子句 的帐户 ,或使用 ALTER USER 现有帐户添加 REQUIRE SSL 子句。 除非MySQL支持加密连接并且可以建立加密连接,否则将拒绝使用该帐户的客户端的连接尝试。

    REQUIRE 条款允许其他与加密相关的选项,这些选项可用于强制执行比更严格的安全要求 REQUIRE SSL 有关其他详细信息有关哪些选项可以或必须由连接使用使用各种配置的帐户的客户来指定命令 REQUIRE 选项,见描述 REQUIRE 第13.7.1.3,“CREATE USER语法”

  • --tls-ciphersuites=ciphersuite_list

    对于客户端程序,指定客户端允许加密连接的TLSv1.3密码套件。 该值是一个或多个以冒号分隔的密码组名称的列表。 例如:

    MySQL的--tls-密码组= “ suite1suite2suite3

    可以为此选项命名的密码套件取决于用于编译MySQL的SSL库。 有关详细信息,请参见 第6.3.6节“加密连接协议和密码”

    MySQL 8.0.16中添加了此选项。

    要指定服务器允许的密码组,请改用 tls_ciphersuites 系统变量。

  • --tls-version=protocol_list

    对于客户端程序,指定客户端允许加密连接的协议。 该值是一个或多个以逗号分隔的协议名称的列表。 例如:

    mysql --tls-version =“TLSv1.1,TLSv1.2”
    

    可以为此选项命名的协议取决于用于编译MySQL的SSL库。 有关详细信息,请参见 第6.3.6节“加密连接协议和密码”

    要指定服务器允许的协议,请改用 tls_version 系统变量。

6.3.3创建SSL和RSA证书和密钥

以下讨论描述了如何在MySQL中创建SSL和RSA支持所需的文件。 可以使用MySQL本身提供的工具或 直接 调用 openssl 命令 来执行文件创建

SSL证书和密钥文件使MySQL能够使用SSL支持加密连接。 请参见 第6.3.1节“配置MySQL以使用加密连接”

RSA密钥文件使MySQL能够通过未加密的连接支持通过 sha256_password caching_sha2_password 插件 验证的帐户的安全密码交换 请参见 第6.4.1.2节“SHA-256可插拔认证” 第6.4.1.3节“高速缓存SHA-2可插入认证”

6.3.3.1使用MySQL创建SSL和RSA证书和密钥

MySQL提供了这些方法来创建SSL证书和密钥文件以及使用SSL支持加密连接所需的RSA密钥对文件,以及使用RSA通过未加密连接进行安全密码交换(如果缺少这些文件):

  • 对于使用OpenSSL编译的MySQL发行版,服务器可以在启动时自动生成这些文件。

  • 用户可以 手动 调用 mysql_ssl_rsa_setup 实用程序。

  • 对于某些分发类型(例如RPM包), 在数据目录初始化期间会发生 mysql_ssl_rsa_setup 调用。 在这种情况下,只要 openssl 命令可用 ,就不需要使用OpenSSL编译MySQL发行 版。

重要

服务器自动生成和 mysql_ssl_rsa_setup 有助于降低使用SSL的障碍,方便生成所需的文件。 但是,这些方法生成的证书是自签名的,可能不是很安全。 获得使用此类文件的经验后,请考虑从已注册的证书颁发机构获取证书/密钥材料。

自动SSL和RSA文件生成

对于使用OpenSSL编译的MySQL发行版,MySQL服务器能够在启动时自动生成缺少的SSL和RSA文件。 auto_generate_certs sha256_password_auto_generate_rsa_keys caching_sha2_password_auto_generate_rsa_keys 系统变量控制自动生成这些文件。 默认情况下启用这些变量。 它们可以在启动时启用并检查,但不能在运行时设置。

启动时,如果 auto_generate_certs 启用 系统变量 ,则服务器会自动在数据目录中生成服务器端和客户端SSL证书和密钥文件 ,不会 --ssl 指定 指定 之外的SSL选项 ,并且数据中缺少服务器端SSL文件目录。 这些文件使用SSL启用加密的客户端连接; 请参见 第6.3.1节“配置MySQL以使用加密连接”

  1. 服务器使用以下名称检查数据目录中的SSL文件:

    ca.pem
    服务器cert.pem
    服务器key.pem
    
  2. 如果存在任何这些文件,则服务器不会创建任何SSL文件。 否则,它会创建它们,以及一些其他文件:

    ca.pem自签名CA证书
    ca-key.pem CA私钥
    server-cert.pem服务器证书
    server-key.pem服务器私钥
    client-cert.pem客户端证书
    client-key.pem客户端私钥
    
  3. 如果服务器自动生成SSL文件,它使用的名称 ca.pem server-cert.pem 以及 server-key.pem 文件来设置相应的系统变量( ssl_ca ssl_cert ssl_key )。

在启动时,如果满足所有这些条件,则服务器会自动在数据目录中生成RSA私钥/公钥对文件: sha256_password_auto_generate_rsa_keys 或者 caching_sha2_password_auto_generate_rsa_keys 启用系统变量; 没有指定RSA选项; 数据目录中缺少RSA文件。 这些密钥对文件通过未加密的连接使用RSA进行安全密码交换,以便对由 sha256_password or或 caching_sha2_password plugin 进行身份验证的帐户进行安全密码交换 请参见 第6.4.1.2节“SHA-256可插拔认证” 第6.4.1.3节“高速缓存SHA-2可插拔认证”

  1. 服务器使用以下名称检查数据目录中的RSA文件:

    private_key.pem私钥/公钥对的私有成员
    public_key.pem私钥/公钥对的公共成员
    
  2. 如果存在任何这些文件,则服务器不会创建任何RSA文件。 否则,它会创建它们。

  3. 如果服务器自动生成RSA文件,它将使用其名称来设置相应的系统变量( sha256_password_private_key_path sha256_password_public_key_path ; caching_sha2_password_private_key_path caching_sha2_password_public_key_path )。

使用mysql_ssl_rsa_setup手动生成SSL和RSA文件

MySQL发行版包括一个 mysql_ssl_rsa_setup 实用程序,可以手动调用 实用程序来生成SSL和RSA文件。 所有MySQL发行版都包含此实用程序(无论是使用OpenSSL还是使用wolfSSL编译),但它确实需要 openssl 命令可用。 有关使用说明,请参见 第4.4.3节“ mysql_ssl_rsa_setup - 创建SSL / RSA文件”

SSL和RSA文件特征

由服务器自动创建或通过调用 mysql_ssl_rsa_setup 创建的SSL和RSA文件 具有以下特征:

  • SSL和RSA密钥的大小为2048位。

  • SSL CA证书是自签名的。

  • 使用 sha256WithRSAEncryption 签名算法 使用CA证书和密钥对SSL服务器和客户端证书进行 签名。

  • SSL证书使用这些公用名(CN)值以及相应的证书类型(CA,Server,Client):

    ca.pem:MySQL_Server_ suffix_Auto_Generated_CA_Certificate
    server-cert.pm:MySQL_Server_ suffix_Auto_Generated_Server_Certificate
    client-cert.pm:MySQL_Server_ suffix_Auto_Generated_Client_Certificate
    

    suffix 值基于MySQL版本号。 对于 mysql_ssl_rsa_setup 生成的文件 ,可以使用该 --suffix 选项 显式指定后缀

    对于服务器生成的文件,如果生成的CN值超过64个字符, 则省略 部分名称。 _suffix

  • SSL文件具有国家/地区(C),州或省(ST),组织(O),组织单位名称(OU)和电子邮件地址的空白值。

  • 服务器或 mysql_ssl_rsa_setup 创建的SSL文件自生成之 日起 有效期为十年。

  • RSA文件不会过期。

  • SSL文件对于每个证书/密钥对具有不同的序列号(1个用于CA,2个用于服务器,3个用于客户端)。

  • 由服务器自动创建的文件由运行服务器的帐户拥有。 使用 mysql_ssl_rsa_setup 创建的文件 由调用该程序的用户拥有。 chown() 如果程序被调用, 则可以在支持 系统调用 系统 上更改 root --uid 选项 指定应该拥有文件的用户。

  • 在Unix和类Unix系统上,证书文件(即世界可读)的文件访问模式为644,密钥文件的文件访问模式为600(即只能由运行服务器的帐户访问)。

要查看SSL证书的内容(例如,要检查其有效的日期范围),请 直接 调用 openssl

openssl x509 -text -in ca.pem
openssl x509 -text -in server-cert.pem
openssl x509 -text -in client-cert.pem

也可以使用以下SQL语句检查SSL证书过期信息:

MySQL的> SHOW STATUS LIKE 'Ssl_server_not%';
+ ----------------------- + ------------------------- -  +
| Variable_name | 价值|
+ ----------------------- + ------------------------- -  +
| Ssl_server_not_after | 4月28日14:16:39 2027 GMT |
| Ssl_server_not_before | 2017年5月1日14:16:39 GMT |
+ ----------------------- + ------------------------- -  +

6.3.3.2使用openssl创建SSL证书和密钥

本节介绍如何使用 openssl 命令设置供MySQL服务器和客户端使用的SSL证书和密钥文件。 第一个示例显示了一个简化的过程,例如您可以从命令行使用。 第二个显示包含更多详细信息的脚本。 前两个示例旨在用于Unix,并且都使用 openssl 命令,它是OpenSSL的一部分。 第三个示例描述了如何在Windows上设置SSL文件。

注意

生成SSL所需文件比使用此处描述的过程更容易:让服务器自动生成它们或使用 mysql_ssl_rsa_setup 程序。 请参见 第6.3.3.1节“使用MySQL创建SSL和RSA证书和密钥”

重要

无论您使用哪种方法生成证书和密钥文件,用于服务器和客户端证书/密钥的公用名称值都必须与用于CA证书的公用名称值不同。 否则,证书和密钥文件将不适用于使用OpenSSL编译的服务器。 这种情况下的典型错误是:

ERROR 2026(HY000):SSL连接错误:
错误:00000001:LIB(0):函数(0):原因(1)
示例1:在Unix上从命令行创建SSL文件

以下示例显示了一组用于创建MySQL服务器和客户端证书以及密钥文件的命令。 您需要通过 openssl 命令 响应多个提示 要生成测试文件,可以按Enter键以显示所有提示。 要生成供生产使用的文件,您应该提供非空的响应。

#创建干净的环境
rm -rf newcerts
mkdir newcerts && cd newcerts

#创建CA证书
openssl genrsa 2048> ca-key.pem
openssl req -new -x509 -nodes -days 3600 \
        -key ca-key.pem -out ca.pem

#创建服务器证书,删除密码并签名
#server-cert.pem = public key,server-key.pem =私钥
openssl req -newkey rsa:2048 -days 3600 \
        -nodes -keyout server-key.pem -out server-req.pem
openssl rsa -in server-key.pem -out server-key.pem
openssl x509 -req -in server-req.pem -days 3600 \
        -CA ca.pem -CAkey ca-key.pem -set_serial 01 -out server-cert.pem

#创建客户端证书,删除密码并签名
#client-cert.pem = public key,client-key.pem = private key
openssl req -newkey rsa:2048 -days 3600 \
        -nodes -keyout client-key.pem -out client-req.pem
openssl rsa -in client-key.pem -out client-key.pem
openssl x509 -req -in client-req.pem -days 3600 \
        -CA ca.pem -CAkey ca-key.pem -set_serial 01 -out client-cert.pem

生成证书后,验证它们:

openssl verify -CAfile ca.pem server-cert.pem client-cert.pem

您应该看到这样的回复:

server-cert.pem:好的
client-cert.pem:好的

要查看证书的内容(例如,要检查证书有效的日期范围),请 像这样 调用 openssl

openssl x509 -text -in ca.pem
openssl x509 -text -in server-cert.pem
openssl x509 -text -in client-cert.pem

现在您有一组可以按如下方式使用的文件:

  • ca.pem :将此作为 --ssl-ca 服务器和客户端 的参数 (如果使用CA证书,则双方的证书必须相同。)

  • server-cert.pem server-key.pem :使用这些作为 服务器端 --ssl-cert --ssl-key 服务器端 的参数

  • client-cert.pem client-key.pem :使用这些作为 客户端 --ssl-cert --ssl-key 客户端 的参数

有关其他使用说明,请参见 第6.3.1节“配置MySQL以使用加密连接”

示例2:在Unix上使用脚本创建SSL文件

下面是一个示例脚本,演示如何为MySQL设置SSL证书和密钥文件。 执行脚本后,使用 第6.3.1节“配置MySQL使用加密连接”中 所述的SSL连接文件

DIR =`pwd` / OpenSSL的
PRIV = $ DIR /私有

mkdir $ DIR $ PRIV $ DIR / newcerts
cp /usr/share/ssl/openssl.cnf $ DIR
替换./demoCA $ DIR  -  $ DIR / openssl.cnf

#创建必要的文件:$ database,$ serial和$ new_certs_dir
#directory(可选)

触摸$ DIR / index.txt
echo“01”> $ DIR / serial

#证书颁发机构(CA)的生成

openssl req -new -x509 -keyout $ PRIV / cakey.pem -out $ DIR / ca.pem \
    -days 3600 -config $ DIR / openssl.cnf

#示例输出:
#使用/home/monty/openssl/openssl.cnf中的配置
#生成1024位RSA私钥
#................ ++++++
#......... ++++++
#将新私钥写入'/home/monty/openssl/private/cakey.pem'
#输入PEM密码短语:
#验证密码 - 输入PEM密码短语:
#-----
#您将被要求输入将要提供的信息
#并入您的证书申请。
#您将要进入的是所谓的专有名称
#或DN。
#有很多字段,但你可以留空
#对于某些字段,将有一个默认值,
#如果输入“。”,该字段将留空。
#-----
#国名(2个字母代码)[AU]:FI
#州或省名(全名)[Some-State]:
#地点名称(例如,城市)[]:
#组织名称(例如,公司)[Internet Widgits Pty Ltd]:MySQL AB
#组织单位名称(例如,部分)[]:
#Common Name(例如,你的名字)[]:MySQL admin
# 电子邮件地址 []:

#创建服务器请求和密钥
openssl req -new -keyout $ DIR / server-key.pem -out \
    $ DIR / server-req.pem -days 3600 -config $ DIR / openssl.cnf

#示例输出:
#使用/home/monty/openssl/openssl.cnf中的配置
#生成1024位RSA私钥
#.. ++++++
#.......... ++++++
#将新私钥写入'/home/monty/openssl/server-key.pem'
#输入PEM密码短语:
#验证密码 - 输入PEM密码短语:
#-----
#您将被要求输入将要提供的信息
#并入您的证书申请。
#您将要进入的是所谓的专有名称
#或DN。
#有很多字段,但你可以留空
#对于某些字段,将有一个默认值,
#如果输入“。”,该字段将留空。
#-----
#国名(2个字母代码)[AU]:FI
#州或省名(全名)[Some-State]:
#地点名称(例如,城市)[]:
#组织名称(例如,公司)[Internet Widgits Pty Ltd]:MySQL AB
#组织单位名称(例如,部分)[]:
#Common Name(例如,你的名字)[]:MySQL服务器
# 电子邮件地址 []:
#请输入以下'额外'属性
#与您的证书请求一起发送
#挑战密码[]:
#可选的公司名称[]:

#从密钥中删除密码
openssl rsa -in $ DIR / server-key.pem -out $ DIR / server-key.pem

#签署服务器证书
openssl ca -cert $ DIR / ca.pem -policy policy_anything \
    -out $ DIR / server-cert.pem -config $ DIR / openssl.cnf \
    -infiles $ DIR / server-req.pem

#示例输出:
#使用/home/monty/openssl/openssl.cnf中的配置
#输入PEM密码短语:
#检查请求是否与签名匹配
#签名确定
#主题专有名称如下
#countryName:PRINTABLE:'FI'
#organizationName:PRINTABLE:'MySQL AB'
#commonName:PRINTABLE:'MySQL admin'
#证书将于格林尼治标准时间9月13日14:22:46之前获得认证
#(365天)
#签署证书?[Y / N]:Y
#1中有1个证书请求已通过认证,提交?[Y / N  - ] Y
#用1个新条目写出数据库
#Data Base已更新

#创建客户端请求和密钥
openssl req -new -keyout $ DIR / client-key.pem -out \
    $ DIR / client-req.pem -days 3600 -config $ DIR / openssl.cnf

#示例输出:
#使用/home/monty/openssl/openssl.cnf中的配置
#生成1024位RSA私钥
#..................................... ++++++
#............................................. +++ ++
#将新私钥写入'/home/monty/openssl/client-key.pem'
#输入PEM密码短语:
#验证密码 - 输入PEM密码短语:
#-----
#您将被要求输入将要提供的信息
#并入您的证书申请。
#您将要进入的是所谓的专有名称
#或DN。
#有很多字段,但你可以留空
#对于某些字段,将有一个默认值,
#如果输入“。”,该字段将留空。
#-----
#国名(2个字母代码)[AU]:FI
#州或省名(全名)[Some-State]:
#地点名称(例如,城市)[]:
#组织名称(例如,公司)[Internet Widgits Pty Ltd]:MySQL AB
#组织单位名称(例如,部分)[]:
#Common Name(例如,你的名字)[]:MySQL用户
# 电子邮件地址 []:
#请输入以下'额外'属性
#与您的证书请求一起发送
#挑战密码[]:
#可选的公司名称[]:

#从密钥中删除密码
openssl rsa -in $ DIR / client-key.pem -out $ DIR / client-key.pem

#签署客户证书

openssl ca -cert $ DIR / ca.pem -policy policy_anything \
    -out $ DIR / client-cert.pem -config $ DIR / openssl.cnf \
    -infiles $ DIR / client-req.pem

#示例输出:
#使用/home/monty/openssl/openssl.cnf中的配置
#输入PEM密码短语:
#检查请求是否与签名匹配
#签名确定
#主题专有名称如下
#countryName:PRINTABLE:'FI'
#organizationName:PRINTABLE:'MySQL AB'
#commonName:PRINTABLE:'MySQL用户'
#证书将于格林尼治标准时间9月13日16:45:17之前通过认证
#(365天)
#签署证书?[Y / N]:Y
#1中有1个证书请求已通过认证,提交?[Y / N  - ] Y
#用1个新条目写出数据库
#Data Base已更新

#创建一个可用于测试证书的my.cnf文件

猫<< EOF> $ DIR / my.cnf
[客户]
SSL-CA = $ DIR / ca.pem
SSL证书= $ DIR /客户cert.pem
SSL密钥= $ DIR /客户key.pem
的[mysqld]
SSL-CA = $ DIR / ca.pem
SSL证书= $ DIR /服务器cert.pem
SSL密钥= $ DIR /服务器key.pem
EOF
示例3:在Windows上创建SSL文件

如果您的系统上未安装OpenSSL for Windows,请下载它。 可在此处查看可用包的概述:

http://www.slproweb.com/products/Win32OpenSSL.html

选择Win32 OpenSSL Light或Win64 OpenSSL Light程序包,具体取决于您的体系结构(32位或64位)。 默认安装位置为 C:\OpenSSL-Win32 C:\OpenSSL-Win64 ,具体取决于您下载的软件包。 以下说明假定默认位置为 C:\OpenSSL-Win32 如果您使用的是64位软件包,请根据需要进行修改。

如果在安装程序指示期间出现消息 '...critical component is missing: Microsoft Visual C++ 2008 Redistributables' ,请取消设置并下载以下软件包之一,这取决于您的体系结构(32位或64位):

安装附加软件包后,重新启动OpenSSL安装过程。

在安装过程中,保留默认值 C:\OpenSSL-Win32 作为安装路径,并保留 'Copy OpenSSL DLL files to the Windows system directory' 选中 的默认选项

安装完成后,添加 C:\OpenSSL-Win32\bin 到服务器的Windows系统路径变量中(根据您的Windows版本,以下路径设置说明可能略有不同):

  1. 在Windows桌面上,右键单击“ 我的电脑” 图标,然后选择“ 属性”

  2. 从出现的“ 系统属性” 菜单中 选择“ 高级” 选项卡 ,然后单击“ 环境变量” 按钮。

  3. 在“ 系统变量”下 ,选择“ 路径” ,然后单击“ 编辑” 按钮。 应出现 编辑系统变量” 对话框。

  4. 添加 ';C:\OpenSSL-Win32\bin' 到最后(注意分号)。

  5. 按OK 3次。

  6. 通过打开新的命令控制台(“ 开始”>“运行”>“cmd.exe” )并验证OpenSSL是否可用,检查OpenSSL是否 已正确集成到Path变量中

    Microsoft Windows [版本...]
    版权所有(c)2006 Microsoft Corporation。版权所有。
    
    C:\ Windows \ System32下>cd \
    
    C:\> openssl
    OpenSSL> exit<<<如果看到OpenSSL提示,则安装成功。
    
    C:\>
    

安装OpenSSL后,使用类似于示例1(本节前面所示)的说明,并进行以下更改:

  • 更改以下Unix命令:

    #创建干净的环境
    rm -rf newcerts
    mkdir newcerts && cd newcerts
    

    在Windows上,请改用以下命令:

    #创建干净的环境
    md c:\ newcerts
    cd c:\ newcerts
    
  • 当一个 '\' 字符显示在命令行的末尾时, '\' 必须删除 字符并在一行中输入所有命令行。

生成证书和密钥文件后,要将它们用于SSL连接,请参见 第6.3.1节“配置MySQL以使用加密连接”

6.3.3.3使用openssl创建RSA密钥

本节介绍如何使用 openssl 命令设置RSA密钥文件,这些文件使MySQL能够通过未加密的连接支持通过 sha256_password caching_sha2_password 插件 验证的帐户的安全密码交换

注意

生成RSA所需文件比使用此处描述的过程更容易:让服务器自动生成它们或使用 mysql_ssl_rsa_setup 程序。 请参见 第6.3.3.1节“使用MySQL创建SSL和RSA证书和密钥”

要创建RSA私钥和公钥对文件,请在登录用于运行MySQL服务器的系统帐户时运行这些命令,以便该文件归该帐户所有:

openssl genrsa -out private_key.pem 2048
openssl rsa -in private_key.pem -poutout -out public_key.pem

这些命令创建2,048位密钥。 要创建更强的键,请使用更大的值。

然后设置密钥文件的访问模式。 私钥只能由服务器读取,而公钥可以自由分发给客户端用户:

chmod 400 private_key.pem
chmod 444 public_key.pem

6.3.4 SSL库相关功能

可以使用OpenSSL或wolfSSL编译MySQL,这两者都支持基于OpenSSL API的加密连接:

  • MySQL Enterprise Edition二进制发行版使用OpenSSL编译。 在MySQL Enterprise Edition中使用wolfSSL是不可能的。

  • MySQL Community Edition二进制发行版使用OpenSSL编译。

  • 可以使用OpenSSL或wolfSSL编译MySQL Community Edition源代码分发(请参见 第6.3.5节“使用支持加密连接构建MySQL” )。

OpenSSL和wolfSSL提供相同的基本功能,但使用OpenSSL编译的MySQL发行版具有其他功能:

只有在使用OpenSSL编译MySQL时,才会出现某些与OpenSSL相关的系统和状态变量:

要确定是否使用OpenSSL编译服务器,请测试是否存在任何这些变量。 例如,如果使用OpenSSL,则此语句返回一行;如果使用wolfSSL,则返回空结果:

显示状态如'Rsa_public_key';

6.3.5构建支持加密连接的MySQL

要在MySQL服务器和客户端程序之间使用加密连接,您的系统必须支持OpenSSL或wolfSSL:

  • MySQL Enterprise Edition二进制发行版使用OpenSSL编译。 在MySQL Enterprise Edition中使用wolfSSL是不可能的。

  • MySQL Community Edition二进制发行版使用OpenSSL编译。

  • 可以使用OpenSSL或wolfSSL编译MySQL Community Edition源代码分发。

如果从源代码分发编译MySQL, CMake会将 分发配置为默认使用OpenSSL。

要使用OpenSSL进行编译,请使用以下过程:

  1. 确保系统上已安装OpenSSL 1.0.1或更高版本。 如果安装的OpenSSL版本低于1.0.1,则 CMake 会在MySQL配置时生成错误。 如果有必要获得OpenSSL,请访问 http://www.openssl.org

  2. CMake的 选项确定为编译MySQL使用的SSL库(参见 第2.9.4“MySQL的源代码,配置选项” )。 默认值为 ,使用OpenSSL。 要明确这一点,请在 CMake 命令行 上指定该选项 例如: WITH_SSL -DWITH_SSL=system

    cmake。-DWITH_SSL =系统
    

    该命令配置分发以使用已安装的OpenSSL库。 或者,要显式指定OpenSSL安装的路径名,请使用以下语法。 如果您安装了多个版本的OpenSSL,这可能很有用,以防止 CMake 选择错误的版本:

    cmake。-DWITH_SSL =path_name
    
  3. 编译并安装发行版。

要使用wolfSSL进行编译,请下载wolfSSL发行版并应用一个小补丁。 有关说明,请参阅该 extra/README-wolfssl.txt 文件。

要检查 mysqld 服务器 是否 支持加密连接,请检查 have_ssl 系统变量 的值

MySQL的> SHOW VARIABLES LIKE 'have_ssl';
+ --------------- + ------- +
| Variable_name | 价值|
+ --------------- + ------- +
| have_ssl | 是的|
+ --------------- + ------- +

如果值为 YES ,则服务器支持加密连接。 如果值为 DISABLED ,则服务器能够支持加密连接,但未使用适当的 选项 启动 以启用加密连接; 请参见 第6.3.1节“配置MySQL以使用加密连接” --ssl-xxx

要确定服务器是使用OpenSSL还是使用wolfSSL编译,请检查是否存在仅适用于OpenSSL的系统或状态变量。 请参见 第6.3.4节“SSL库相关功能”

6.3.6加密连接协议和密码

要确定加密连接使用哪种加密协议和密码,请使用以下语句检查 Ssl_version Ssl_cipher 状态变量的值:

MySQL的> SHOW SESSION STATUS LIKE 'Ssl_version';
+ --------------- + ------- +
| Variable_name | 价值|
+ --------------- + ------- +
| Ssl_version | TLSv1 |
+ --------------- + ------- +
MySQL的> SHOW SESSION STATUS LIKE 'Ssl_cipher';
+ --------------- + --------------------------- +
| Variable_name | 价值|
+ --------------- + --------------------------- +
| Ssl_cipher | DHE-RSA-AES128-GCM-SHA256 |
+ --------------- + --------------------------- +

如果连接未加密,则两个变量都具有空值。

MySQL支持使用TLSv1,TLSv1.1,TLSv1.2和TLSv1.3协议的加密连接。

注意

从MySQL 8.0.16开始支持TLSv1.3协议,但需要使用OpenSSL 1.1.1或更高版本编译MySQL。 如果SSL库不支持TLSv1.3,则以下讨论中的MySQL和TLSv1.3相关部分也不适用。

目前,Group Replication不支持TLSv1.3。

tls_version 系统变量 的值 确定服务器允许加密连接的协议。 tls_version 值适用于使用常规主/从复制的客户端和从服务器的连接。 变量值是此列表中一个或多个逗号分隔的协议名称的列表(不区分大小写):TLSv1,TLSv1.1,TLSv1.2和(如果可用)TLSV1.3。 默认情况下,此变量列出用于编译MySQL的SSL库支持的所有协议。 要确定 tls_version 运行时 的值 ,请使用以下语句:

MySQL的> SHOW GLOBAL VARIABLES LIKE 'tls_version';
+ --------------- + ----------------------- +
| Variable_name | 价值|
+ --------------- + ----------------------- +
| tls_version | TLSv1,TLSv1.1,TLSv1.2 |
+ --------------- + ----------------------- +

要更改其值 tls_version ,请在服务器启动时设置它。 例如,要允许使用TLSv1.1或TLSv1.2协议的连接,但禁止使用安全性较低的TLSv1协议的连接,请在服务器 my.cnf 文件中 使用以下行

的[mysqld]
tls_version = TLSv1.1,TLSv1.2工作

为了更加严格,只允许TLSv1.2连接,设置 tls_version 如下:

的[mysqld]
tls_version = TLSv1.2工作

从MySQL 8.0.16开始, tls_version 也可以在运行时更改。 请参阅 加密连接的服务器端运行时配置

对于客户端程序,该 --tls-version 选项指定客户端允许与服务器连接的TLS协议。 选项值的格式与 tls_version 系统变量 的格式相同

对于常规复制,该 语句 MASTER_TLS_VERSION 选项 CHANGE MASTER TO 指定从服务器允许与主服务器连接的TLS协议。 选项值的格式与 tls_version 系统变量 的格式相同 请参见 第17.3.9节“设置复制以使用加密连接”

可以指定的协议 MASTER_TLS_VERSION 仅依赖于SSL库。 此选项独立 tls_version 于从服务器上配置 ,不受其影响 例如,可以将充当复制从站的服务器配置为 tls_version 设置为TLSv1.3,以仅允许使用TLSv1.3的传入连接,但也使用 MASTER_TLS_VERSION set to TLSv1.2 配置 为仅作为从站连接到允许的主站TLSv1.2工作。

默认情况下,MySQL会尝试使用可用的最高TLS协议版本,具体取决于用于编译服务器和客户端的SSL库,使用的密钥大小,以及服务器或客户端是否限制使用某些协议(例如,的意思是 tls_version :) --tls-version

  • 如果TLSv1.3可用,则尽可能使用它。 如果没有,MySQL继续通过可用协议列表,如果可能的话使用TLSv1.2,依此类推。

  • TLSv1.2不适用于密钥大小为512位或更小的所有密码。 要将此协议与此类密钥一起使用,请使用 --ssl-cipher 以明确指定密码名称:

    AES128-SHA
    AES128-SHA256
    AES256-SHA
    AES256-SHA256
    CAMELLIA128-SHA
    CAMELLIA256-SHA
    DES-CBC3-SHA
    DHE-RSA-AES256-SHA
    RC4,MD5
    RC4-SHA
    SEED-SHA
    
  • 为了更好的安全性,请使用RSA密钥大小至少为2048位的证书。

如果服务器和客户端协议功能没有共同的协议,则服务器终止连接请求。 例子:

  • 如果配置了服务器,则 tls_version=TLSv1.1,TLSv1.2 调用的客户端的连接尝试失败 --tls-version=TLSv1 ,对于不支持该 --tls-version 选项的 旧客户端, 并且仅隐式支持TLSv1。

  • 同样,对于配置了的复制从站的连接尝试失败 MASTER_TLS_VERSION = 'TLSv1' ,对于不支持该 MASTER_TLS_VERSION 选项且仅隐式支持TLSv1的 旧从站 ,连接尝试失败

OpenSSL 1.1.1及更高版本支持以下密码套件,前三个密码套件默认启用:

TLS_AES_128_GCM_SHA256
TLS_AES_256_GCM_SHA384
TLS_CHACHA20_POLY1305_SHA256
TLS_AES_128_CCM_SHA256
TLS_AES_128_CCM_8_SHA256 

要明确配置允许的TLSv1.3密码套件:

在每种情况下,配置值是一个或多个冒号分隔的密码组名称的列表。

MySQL允许指定要支持的协议列表。 此列表直接传递到底层SSL库,最终由该库提供从提供的列表中实际启用的协议。 SSL_CTX_new() 有关SSL库如何处理此问题的信息, 请参阅MySQL源代码和OpenSSL 文档。

要确定给定服务器支持的密码,请使用以下语句检查 Ssl_cipher_list 状态变量 的值

显示会话状态,如'Ssl_cipher_list';

Ssl_cipher_list 状态变量列出了可能的SSL密码(空非SSL连接)。 如果MySQL支持TLSv1.3,则该值包括可能的TLSv1.3密码套件。

MySQL传递给SSL库的密码顺序非常重要。 列表中首先提到了更安全的密码,并选择了提供的证书支持的第一个密码。

MySQL将此密码列表传递给SSL库:

ECDHE-ECDSA-AES128-GCM-SHA256
ECDHE-ECDSA-AES256-GCM-SHA384
ECDHE-RSA-AES128-GCM-SHA256
ECDHE-RSA-AES256-GCM-SHA384
ECDHE-ECDSA-AES128-SHA256
ECDHE-RSA-AES128-SHA256
ECDHE-ECDSA-AES256-SHA384
ECDHE-RSA-AES256-SHA384
DHE-RSA-AES128-GCM-SHA256
DHE-DSS-AES128-GCM-SHA256
DHE-RSA-AES128-SHA256
DHE-DSS-AES128-SHA256
DHE-DSS-AES256-GCM-SHA384
DHE-RSA-AES256-SHA256
DHE-DSS-AES256-SHA256
ECDHE-RSA-AES128-SHA
ECDHE-ECDSA-AES128-SHA
ECDHE-RSA-AES256-SHA
ECDHE-ECDSA-AES256-SHA
DHE-DSS-AES128-SHA
DHE-RSA-AES128-SHA
TLS_DHE_DSS_WITH_AES_256_CBC_SHA
DHE-RSA-AES256-SHA
AES128-GCM-SHA256
DH-DSS-AES128-GCM-SHA256
ECDH-ECDSA-AES128-GCM-SHA256
AES256-GCM-SHA384
DH-DSS-AES256-GCM-SHA384
ECDH-ECDSA-AES256-GCM-SHA384
AES128-SHA256
DH-DSS-AES128-SHA256
ECDH-ECDSA-AES128-SHA256
AES256-SHA256
DH-DSS-AES256-SHA256
ECDH-ECDSA-AES256-SHA384
AES128-SHA
DH-DSS-AES128-SHA
ECDH-ECDSA-AES128-SHA
AES256-SHA
DH-DSS-AES256-SHA
ECDH-ECDSA-AES256-SHA
DHE-RSA-AES256-GCM-SHA384
DH-RSA-AES128-GCM-SHA256
ECDH-RSA-AES128-GCM-SHA256
DH-RSA-AES256-GCM-SHA384
ECDH-RSA-AES256-GCM-SHA384
DH-RSA-AES128-SHA256
ECDH-RSA-AES128-SHA256
DH-RSA-AES256-SHA256
ECDH-RSA-AES256-SHA384
ECDHE-RSA-AES128-SHA
ECDHE-ECDSA-AES128-SHA
ECDHE-RSA-AES256-SHA
ECDHE-ECDSA-AES256-SHA
DHE-DSS-AES128-SHA
DHE-RSA-AES128-SHA
TLS_DHE_DSS_WITH_AES_256_CBC_SHA
DHE-RSA-AES256-SHA
AES128-SHA
DH-DSS-AES128-SHA
ECDH-ECDSA-AES128-SHA
AES256-SHA
DH-DSS-AES256-SHA
ECDH-ECDSA-AES256-SHA
DH-RSA-AES128-SHA
ECDH-RSA-AES128-SHA
DH-RSA-AES256-SHA
ECDH-RSA-AES256-SHA
DES-CBC3-SHA

这些密码限制到位:

  • 以下密码永久受限:

    !DHE-DSS-DES-CBC3-SHA
    !DHE-RSA-DES-CBC3-SHA
    !ECDH-RSA-DES-CBC3-SHA
    !ECDH-ECDSA-DES-CBC3-SHA
    !ECDHE-RSA-DES-CBC3-SHA
    !ECDHE-ECDSA-DES-CBC3-SHA
    
  • 以下类别的密码是永久限制的:

    !A零位
    !ENULL
    !出口
    !低
    !MD5
    !DES
    !RC2
    !RC4
    !PSK
    !的SSLv3
    

如果使用使用任何前述受限密码或密码类别的兼容证书启动服务器,则服务器启动时禁用加密连接。

6.3.7使用SSH从Windows远程连接到MySQL

本节介绍如何使用SSH获取与远程MySQL服务器的加密连接。 该信息由David Carlson提供

  1. 在Windows计算机上安装SSH客户端。 有关SSH客户端的比较,请参阅 http://en.wikipedia.org/wiki/Comparison_of_SSH_clients

  2. 启动Windows SSH客户端。 设置 设置 为登录您的服务器。 值可能与您的MySQL帐户的用户名不同。 Host_Name = yourmysqlserver_URL_or_IP userid=your_userid userid

  3. 设置端口转发。 要么是遥控前进(设置 local_port: 3306 )或本地转发(设置 )。 remote_host: yourmysqlservername_or_ip remote_port: 3306 port: 3306 host: localhost remote port: 3306

  4. 保存所有内容,否则您将不得不在下次重做它。

  5. 使用刚刚创建的SSH会话登录服务器。

  6. 在Windows计算机上,启动一些ODBC应用程序(例如Access)。

  7. 在Windows中创建一个新文件,并使用ODBC驱动程序以与通常相同的方式链接到MySQL,除了输入 localhost MySQL主机服务器,不是 yourmysqlservername

此时,您应该与MySQL建立ODBC连接,使用SSH加密。

6.4安全组件和插件

MySQL包含几个实现安全功能的组件和插件:

  • 用于验证客户端连接到MySQL服务器的尝试的插件。 插件可用于多种身份验证协议。 有关身份验证过程的一般讨论,请参见 第6.2.17节“可插入身份验证” 有关特定身份验证插件的特性,请参见 第6.4.1节“身份验证插件”

  • 密码验证组件,用于实施密码强度策略和评估潜在密码的强度。 请参见 第6.4.3节“密码验证组件”

  • 密钥环插件,为敏感信息提供安全存储。 请参见 第6.4.4节“MySQL密钥环”

  • (仅限MySQL企业版)使用服务器插件实现的MySQL Enterprise Audit使用开放的MySQL Audit API来启用基于策略的标准监视以及在特定MySQL服务器上执行的连接和查询活动的日志记录。 MySQL Enterprise Audit旨在满足Oracle审计规范,为受内部和外部监管准则管理的应用程序提供开箱即用,易于使用的审计和合规性解决方案。 请参见 第6.4.5节“MySQL Enterprise Audit”

  • 用户定义的函数使应用程序可以将自己的消息事件添加到审计日志中。 请参见 第6.4.6节“审计消息组件”

  • (仅限MySQL企业版)MySQL企业防火墙,一种应用程序级防火墙,允许数据库管理员根据与已接受语句模式的白名单进行匹配来允许或拒绝SQL语句执行。 这有助于强化MySQL服务器免受SQL注入等攻击或尝试通过在合法查询工作负载特征之外使用应用程序来利用应用程序。 请参见 第6.4.7节“MySQL Enterprise Firewall”

  • (仅限MySQL企业版)MySQL企业数据屏蔽和去标识,作为包含插件和一组用户定义函数的插件库实现。 数据屏蔽通过用替换替换实际值来隐藏敏感信息。 MySQL企业数据屏蔽和去标识功能可以使用多种方法屏蔽现有数据,例如模糊处理(删除识别特征),格式化随机数据的生成以及数据替换或替换。 请参见 第6.4.8节“MySQL企业数据屏蔽和取消标识”

6.4.1认证插件

以下部分描述了MySQL中可用的可插入身份验证方法以及实现这些方法的插件。 有关身份验证过程的一般讨论,请参见 第6.2.17节“可插入身份验证”

默认插件由 default_authentication_plugin 系统变量 的值指示

6.4.1.1本地可插入认证

MySQL包含一个 mysql_native_password 实现本机身份验证 插件; 也就是说,在引入可插入身份验证之前,基于密码哈希方法的身份验证使用。

下表显示了服务器端和客户端上的插件名称。

表6.13本机密码验证的插件和库名称

插件或文件 插件或文件名
服务器端插件 mysql_native_password
客户端插件 mysql_native_password
库文件 无(插件内置)

以下部分提供特定于本机可插入身份验证的安装和使用信息:

有关MySQL中可插入身份验证的一般信息,请参见 第6.2.17节“可插入身份验证”

安装本机可插入身份验证

mysql_native_password 插件存在于服务器和客户端表单中:

  • 服务器端插件内置于服务器中,无需显式加载,也无法通过卸载来禁用。

  • 客户端插件内置于 libmysqlclient 客户端库中,可用于任何链接的程序 libmysqlclient

使用本机可插入身份验证

MySQL客户端程序 mysql_native_password 默认 使用 --default-auth 选项可用作关于程序可以使用哪个客户端插件的提示:

外壳> mysql --default-auth=mysql_native_password ...

6.4.1.2 SHA-256可插拔认证

MySQL提供了两个身份验证插件,可以为用户帐户密码实现SHA-256哈希:

  • sha256_password :实现基本的SHA-256身份验证。

  • caching_sha2_password :实现SHA-256身份验证(如 sha256_password ),但在服务器端使用缓存以获得更好的性能,并具有更广泛的适用性的附加功能。

本节介绍原始非缓存SHA-2身份验证插件。 有关缓存插件的信息,请参见 第6.4.1.3节“缓存SHA-2可插入身份验证”

重要

在MySQL 8.0中, caching_sha2_password 是默认的身份验证插件而不是 mysql_native_password 有关此更改对服务器操作的影响以及服务器与客户端和连接器的兼容性的信息,请参阅 caching_sha2_password作为首选身份验证插件

因为它 caching_sha2_password 是MySQL 8.0中的默认身份验证插件并提供了 sha256_password 身份验证插件 功能的超集 sha256_password 所以不推荐使用,并且将在未来的MySQL版本中删除。 sha256_password 应该迁移使用 身份验证的MySQL帐户 以使用 caching_sha2_password

重要

要使用通过 sha256_password 插件进行 身份验证的帐户连接到服务器 ,您必须使用TLS连接或支持使用RSA密钥对进行密码交换的未加密连接,如本节后面所述。 无论哪种方式, sha256_password 插件都使用MySQL的加密功能。 请参见 第6.3节“使用加密连接”

注意

在名称中 sha256_password sha256 指的是插件用于加密的256位摘要长度。 在名称中 caching_sha2_password sha2 更一般地指SHA-2类加密算法,其中256位加密是一个实例。 后一个名称选择为将来扩展可能的摘要长度留下了空间,而无需更改插件名称。

下表显示了服务器端和客户端上的插件名称。

表6.14 SHA-256身份验证的插件和库名称

插件或文件 插件或文件名
服务器端插件 sha256_password
客户端插件 sha256_password
库文件 无(插件内置)

以下部分提供特定于SHA-256可插入身份验证的安装和使用信息:

有关MySQL中可插入身份验证的一般信息,请参见 第6.2.17节“可插入身份验证”

安装SHA-256可插拔认证

sha256_password 插件存在于服务器和客户端表单中:

  • 服务器端插件内置于服务器中,无需显式加载,也无法通过卸载来禁用。

  • 客户端插件内置于 libmysqlclient 客户端库中,可用于任何链接的程序 libmysqlclient

使用SHA-256可插拔认证

要设置使用 sha256_password 插件进行SHA-256密码哈希 的帐户,请使用 以下语句,其中 password 包含所需的帐户密码:

创建用户'sha256user'@'localhost'
用sha256_password BY' password' 识别;

服务器将 sha256_password 插件 分配给 帐户并使用它来使用SHA-256加密密码,并将这些值存储 系统表 plugin authentication_string 列中 mysql.user

前面的说明不假定这 sha256_password 是默认的身份验证插件。 如果 sha256_password 是默认的身份验证插件, CREATE USER 则可以使用 更简单的 语法。

要在默认身份验证插件设置为的情况下启动服务器 sha256_password ,请将这些行放在服务器选项文件中:

的[mysqld]
default_authentication_plugin = sha256_password

这会导致 sha256_password 默认情况下为新帐户使用插件。 因此,可以创建帐户并设置其密码,而无需明确命名插件:

创建用户'sha256user'@'localhost'IDENTIFIED BY' password';

设置的另一个结果 default_authentication_plugin sha256_password 的是,使用一些其他的插件创建帐户,您必须指定插件明确。 例如,要使用该 mysql_native_password 插件,请使用以下语句:

创建用户'nativeuser'@'localhost'
使用mysql_native_password BY' password' 识别;

sha256_password 通过安全传输支持连接。 sha256_password 如果满足以下条件,还支持使用RSA通过未加密的连接进行加密密码交换:

  • MySQL是使用OpenSSL编译的。 可以使用OpenSSL或yaSSL编译MySQL(请参见 第6.3.4节“SSL库依赖功能” ),并 sha256_password 使用使用任一软件包编译的分发版,但RSA支持需要OpenSSL。

  • 您要连接的MySQL服务器配置为支持RSA(使用本节后面给出的RSA配置过程)。

RSA支持具有以下特征:

对于使用该 sha256_password 插件的 客户端 ,密码在连接到服务器时绝不会以明文形式公开。 密码传输的方式取决于是使用安全连接还是RSA加密:

  • 如果连接是安全的,则不需要RSA密钥对,也不使用。 这适用于使用TLS的加密连接。 密码以明文形式发送,但由于连接安全,因此无法窥探密码。

  • 如果连接不安全,并且RSA密钥对可用,则连接保持未加密状态。 这适用于没有TLS的未加密连接。 RSA仅用于客户端和服务器之间的密码交换,以防止密码窥探。 当服务器收到加密密码时,它会对其进行解密。 加密中使用加扰来防止重复攻击。

  • 如果未使用安全连接且RSA加密不可用,则连接尝试将失败,因为密码无法在未显示为明文的情况下发送。

如前所述,只有在使用OpenSSL编译MySQL时,RSA密码加密才可用。 使用wolfSSL编译的MySQL发行版的含义是,要使用SHA-256密码,客户端 必须 使用加密连接来访问服务器。 请参见 第6.3.1节“配置MySQL以使用加密连接”

注意

要使用RSA密码加密 sha256_password ,必须使用OpenSSL编译客户端和服务器,而不仅仅是其中之一。

假设MySQL已使用OpenSSL编译,请使用以下过程在客户端连接过程中使用RSA密钥对进行密码交换:

  1. 使用 第6.3.3节“创建SSL和RSA证书和密钥”中 的说明创建RSA专用和公用密钥对文件

  2. 如果私钥和公钥文件都位于数据目录中,名为 private_key.pem public_key.pem (的默认值 sha256_password_private_key_path sha256_password_public_key_path 系统变量),服务器在启动时自动使用它们。

    否则,要明确命名密钥文件,请将系统变量设置为服务器选项文件中的密钥文件名。 如果文件位于服务器数据目录中,则无需指定其完整路径名:

    的[mysqld]
    sha256_password_private_key_path = myprivkey.pem
    sha256_password_public_key_path = mypubkey.pem
    

    如果密钥文件不在数据目录中,或者在系统变量值中显示其位置,请使用完整路径名:

    的[mysqld]
    sha256_password_private_key_path =的/ usr /本地/ MySQL的/ myprivkey.pem
    sha256_password_public_key_path =的/ usr /本地/ MySQL的/ mypubkey.pem
    
  3. 重新启动服务器,然后连接到它并检查 Rsa_public_key 状态变量值。 该值将与此处显示的值不同,但应该是非空的:

    MySQL的> SHOW STATUS LIKE 'Rsa_public_key'\G
    *************************** 1。排******************** *******
    Variable_name:Rsa_public_key
            价值:-----开始公钥-----
    MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDO9nRUDd + KvSZgY7cNBZMNpwX6
    MvE1PbJFXO7u18nJ9lwc99Du / E7lw6CVXw7VKrXPeHbVQUzGyUNkf45Nz / ckaaJa
    aLgJOBCIDmNVnyU54OT / 1lcs2xiyfaDMe8fCJ64ZwTnKbY2gkt1IMjUAB5Ogd5kJ
    g8aV7EtKwyhHb0c30QIDAQAB
    ----- END PUBLIC KEY -----
    

    如果值为空,则服务器发现密钥文件存在问题。 检查错误日志以获取诊断信息。

使用RSA密钥文件配置服务器后,使用该 sha256_password 插件进行 身份验证的帐户可以 选择使用这些密钥文件连接到服务器。 如前所述,此类帐户可以使用安全连接(在这种情况下不使用RSA)或使用RSA执行密码交换的未加密连接。 假设使用了未加密的连接。 例如:

shell> mysql --ssl-mode=DISABLED -u sha256user -p
输入密码:password

对于此连接尝试 sha256user ,服务器确定该 sha256_password 是适当的身份验证插件并调用它(因为那是 CREATE USER 时间 指定的插件 )。 该插件发现连接未加密,因此需要使用RSA加密传输密码。 在这种情况下,插件将RSA公钥发送给客户端,客户端使用它来加密密码并将结果返回给服务器。 该插件使用服务器端的RSA私钥来解密密码,并根据密码是否正确接受或拒绝连接。

服务器根据需要将RSA公钥发送给客户端。 但是,如果客户端具有包含服务器所需的RSA公钥的本地副本的文件,则它可以使用以下 --server-public-key-path 选项 指定该文件

shell> 
输入密码:mysql --ssl-mode=DISABLED -u sha256user -p --server-public-key-path=file_namepassword

--server-public-key-path 选项 命名的文件中的公钥值 应与 sha256_password_public_key_path 系统变量 指定的服务器端文件中的键值相同 如果密钥文件包含有效的公钥值但值不正确,则会发生访问拒绝错误。 如果密钥文件不包含有效的公钥,则客户端程序无法使用它。 在这种情况下, sha256_password 插件将公钥发送到客户端,就好像没有 --server-public-key-path 指定选项一样。

客户端用户可以通过两种方式获取RSA公钥:

  • 数据库管理员可以提供公钥文件的副本。

  • 可以通过其他方式连接到服务器的客户端用户可以使用 SHOW STATUS LIKE 'Rsa_public_key' 语句并将返回的键值保存在文件中。

6.4.1.3缓存SHA-2可插入认证

MySQL提供了两个身份验证插件,可以为用户帐户密码实现SHA-256哈希:

  • sha256_password :实现基本的SHA-256身份验证。

  • caching_sha2_password :实现SHA-256身份验证(如 sha256_password ),但在服务器端使用缓存以获得更好的性能,并具有更广泛的适用性的附加功能。

本节介绍缓存SHA-2身份验证插件。 有关原始基本(非高速缓存)插件的信息,请参见 第6.4.1.2节“SHA-256可插入认证”

重要

在MySQL 8.0中, caching_sha2_password 是默认的身份验证插件而不是 mysql_native_password 有关此更改对服务器操作的影响以及服务器与客户端和连接器的兼容性的信息,请参阅 caching_sha2_password作为首选身份验证插件

重要

要使用通过 caching_sha2_password 插件进行 身份验证的帐户连接到服务器 ,您必须使用安全连接或支持使用RSA密钥对进行密码交换的未加密连接,如本节后面所述。 无论哪种方式, caching_sha2_password 插件都使用MySQL的加密功能。 请参见 第6.3节“使用加密连接”

注意

在名称中 sha256_password sha256 指的是插件用于加密的256位摘要长度。 在名称中 caching_sha2_password sha2 更一般地指SHA-2类加密算法,其中256位加密是一个实例。 后一个名称选择为将来扩展可能的摘要长度留下了空间,而无需更改插件名称。

caching_sha2_password 以下相比, 插件具有以下优势 sha256_password

  • 在服务器端,内存缓存可以更快地重新验证之前再次连接时已连接的用户。

  • 无论与MySQL链接的SSL库如何,都可以使用基于RSA的密码交换。

  • 支持使用Unix套接字文件和共享内存协议的客户端连接。

下表显示了服务器端和客户端上的插件名称。

表6.15 SHA-2身份验证的插件和库名称

插件或文件 插件或文件名
服务器端插件 caching_sha2_password
客户端插件 caching_sha2_password
库文件 无(插件内置)

以下部分提供了特定于缓存SHA-2可插入身份验证的安装和使用信息:

有关MySQL中可插入身份验证的一般信息,请参见 第6.2.17节“可插入身份验证”

安装SHA-2可插拔认证

caching_sha2_password 插件存在于服务器和客户端表单中:

  • 服务器端插件内置于服务器中,无需显式加载,也无法通过卸载来禁用。

  • 客户端插件内置于 libmysqlclient 客户端库中,可用于任何链接的程序 libmysqlclient

服务器端插件使用 sha2_cache_cleaner 审计插件作为帮助程序来执行密码缓存管理。 sha2_cache_cleaner ,比如 caching_sha2_password ,内置,无需安装。

使用SHA-2可插拔认证

要设置使用 caching_sha2_password 插件进行SHA-256密码哈希 的帐户,请使用 以下语句,其中 password 包含所需的帐户密码:

创建用户'sha2user'@'localhost'
通过caching_sha2_password BY' password' 识别;

服务器将 caching_sha2_password 插件 分配给 帐户并使用它来使用SHA-256加密密码,并将这些值存储 系统表 plugin authentication_string 列中 mysql.user

前面的说明不假定这 caching_sha2_password 是默认的身份验证插件。 如果 caching_sha2_password 是默认的身份验证插件, CREATE USER 则可以使用 更简单的 语法。

要在默认身份验证插件设置为的情况下启动服务器 caching_sha2_password ,请将这些行放在服务器选项文件中:

的[mysqld]
default_authentication_plugin = caching_sha2_password

这会导致 caching_sha2_password 默认情况下为新帐户使用插件。 因此,可以创建帐户并设置其密码,而无需明确命名插件:

创建用户'sha2user'@'localhost'IDENTIFIED BY' password';

设置的另一个结果 default_authentication_plugin caching_sha2_password 的是,使用一些其他的插件创建帐户,您必须指定插件明确。 例如,要使用该 mysql_native_password 插件,请使用以下语句:

创建用户'nativeuser'@'localhost'
使用mysql_native_password BY' password' 识别;

caching_sha2_password 通过安全传输支持连接。 如果您遵循本节后面给出的RSA配置过程,它还支持使用RSA通过未加密的连接进行加密密码交换。 RSA支持具有以下特征:

对于使用该 caching_sha2_password 插件的 客户端 ,密码在连接到服务器时绝不会以明文形式公开。 密码传输的方式取决于是使用安全连接还是RSA加密:

  • 如果连接是安全的,则不需要RSA密钥对,也不使用。 这适用于使用TLS的加密TCP连接,以及Unix套接字文件和共享内存连接。 密码以明文形式发送,但由于连接安全,因此无法窥探密码。

  • 如果连接不安全,则使用RSA密钥对。 这适用于没有TLS和命名管道连接的未加密TCP连接。 RSA仅用于客户端和服务器之间的密码交换,以防止密码窥探。 当服务器收到加密密码时,它会对其进行解密。 加密中使用加扰来防止重复攻击。

要在客户端连接过程中使用RSA密钥对进行密码交换,请使用以下过程:

  1. 使用 第6.3.3节“创建SSL和RSA证书和密钥”中 的说明创建RSA专用和公用密钥对文件

  2. 如果私钥和公钥文件都位于数据目录中,名为 private_key.pem public_key.pem (的默认值 caching_sha2_password_private_key_path caching_sha2_password_public_key_path 系统变量),服务器在启动时自动使用它们。

    否则,要明确命名密钥文件,请将系统变量设置为服务器选项文件中的密钥文件名。 如果文件位于服务器数据目录中,则无需指定其完整路径名:

    的[mysqld]
    caching_sha2_password_private_key_path = myprivkey.pem
    caching_sha2_password_public_key_path = mypubkey.pem
    

    如果密钥文件不在数据目录中,或者在系统变量值中显示其位置,请使用完整路径名:

    的[mysqld]
    caching_sha2_password_private_key_path =的/ usr /本地/ MySQL的/ myprivkey.pem
    caching_sha2_password_public_key_path =的/ usr /本地/ MySQL的/ mypubkey.pem
    
  3. 重新启动服务器,然后连接到它并检查 Caching_sha2_password_rsa_public_key 状态变量值。 该值将与此处显示的值不同,但应该是非空的:

    MySQL的> SHOW STATUS LIKE 'Caching_sha2_password_rsa_public_key'\G
    *************************** 1。排******************** *******
    Variable_name:Caching_sha2_password_rsa_public_key
            价值:-----开始公钥-----
    MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDO9nRUDd + KvSZgY7cNBZMNpwX6
    MvE1PbJFXO7u18nJ9lwc99Du / E7lw6CVXw7VKrXPeHbVQUzGyUNkf45Nz / ckaaJa
    aLgJOBCIDmNVnyU54OT / 1lcs2xiyfaDMe8fCJ64ZwTnKbY2gkt1IMjUAB5Ogd5kJ
    g8aV7EtKwyhHb0c30QIDAQAB
    ----- END PUBLIC KEY -----
    

    如果值为空,则服务器发现密钥文件存在问题。 检查错误日志以获取诊断信息。

使用RSA密钥文件配置服务器后,使用该 caching_sha2_password 插件进行 身份验证的帐户可以 选择使用这些密钥文件连接到服务器。 如前所述,此类帐户可以使用安全连接(在这种情况下不使用RSA)或使用RSA执行密码交换的未加密连接。 假设使用了未加密的连接。 例如:

shell> mysql --ssl-mode=DISABLED -u sha2user -p
输入密码:password

对于此连接尝试 sha2user ,服务器确定该 caching_sha2_password 是适当的身份验证插件并调用它(因为那是 CREATE USER 时间 指定的插件 )。 该插件发现连接未加密,因此需要使用RSA加密传输密码。 但是,服务器不会将公钥发送到客户端,并且客户端不提供公钥,因此无法加密密码并且连接失败:

ERROR 2061(HY000):身份验证插件'caching_sha2_password'
报告错误:身份验证需要安全连接。

要从服务器请求RSA公钥,请指定 --get-server-public-key 选项:

shell> mysql --ssl-mode=DISABLED -u sha2user -p --get-server-public-key
输入密码:password

在这种情况下,服务器将RSA公钥发送给客户端,客户端使用它来加密密码并将结果返回给服务器。 该插件使用服务器端的RSA私钥来解密密码,并根据密码是否正确接受或拒绝连接。

或者,如果客户端具有包含服务器所需的RSA公钥的本地副本的文件,则它可以使用以下 --server-public-key-path 选项 指定该文件

shell> 
输入密码:mysql --ssl-mode=DISABLED -u sha2user -p --server-public-key-path=file_namepassword

在这种情况下,客户端使用公钥来加密密码并将结果返回给服务器。 该插件使用服务器端的RSA私钥来解密密码,并根据密码是否正确接受或拒绝连接。

--server-public-key-path 选项 命名的文件中的公钥值 应与 caching_sha2_password_public_key_path 系统变量 指定的服务器端文件中的键值相同 如果密钥文件包含有效的公钥值但值不正确,则会发生访问拒绝错误。 如果密钥文件不包含有效的公钥,则客户端程序无法使用它。

客户端用户可以通过两种方式获取RSA公钥:

  • 数据库管理员可以提供公钥文件的副本。

  • 可以通过其他方式连接到服务器的客户端用户可以使用 SHOW STATUS LIKE 'Caching_sha2_password_rsa_public_key' 语句并将返回的键值保存在文件中。

SHA-2可插入认证的缓存操作

在服务器端,该 caching_sha2_password 插件使用内存缓存来更快地验证之前已连接的客户端。 条目由帐户名/密码哈希对组成。 缓存的工作方式如下:

  1. 当客户端连接时, caching_sha2_password 检查客户端和密码是否与某些缓存条目匹配。 如果是,则身份验证成功。

  2. 如果没有匹配的缓存条目,则插件会尝试根据 mysql.user 系统表 中的凭据验证客户端 如果成功, caching_sha2_password 则将客户端条目添加到哈希。 否则,身份验证失败,连接被拒绝。

这样,当客户端首次连接时, mysql.user 就会 系统表进行 身份验证 当客户端随后连接时,会对缓存进行更快的身份验证。

除了添加条目之外的密码缓存操作由 sha2_cache_cleaner 审计插件 处理, 审计插件代表以下方式执行以下操作 caching_sha2_password

  • 它会清除重命名或删除的任何帐户的缓存条目,或者更改凭据或身份验证插件的任何帐户。

  • 它在 FLUSH PRIVILEGES 执行语句 时清空缓存

  • 它会在服务器关闭时清空缓存。 (这意味着缓存在服务器重新启动时不会持久。)

缓存清除操作会影响后续客户端连接的身份验证要求。 对于每个用户帐户,在执行以下任何操作之后,用户的第一个客户端连接必须使用安全连接(使用TCP使用TLS凭据,Unix套接字文件或共享内存)或基于RSA密钥对的密码交换:

FLUSH PRIVILEGES 清除整个缓存并影响使用该 caching_sha2_password 插件的 所有帐户 其他操作会清除特定的高速缓存条目,并仅影响属于该操作的帐户。

用户成功验证后,帐户将进入缓存,后续连接不需要安全连接或RSA密钥对,直到发生影响帐户的另一个缓存清除事件。 (当可以使用缓存时,服务器使用质询 - 响应机制,该机制不使用明文密码传输,也不需要安全连接。)

6.4.1.4客户端明文可插入认证

客户端身份验证插件可用,使客户端能够以明文形式向服务器发送密码,而无需散列或加密。 这个插件内置在MySQL客户端库中。

下表显示了插件名称。

表6.16明文身份验证的插件和库名称

插件或文件 插件或文件名
服务器端插件 没有,请参阅讨论
客户端插件 mysql_clear_password
库文件 无(插件内置)

许多客户端身份验证插件在客户端将其发送到服务器之前执行散列或密码加密。 这使客户端可以避免以明文形式发送密码。

无法对需要服务器接收客户端输入的密码的身份验证方案进行散列或加密。 在这种情况下,使用客户端 mysql_clear_password 插件,使客户端能够以明文形式将密码发送到服务器。 没有相应的服务器端插件。 相反, mysql_clear_password 可以在客户端使用任何需要明文密码的服务器端插件。 (例如PAM和简单LDAP身份验证插件;请参见 第6.4.1.5节“PAM可插入身份验证” 第6.4.1.7节“LDAP可插入身份验证” 。)

以下讨论提供了特定于明文可插入身份验证的使用信息。 有关MySQL中可插入身份验证的一般信息,请参见 第6.2.17节“可插入身份验证”

注意

在某些配置中,将密码作为明文发送可能是一个安全问题。 如果有可能截获密码以避免出现问题,客户端应使用保护密码的方法连接到MySQL Server。 可能性包括SSL(请参见 第6.3节“使用加密连接” ),IPsec或专用网络。

为了 mysql_clear_password 不太可能 无意中使用 插件,MySQL客户端必须明确启用它。 这可以通过以下几种方式完成:

  • 在设置 LIBMYSQL_ENABLE_CLEARTEXT_PLUGIN 环境变量,且开头的值 1 Y y 这为所有客户端连接启用了插件。

  • MySQL的 中mysqladmin mysqlcheck的 mysqldump的 mysqlshow mysqlslap 客户端程序支持 --enable-cleartext-plugin ,允许在每调用基础的插件选项。

  • mysql_options() C API函数支持 MYSQL_ENABLE_CLEARTEXT_PLUGIN 选项,使在每个连接的基础插件。 此外,任何使用 libmysqlclient 和读取选项文件的程序都可以 enable-cleartext-plugin 通过在客户端库读取的选项组中 包含 选项 来启用插件

6.4.1.5 PAM可插拔认证

注意

PAM可插入身份验证是MySQL企业版(一种商业产品)中包含的扩展。 要了解有关商业产品的更多信息,请访问 https://www.mysql.com/products/

MySQL企业版支持一种身份验证方法,使MySQL服务器能够使用PAM(可插入身份验证模块)对MySQL用户进行身份验证。 PAM使系统能够使用标准接口访问各种身份验证方法,例如传统的Unix密码或LDAP目录。

PAM可插拔身份验证提供以下功能:

  • 外部身份验证:PAM身份验证使MySQL Server能够接受来自MySQL授权表外部定义的用户的连接,并使用PAM支持的方法进行身份验证。

  • 代理用户支持:根据外部用户所属的PAM组和提供的身份验证字符串,PAM身份验证可以向MySQL返回与客户端程序传递的外部用户名不同的用户名。 这意味着该插件可以返回MySQL用户,该用户定义外部PAM认证用户应具有的权限。 例如,名为的操作系统用户 joe 可以连接并具有名为的MySQL用户的权限 developer

PAM可插拔身份验证已在Linux和macOS上进行了测试。

下表显示了插件和库文件名。 文件名后缀可能与您的系统不同。 该文件必须位于 plugin_dir 系统变量 指定的目录中 有关安装信息,请参阅 安装PAM可插入身份验证

表6.17 PAM身份验证的插件和库名称

插件或文件 插件或文件名
服务器端插件 authentication_pam
客户端插件 mysql_clear_password
库文件 authentication_pam.so

mysql_clear_password 与服务器端PAM插件通信 的客户端 明文插件内置于 libmysqlclient 客户端库中,并包含在所有发行版中,包括社区发行版。 在所有MySQL发行版中包含客户端cleartext插件,可以使任何发行版的客户端连接到加载了服务器端PAM插件的服务器。

以下部分提供了特定于PAM可插入身份验证的安装和使用信息:

有关MySQL中可插入身份验证的一般信息,请参见 第6.2.17节“可插入身份验证” 有关 mysql_clear_password 插件的 信息 ,请参见 第6.4.1.4节“客户端明文可插入认证” 有关代理用户信息,请参见 第6.2.18节“代理用户”

MySQL用户的PAM身份验证如何工作

本节概述了MySQL和PAM如何协同工作以验证MySQL用户。 有关如何设置MySQL帐户以使用特定PAM服务的示例,请参阅 使用PAM可插入身份验证

  1. 客户端程序和服务器通信,客户端向服务器发送客户端用户名(默认为操作系统用户名)和密码:

    • 客户端用户名是外部用户名。

    • 对于使用PAM服务器端身份验证插件的帐户,相应的客户端插件是 mysql_clear_password 此客户端插件不执行密码散列,结果客户端以明文形式将密码发送到服务器。

  2. 服务器根据外部用户名和客户端连接的主机找到匹配的MySQL帐户。 PAM插件使用MySQL Server传递给它的信息(例如用户名,主机名,密码和认证字符串)。 定义使用PAM进行身份验证的MySQL帐户时,身份验证字符串包含:

    • PAM服务名称,系统管理员可以使用该名称来引用特定应用程序的身份验证方法。 可以有多个与单个数据库服务器实例关联的应用程序,因此服务名称的选择留给SQL应用程序开发人员。

    • (可选)如果要使用代理,则从PAM组到MySQL用户名的映射。

  3. 该插件使用身份验证字符串中指定的PAM服务来检查用户凭据并返回 密码必须适合PAM服务使用的密码存储。 例子: 'Authentication succeeded, Username is user_name' 'Authentication failed'

    • 对于传统的Unix密码,该服务会查找存储在 /etc/shadow 文件中的 密码

    • 对于LDAP,该服务查找存储在LDAP目录中的密码。

    如果凭据检查失败,则服务器拒绝连接。

  4. 否则,验证字符串指示是否发生代理。 如果字符串不包含PAM组映射,则不会发生代理。 在这种情况下,MySQL用户名与外部用户名相同。

  5. 否则,基于PAM组映射指示代理,其中MySQL用户名基于映射列表中的第一个匹配组来确定。 PAM组 的含义 取决于PAM服务。 例子:

    • 对于传统的Unix密码,组是 /etc/group 文件中 定义的Unix组 ,可能 文件中补充了额外的PAM信息 /etc/security/group.conf

    • 对于LDAP,组是LDAP目录中定义的LDAP组。

    如果代理用户(外部用户)具有 PROXY 代理MySQL用户名的特权,则代理用户将承担代理用户的特权,从而进行代理。

安装PAM可插入身份验证

本节介绍如何安装PAM身份验证插件。 有关安装插件的一般信息,请参见 第5.6.1节“安装和卸载插件”

要使服务器可以使用,插件库文件必须位于MySQL插件目录( plugin_dir 系统变量 指定的目录 )中。 如有必要,通过设置 plugin_dir 服务器启动时 的值来配置插件目录位置

插件库文件基本名称是 authentication_pam 文件名后缀因平台 .so 而异 (例如, 对于Unix和类Unix系统, .dll 对于Windows)。

要在服务器启动时加载插件,请使用该 --plugin-load-add 选项命名包含它的库文件。 使用此插件加载方法,每次服务器启动时都必须提供该选项。 例如,将这些行放在服务器 my.cnf 文件中( .so 根据需要 调整 平台 后缀):

的[mysqld]
插件的负载加= authentication_pam.so

修改后 my.cnf ,重新启动服务器以使新设置生效。

或者,要在运行时注册插件,请使用此语句( .so 根据需要 调整 后缀):

INSTALL PLUGIN authentication_pam SONAME'authentication_pam.so';

INSTALL PLUGIN 立即加载插件,并将其注册到 mysql.plugins 系统表中,以使服务器为每个后续的正常启动加载它。

要验证插件安装,请检查 INFORMATION_SCHEMA.PLUGINS 表或使用该 SHOW PLUGINS 语句(请参见 第5.6.2节“获取服务器插件信息” )。 例如:

MySQL的> SELECT PLUGIN_NAME, PLUGIN_STATUS
       FROM INFORMATION_SCHEMA.PLUGINS
       WHERE PLUGIN_NAME LIKE '%pam%';
+ -------------------- + --------------- +
| PLUGIN_NAME | PLUGIN_STATUS |
+ -------------------- + --------------- +
| authentication_pam | ACTIVE |
+ -------------------- + --------------- +

如果插件无法初始化,请检查服务器错误日志以获取诊断消息。

要将MySQL帐户与PAM插件关联,请参阅 使用PAM可插入身份验证

卸载PAM可插入身份验证

用于卸载PAM身份验证插件的方法取决于您安装它的方式:

  • 如果您在服务器启动时使用 --plugin-load-add 选项 安装了插件,请在 没有该选项的情况下重新启动服务器。

  • 如果您在运行时使用安装插件 INSTALL PLUGIN ,它将在服务器重新启动 保持安装。 要卸载它,请使用 UNINSTALL PLUGIN

    UNINSTALL PLUGIN authentication_pam;
    
使用PAM可插入身份验证

本节概括地描述了如何使用PAM身份验证插件从MySQL客户端程序连接到服务器。 以下部分提供了以特定方式使用PAM身份验证的说明。 假设服务器在启用服务器端PAM插件的情况下运行,如 安装PAM可插入身份验证中所述

要在 语句 IDENTIFIED WITH 子句中 引用PAM身份验证插件 CREATE USER ,请使用该名称 authentication_pam 例如:

创建用户 user
  通过authentication_pam识别
  AS' auth_string';

身份验证字符串指定以下类型的信息:

  • PAM服务名称(请参阅 MySQL用户的PAM身份验证如何工作 )。 以下讨论中的示例使用服务名称 mysql-unix 进行使用传统Unix密码 mysql-ldap 的身份验证 ,以及 使用LDAP进行身份验证。

  • 对于代理支持,PAM为PAM模块提供了一种方法,以便在连接到服务器时,将客户端程序传递的外部用户名以外的MySQL用户名返回给服务器。 使用身份验证字符串来控制从外部用户名到MySQL用户名的映射。 如果要利用代理用户功能,则身份验证字符串必须包含此类映射。

例如,如果帐户使用 mysql-unix PAM服务名称并且应该将 root users PAM组 中的操作系统用户分别映射 developer data_entry MySQL用户,请使用如下语句:

创建用户 user
  通过authentication_pam识别
  AS'mysql-unix,root = developer,users = data_entry';

PAM身份验证插件的身份验证字符串语法遵循以下规则:

  • 该字符串由PAM服务名称组成,可选地后跟PAM组映射列表,该列表由一个或多个关键字/值对组成,每个关键字/值对指定一个PAM组名称和一个MySQL用户名:

    pam_service_name[,pam_group_name= mysql_user_name] ......
    

    插件为每个使用该帐户的连接尝试解析身份验证字符串。 为了尽量减少开销,请尽可能缩短字符串。

  • 对必须以逗号开头。 pam_group_name=mysql_user_name

  • 不在双引号内的前导和尾随空格将被忽略。

  • 未加引号 pam_service_name pam_group_name mysql_user_name 值可包含除等号,逗号或空间什么。

  • 如果 使用双引号引用 a pam_service_name pam_group_name mysql_user_name 值,则引号之间的所有内容都是值的一部分。 例如,如果值包含空格字符,则这是必需的。 除双引号和反斜杠( \ 外,所有字符都是合法的 要包含任一字符,请使用反斜杠转义它。

如果插件成功验证了外部用户名(客户端传递的名称),它会在身份验证字符串中查找PAM组映射列表,如果存在,则使用它来向MySQL服务器返回不同的MySQL用户名。哪些PAM组外部用户是以下成员:

  • 如果身份验证字符串不包含PAM组映射列表,则插件将返回外部名称。

  • 如果验证字符串确实包含PAM组映射列表,插件检查每个 列表中对由左到右,并试图找到一个匹配 分配给经过身份验证的用户和收益组的非MySQL目录值 的它找到的第一场比赛。 如果插件找不到任何PAM组的匹配项,则返回外部名称。 如果插件无法在目录中查找组,则会忽略PAM组映射列表并返回外部名称。 pam_group_name=mysql_user_name pam_group_name mysql_user_name

以下部分描述了如何设置使用PAM身份验证插件的多个身份验证方案:

  • 没有代理用户。 这仅使用PAM来检查登录名和密码。 允许连接到MySQL服务器的每个外部用户都应该具有匹配的MySQL帐户,该帐户被定义为使用PAM身份验证。 (对于 与外部用户匹配的 MySQL帐户 必须是外部用户名,并且 必须与客户端连接的主机匹配。)可以通过各种PAM支持的方法执行身份验证。 后面的讨论显示了如何使用传统的Unix密码和LDAP中的密码验证客户端凭据。 'user_name'@'host_name' user_name host_name

    PAM身份验证(不通过代理用户或PAM组完成)要求MySQL用户名与操作系统用户名相同。 MySQL用户名限制为32个字符(请参见 第6.2.3节“授权表” ),这会将PAM非委托身份验证限制为名称最多为32个字符的Unix帐户。

  • 仅限代理用户,具有PAM组映射。 对于此方案,请创建一个或多个定义不同权限集的MySQL帐户。 (理想情况下,没有人应该直接使用这些帐户进行连接。)然后定义一个默认用户通过PAM进行身份验证,该用户使用一些映射方案(通常基于用户所属的外部PAM组)将所有外部用户名映射到少数MySQL持有特权集的帐户。 连接并指定外部用户名作为客户端用户名的任何客户端都映射到其中一个MySQL帐户并使用其权限。 讨论显示了如何使用传统的Unix密码进行设置,

这些方案的变化是可能的:

  • 您可以允许某些用户直接登录(无需代理),但要求其他用户通过代理帐户进行连接。

  • 通过在经过PAM验证的帐户中使用不同的PAM服务名,可以为某些用户使用一种PAM身份验证方法,为其他用户使用另一种方法。 例如,您可以 mysql-unix 为某些用户和 mysql-ldap 其他 用户 使用 PAM服务

这些例子做出以下假设。 如果您的系统设置不同,则可能需要进行一些调整。

  • 登录名和密码分别为 antonio antonio_password 更改这些以对应您要进行身份验证的用户。

  • PAM配置目录是 /etc/pam.d

  • PAM服务名称对应于身份验证方法( mysql-unix mysql-ldap 在此讨论中)。 要使用给定的PAM服务,必须在PAM配置目录中设置具有相同名称的PAM文件(如果文件不存在,则创建该文件)。 此外,您必须在 CREATE USER 使用该PAM服务进行身份验证的任何帐户 语句 的身份验证字符串中命名 PAM服务。

PAM身份验证插件在初始化时检查是否 AUTHENTICATION_PAM_LOG 在服务器的启动环境中设置 环境值。 如果是这样,该插件可以将诊断消息记录到标准输出。 根据服务器的启动方式,消息可能会显示在控制台或错误日志中。 这些消息有助于调试插件执行身份验证时发生的与PAM相关的问题。 有关更多信息,请参阅 PAM身份验证调试

没有代理用户的Unix密码验证

此身份验证方案使用PAM检查根据操作系统用户名和Unix密码定义的外部用户,而无需代理。 允许连接到MySQL服务器的每个这样的外部用户都应该有一个匹配的MySQL帐户,该帐户被定义为通过传统的Unix密码存储使用PAM身份验证。

注意

使用该 /etc/shadow 文件 检查传统的Unix密码 有关与此文件相关的可能问题的信息,请参阅 对Unix密码存储的PAM身份验证访问

  1. 验证Unix身份验证是否允许使用用户名 antonio 和密码 登录操作系统 antonio_password

  2. 通过创建 mysql-unix 名为 PAM服务文件, 设置PAM以使用传统的Unix密码验证MySQL连接 /etc/pam.d/mysql-unix 文件内容与系统有关,因此请检查目录中现有的与登录相关的文件, /etc/pam.d 以查看它们的外观。 在Linux上,该 mysql-unix 文件可能如下所示:

    #%PAM-1.0
    auth包括password-auth
    帐户包括密码验证
    

    对于macOS,请使用 login 而不是 password-auth

    PAM文件格式在某些系统上可能有所不同。 例如,在Ubuntu和其他基于Debian的系统上,请改用以下文件内容:

    @include common-auth
    @include普通帐户
    @include common-session-noninteractive
    
  3. 使用与操作系统用户名相同的用户名创建一个MySQL帐户,并使用PAM插件和 mysql-unix PAM服务 对其进行身份验证

    创建用户'antonio'@'localhost'
      通过authentication_pam识别
      AS'mysql-unix';
    授予所有特权
      在mydb。*
      TO'antonio'@'localhost';
    

    此处,身份验证字符串仅包含PAM服务名称 mysql-unix ,该 服务名称 验证Unix密码。

  4. 使用 mysql 命令行客户端连接到MySQL服务器 antonio 例如:

    shell> mysql --user=antonio --password --enable-cleartext-plugin
    输入密码:antonio_password
    

    服务器应该允许连接,以下查询应该返回输出,如下所示:

    MySQL的> SELECT USER(), CURRENT_USER(), @@proxy_user;
    + ------------------- ------------------- + --------- + ----- +
    | USER()| CURRENT_USER()| @@ proxy_user |
    + ------------------- ------------------- + --------- + ----- +
    | antonio @ localhost | antonio @ localhost | NULL |
    + ------------------- ------------------- + --------- + ----- +
    

    这表明 antonio 操作系统用户已通过身份验证,具有授予 antonio MySQL用户 的权限 ,并且未发生代理。

注意

客户端 mysql_clear_password 身份验证插件保持密码不变,因此客户端程序将其作为明文发送到MySQL服务器。 这使得密码可以原样传递给PAM。 使用服务器端PAM库需要使用明文密码,但在某些配置中可能存在安全问题。 这些措施将风险降至最低:

没有代理用户的LDAP身份验证

此身份验证方案使用PAM检查根据操作系统用户名和LDAP密码定义的外部用户,而无需代理。 允许连接到MySQL服务器的每个这样的外部用户都应该具有匹配的MySQL帐户,该帐户被定义为通过LDAP使用PAM身份验证。

要对MySQL使用PAM LDAP可插入身份验证,必须满足以下先决条件:

  • 必须有LDAP服务器才能与PAM LDAP服务进行通信。

  • 要由MySQL进行身份验证的LDAP用户必须存在于LDAP服务器管理的目录中。

注意

使用LDAP进行MySQL用户身份验证的另一种方法是使用特定于LDAP的身份验证插件。 请参见 第6.4.1.7节“LDAP可插入认证”

为PAM LDAP身份验证配置MySQL,如下所示:

  1. 验证Unix身份验证是否允许使用用户名 antonio 和密码 登录操作系统 antonio_password

  2. 设置PAM以使用LDAP通过创建 mysql-ldap 名为 PAM服务文件 来验证MySQL连接 /etc/pam.d/mysql-ldap 文件内容与系统有关,因此请检查目录中现有的与登录相关的文件, /etc/pam.d 以查看它们的外观。 在Linux上,该 mysql-ldap 文件可能如下所示:

    #%PAM-1.0
    auth需要pam_ldap.so
    需要帐户pam_ldap.so
    

    如果PAM对象文件的后缀与 .so 系统上 的后缀不同 ,请替换正确的后缀。

    PAM文件格式在某些系统上可能有所不同。

  3. 使用与操作系统用户名相同的用户名创建一个MySQL帐户,并使用PAM插件和 mysql-ldap PAM服务 对其进行身份验证

    创建用户'antonio'@'localhost'
      通过authentication_pam识别
      AS'mysql-ldap';
    授予所有特权
      在mydb。*
      TO'antonio'@'localhost';
    

    此处,身份验证字符串仅包含PAM服务名称 mysql-ldap ,该 服务名称 使用LDAP进行身份验证。

  4. 连接到服务器与 没有代理用户的Unix密码验证中 描述的相同

使用代理用户和组映射进行Unix密码验证

此处描述的身份验证方案使用代理和PAM组映射将使用PAM进行身份验证的连接MySQL用户映射到定义不同权限集的其他MySQL帐户。 用户不直接通过定义权限的帐户进行连接。 相反,它们通过使用PAM进行身份验证的默认代理用户进行连接,以便将所有外部用户映射到拥有权限的MySQL帐户。 任何连接的用户都映射到其中一个MySQL帐户,其权限决定了外部用户允许的数据库操作。

此处显示的过程使用Unix密码验证。 要使用LDAP,请参阅 没有代理用户 LDAP身份验证 的早期步骤

注意

使用该 /etc/shadow 文件 检查传统的Unix密码 有关与此文件相关的可能问题的信息,请参阅 对Unix密码存储的PAM身份验证访问

  1. 验证Unix身份验证是否允许使用用户名 antonio 和密码 登录操作系统 antonio_password

  2. 验证 antonio 是的成员 root users PAM基。

  3. 设置PAM以 mysql-unix 通过创建名为的文件来通过操作系统用户 PAM服务 进行身份验证 /etc/pam.d/mysql-unix 文件内容与系统有关,因此请检查目录中现有的与登录相关的文件, /etc/pam.d 以查看它们的外观。 在Linux上,该 mysql-unix 文件可能如下所示:

    #%PAM-1.0
    auth包括password-auth
    帐户包括密码验证
    

    对于macOS,请使用 login 而不是 password-auth

    PAM文件格式在某些系统上可能有所不同。 例如,在Ubuntu和其他基于Debian的系统上,请改用以下文件内容:

    @include common-auth
    @include普通帐户
    @include common-session-noninteractive
    
  4. 创建一个默认代理用户( ''@'' ),将外部PAM用户映射到代理帐户:

    创建用户 ''@''
      通过authentication_pam识别
      AS'mysql-unix,root = developer,users = data_entry';
    

    这里,身份验证字符串包含PAM服务名称 mysql-unix ,用于验证Unix密码。 身份验证字符串还将 root users PAM组中的 外部用户分别映射 developer data_entry MySQL用户名。

    设置代理用户时,需要PAM服务名称后面的PAM组映射列表。 否则,插件无法告诉如何执行从外部用户名到正确代理的MySQL用户名的映射。

    注意

    如果您的MySQL安装具有匿名用户,则可能与默认代理用户冲突。 有关此问题的更多信息以及处理它的方法,请参阅 默认代理用户和匿名用户冲突

  5. 创建具有MySQL访问所需权限的代理帐户:

    创建用户'开发者'@'localhost'
      识别''very secret password';
    创建用户'data_entry'@'localhost'
      识别' very secret password';
    
    授予所有特权
      在mydevdb上。*
      致''开发'''localhost';
    授予所有特权
      在mydb。*
      TO'data_entry'@'localhost';
    

    如果您不让任何人知道这些帐户的密码,客户端就无法使用它们直接连接到MySQL服务器。 相反,预计使用PAM进行身份验证的用户将 根据其PAM组 使用 developer data_entry 代理帐户。

    确保代理帐户无法直接使用的其他方法:

  6. PROXY 权限 授予 每个代理帐户的代理帐户:

    授予代理权
      ON'开发者'@'localhost'
      至 ''@'';
    授予代理权
      ON'data_entry'@'localhost'
      至 ''@'';
    
  7. 使用 mysql 命令行客户端连接到MySQL服务器 antonio

    shell> mysql --user=antonio --password --enable-cleartext-plugin
    输入密码:antonio_password
    

    服务器使用 ''@'' 代理帐户 验证连接 由此产生的权限 antonio 取决于哪些PAM组 antonio 是其成员。 如果 antonio root PAM组 的成员 ,则PAM插件将映射 root developer MySQL用户名并将该名称返回给服务器。 服务器验证是否 ''@'' 具有该 PROXY 权限 developer 并允许连接。 以下查询应返回输出,如下所示:

    MySQL的> SELECT USER(), CURRENT_USER(), @@proxy_user;
    + ------------------- + --------------------- + ------- ------- +
    | USER()| CURRENT_USER()| @@ proxy_user |
    + ------------------- + --------------------- + ------- ------- +
    | antonio @ localhost | developer @ localhost | ''@''|
    + ------------------- + --------------------- + ------- ------- +
    

    这表明 antonio 操作系统用户已通过身份验证,具有授予 developer MySQL用户 的权限 ,并且代理通过默认代理帐户进行。

    如果 antonio 不是 root PAM组的成员但是PAM组的成员, users 则会发生类似的过程,但插件将 user PAM组成员身份 映射 data_entry MySQL用户名并将该名称返回给服务器:

    MySQL的> SELECT USER(), CURRENT_USER(), @@proxy_user;
    + ------------------- + ---------------------- + ------ -------- +
    | USER()| CURRENT_USER()| @@ proxy_user |
    + ------------------- + ---------------------- + ------ -------- +
    | antonio @ localhost | data_entry @ localhost | ''@''|
    + ------------------- + ---------------------- + ------ -------- +
    

    这表明 antonio 操作系统用户已通过身份验证,具有 data_entry MySQL用户 的权限 ,并且代理通过默认代理帐户进行。

注意

客户端 mysql_clear_password 身份验证插件保持密码不变,因此客户端程序将其作为明文发送到MySQL服务器。 这使得密码可以原样传递给PAM。 使用服务器端PAM库需要使用明文密码,但在某些配置中可能存在安全问题。 这些措施将风险降至最低:

PAM身份验证访问Unix密码存储区

在某些系统上,Unix身份验证使用密码存储,例如 /etc/shadow 通常具有受限访问权限的文件。 这可能导致基于MySQL的MySQL身份验证失败。 不幸的是,PAM实现不允许区分 密码无法检查 (例如,由于无法读取 /etc/shadow 密码不匹配。 如果您使用Unix密码存储进行PAM身份验证,则可以使用以下方法之一从MySQL启用对它的访问:

  • 假设MySQL服务器是从 mysql 操作系统帐户 运行的,请将该 帐户放入 shadow 具有 /etc/shadow 访问权限 组中

    1. 在中创建一个 shadow /etc/group

    2. mysql 操作系统用户 添加 shadow 组中 /etc/group

    3. 分配 /etc/group shadow 组并启用组读取权限:

      chgrp shadow / etc / shadow
      chmod g + r / etc / shadow
      
    4. 重启MySQL服务器。

  • 如果您使用的是 pam_unix 模块和 unix_chkpwd 实用程序,请启用密码存储访问,如下所示:

    chmod us / usr / sbin / unix_chkpwd
    setcap cap_dac_read_search + ep / usr / sbin / unix_chkpwd
    

    根据平台的需要 调整 unix_chkpwd 的路径

PAM身份验证调试

PAM身份验证插件在初始化时检查 AUTHENTICATION_PAM_LOG 环境值 是否 已设置(值无关紧要)。 如果是这样,该插件可以将诊断消息记录到标准输出。 这些消息可能有助于调试插件执行身份验证时发生的与PAM相关的问题。

有些消息包括对PAM插件源文件和行号的引用,这使得插件操作可以更紧密地与代码中的位置绑定。

调试连接失败和确定连接尝试期间发生的事情的另一种技术是配置PAM身份验证以允许所有连接,然后检查系统日志文件。 此技术应仅在 临时 基础上使用,而不应在生产服务器上使用。

配置 /etc/pam.d/mysql-any-password 以这些内容 命名的PAM服务文件 (某些系统上的格式可能不同):

#%PAM-1.0
auth需要pam_permit.so
需要帐户pam_permit.so

创建一个使用PAM插件的帐户并命名 mysql-any-password PAM服务:

创建用户'testuser'@'localhost'
  通过authentication_pam识别
  AS'mysql-any-password';

mysql-any-password 服务文件导致的任何身份验证尝试返回true,即使是不正确的密码。 如果身份验证尝试失败,则会告诉您配置问题是在MySQL端。 否则,问题出在操作系统/ PAM端。 要了解可能发生的,请检查系统日志文件,如 /var/log/secure /var/log/audit.log /var/log/syslog ,或 /var/log/messages

确定问题所在后,删除 mysql-any-password PAM服务文件以禁用任何密码访问。

6.4.1.6 Windows可插拔认证

注意

Windows可插入身份验证是MySQL企业版(一种商业产品)中包含的扩展。 要了解有关商业产品的更多信息,请访问 https://www.mysql.com/products/

MySQL Enterprise Edition for Windows支持在Windows上执行外部身份验证的身份验证方法,使MySQL Server能够使用本机Windows服务对客户端连接进行身份验证。 已登录Windows的用户可以根据其环境中的信息从MySQL客户端程序连接到服务器,而无需指定其他密码。

客户端和服务器在身份验证握手中交换数据包。 作为此交换的结果,服务器创建一个安全上下文对象,该对象表示Windows操作系统中客户端的标识。 此标识包括客户帐户的名称。 Windows可插入身份验证使用客户端的标识来检查它是给定帐户还是组成员。 默认情况下,协商使用Kerberos进行身份验证,如果Kerberos不可用,则使用NTLM。

Windows可插入身份验证提供以下功能:

  • 外部身份验证:Windows身份验证使MySQL Server能够接受已登录到Windows的MySQL授权表外部定义的用户的连接。

  • 代理用户支持:Windows身份验证可以向MySQL返回与客户端程序传递的外部用户名不同的用户名。 这意味着该插件可以返回MySQL用户,该用户定义外部Windows身份验证用户应具有的权限。 例如,名为的Windows用户 joe 可以连接并拥有名为的MySQL用户的权限 developer

下表显示了插件和库文件名。 该文件必须位于 plugin_dir 系统变量 指定的目录中

表6.18 Windows身份验证的插件和库名称

插件或文件 插件或文件名
服务器端插件 authentication_windows
客户端插件 authentication_windows_client
库文件 authentication_windows.dll

库文件仅包含服务器端插件。 客户端插件内置于 libmysqlclient 客户端库中。

服务器端Windows身份验证插件仅包含在MySQL Enterprise Edition中。 它不包含在MySQL社区发行版中。 客户端插件包含在所有发行版中,包括社区发行版。 这允许来自任何分发的客户端连接到加载了服务器端插件的服务器。

MySQL 8.0支持的任何Windows版本都支持Windows身份验证插件(请参阅 https://www.mysql.com/support/supportedplatforms/database.html )。

以下部分提供了特定于Windows可插入身份验证的安装和使用信息:

有关MySQL中可插入身份验证的一般信息,请参见 第6.2.17节“可插入身份验证” 有关代理用户信息,请参见 第6.2.18节“代理用户”

安装Windows可插入身份验证

本节介绍如何安装Windows身份验证插件。 有关安装插件的一般信息,请参见 第5.6.1节“安装和卸载插件”

要使服务器可以使用,插件库文件必须位于MySQL插件目录( plugin_dir 系统变量 指定的目录 )中。 如有必要,通过设置 plugin_dir 服务器启动时 的值来配置插件目录位置

要在服务器启动时加载插件,请使用该 --plugin-load-add 选项命名包含它的库文件。 使用此插件加载方法,每次服务器启动时都必须提供该选项。 例如,将这些行放在服务器 my.cnf 文件中:

的[mysqld]
插件的负载加= authentication_windows.dll

修改后 my.cnf ,重新启动服务器以使新设置生效。

或者,要在运行时注册插件,请使用以下语句:

INSTALL PLUGIN authentication_windows SONAME'authentication_windows.dll';

INSTALL PLUGIN 立即加载插件,并将其注册到 mysql.plugins 系统表中,以使服务器为每个后续的正常启动加载它。

要验证插件安装,请检查 INFORMATION_SCHEMA.PLUGINS 表或使用该 SHOW PLUGINS 语句(请参见 第5.6.2节“获取服务器插件信息” )。 例如:

MySQL的> SELECT PLUGIN_NAME, PLUGIN_STATUS
       FROM INFORMATION_SCHEMA.PLUGINS
       WHERE PLUGIN_NAME LIKE '%windows%';
+ ------------------------ + --------------- +
| PLUGIN_NAME | PLUGIN_STATUS |
+ ------------------------ + --------------- +
| authentication_windows | ACTIVE |
+ ------------------------ + --------------- +

如果插件无法初始化,请检查服务器错误日志以获取诊断消息。

要将MySQL帐户与Windows身份验证插件关联,请参阅 使用Windows可插入身份验证

卸载Windows可插入身份验证

用于卸载Windows身份验证插件的方法取决于您的安装方式:

  • 如果您在服务器启动时使用 --plugin-load-add 选项 安装了插件,请在 没有该选项的情况下重新启动服务器。

  • 如果您在运行时使用安装插件 INSTALL PLUGIN ,它将在服务器重新启动 保持安装。 要卸载它,请使用 UNINSTALL PLUGIN

    UNINSTALL PLUGIN authentication_windows;
    

此外,删除任何设置Windows插件相关系统变量的启动选项。

使用Windows可插入身份验证

Windows身份验证插件支持使用MySQL帐户,以便登录到Windows的用户可以连接到MySQL服务器,而无需指定其他密码。 假设服务器在启用服务器端插件的情况下运行,如 安装Windows可插入身份验证中所述 一旦DBA启用了服务器端插件并设置帐户以使用它,客户端就可以使用这些帐户进行连接,而无需其他设置。

要在 语句 IDENTIFIED WITH 子句中 引用Windows身份验证插件 CREATE USER ,请使用该名称 authentication_windows 假设Windows用户 Rafal ,并 Tasha 应允许连接到MySQL,以及任何用户的 Administrators Power Users 组。 要进行此设置,请创建一个名为 sql_admin 使用Windows插件进行身份验证 的MySQL帐户

CREATE USER sql_admin
  通过authentication_windows识别
  AS'Rafal,Tasha,管理员,“超级用户”';

插件名称是 authentication_windows AS 关键字 后面的字符串 是身份验证字符串。 它指定Windows用户命名 Rafal Tasha 允许以MySQL用户身份向服务器进行身份验证,该 sql_admin 用户 Administrators Power Users 中的任何Windows用户也是如此 后一组名称包含空格,因此必须使用双引号字符引用。

创建 sql_admin 帐户后,登录到Windows的用户可以尝试使用该帐户连接到服务器:

C:\> mysql --user=sql_admin

这里不需要密码。 authentication_windows 插件使用Windows安全API来检查哪个Windows用户正在连接。 如果该用户被命名为 Rafal Tasha ,或者是的成员 Administrators Power Users 组,服务器授予访问权限和客户端进行身份验证为 sql_admin ,有什么权限授予 sql_admin 帐户。 否则,服务器拒绝访问。

Windows身份验证插件的身份验证字符串语法遵循以下规则:

  • 该字符串由一个或多个用逗号分隔的用户映射组成。

  • 每个用户映射将Windows用户或组名与MySQL用户名相关联:

    win_user_or_group_name=mysql_user_name
    win_user_or_group_name
    

    对于后一种语法,没有 mysql_user_name 给出值,隐式值是由 CREATE USER 语句 创建的MySQL用户 因此,这些陈述是等价的:

    CREATE USER sql_admin
      通过authentication_windows识别
      AS'Rafal,Tasha,管理员,“超级用户”';
    
    CREATE USER sql_admin
      通过authentication_windows识别
      AS'Rafal = sql_admin,Tasha = sql_admin,Administrators = sql_admin,
          “Power Users”= sql_admin';
    
  • 值中的每个反斜杠( '\' )必须加倍,因为反斜杠是MySQL字符串中的转义字符。

  • 不在双引号内的前导和尾随空格将被忽略。

  • 不带引号 win_user_or_group_name mysql_user_name 值可以包含除等号,逗号或空格之外的任何内容。

  • 如果 使用双引号引用 a win_user_or_group_name 和or mysql_user_name 值,则引号之间的所有内容都是值的一部分。 例如,如果名称包含空格字符,则这是必需的。 除双引号和反斜杠外,双引号内的所有字符都是合法的。 要包含任一字符,请使用反斜杠转义它。

  • win_user_or_group_name 值使用Windows主体的常规语法,无论是本地还是域。 示例(注意反斜杠加倍):

    域\\用户
    。\\用户
    域\\组
    。\\组
    BUILTIN \\ WellKnownGroup
    

当服务器调用以验证客户端时,插件会从左到右扫描身份验证字符串,以便用户或组匹配Windows用户。 如果匹配,则插件返回与 mysql_user_name MySQL服务器 对应的对应项 如果没有匹配,则身份验证失败。

用户名匹配优先于组名匹配。 假设命名的Windows用户 win_user 是其成员, win_group 并且身份验证字符串如下所示:

'win_group = sql_user1,win_user = sql_user2'

win_user 连接到MySQL服务器时,to win_group 和to 都匹配 win_user 该插件对用户进行身份验证, sql_user2 因为更具体的用户匹配优先于组匹配,即使该组首先列在身份验证字符串中。

Windows身份验证始终适用于运行服务器的同一台计算机上的连接。 对于跨计算机连接,两台计算机都必须在Windows Active Directory中注册。 如果它们位于同一Windows域中,则无需指定域名。 也可以允许来自不同域的连接,如下例所示:

CREATE USER sql_accounting
  通过authentication_windows识别
  AS'SomeDomain \\ Accounting';

SomeDomain 是其他域名。 反斜杠字符加倍,因为它是字符串中的MySQL转义字符。

MySQL支持代理用户的概念,客户端可以使用一个帐户连接和验证MySQL服务器,但连接时具有另一个帐户的权限(请参见 第6.2.18节“代理用户” )。 假设您希望Windows用户使用单个用户名进行连接,但是根据其Windows用户和组名称将其映射到特定的MySQL帐户,如下所示:

  • local_user MyDomain\domain_user 本地和域Windows用户应该映射到 local_wlad MySQL账户。

  • MyDomain\Developers 域组 中的用户 应映射到 local_dev MySQL帐户。

  • 本地计算机管理员应映射到 local_admin MySQL帐户。

要使用此功能,为Windows用户创建连接到代理帐户,并配置该帐户,使用户和用户组映射到相应的MySQL账户( local_wlad local_dev local_admin )。 此外,为MySQL帐户授予适合其需要执行的操作的权限。 下面的说明使用 win_proxy 的代理帐户,和 local_wlad local_dev local_admin 为代理账户。

  1. 创建代理MySQL帐户:

    CREATE USER win_proxy
      通过authentication_windows识别
      AS'local_user = local_wlad,
          MyDomain \\ domain_user = local_wlad,
          MyDomain \\ Developers = local_dev,
          BUILTIN \\ Administrators = local_admin';
    
    注意

    如果您的MySQL安装具有匿名用户,则可能与默认代理用户冲突。 有关此问题的更多信息以及处理它的方法,请参阅 默认代理用户和匿名用户冲突

  2. 要使代理工作,代理帐户必须存在,因此创建它们:

    CREATE USER local_wlad IDENTIFIED BY'wlad_pass';
    CREATE USER local_dev IDENTIFIED BY'dev_pass';
    CREATE USER local_admin IDENTIFIED BY'admin_pass';
    

    如果您不让任何人知道这些帐户的密码,则其他用户无法使用它们直接连接到MySQL服务器。

    您还应该发出 GRANT 声明(未显示),为每个代理帐户授予其所需的权限。

  3. 代理帐户必须具有 PROXY 每个代理帐户 权限:

    授予on_wlad TO win_proxy;
    在local_dev上授予代理权限win_proxy;
    在local_admin上授予代理权到WIN_proxy;
    

现在的Windows用户 local_user ,并 MyDomain\domain_user 可以连接到MySQL服务器 win_proxy 和身份验证时,必须在验证字符串,在这种情况下,考虑到帐户的权限, local_wlad MyDomain\Developers 连接 组中 的用户 win_proxy 具有该 local_dev 帐户 的权限 BUILTIN\Administrators 组中的 用户 具有该 local_admin 帐户 的权限

要配置身份验证,以便所有没有自己的MySQL帐户的Windows用户都通过代理帐户,请 在前面的说明中 替换默认代理用户( ''@'' win_proxy 有关默认代理用户的信息,请参见 第6.2.18节“代理用户”

要在Connector / NET 6.4.4和更高版本中 使用 带有Connector / NET连接字符串 的Windows身份验证插件 ,请参阅 使用Windows本地身份验证插件

Windows身份验证插件的附加控制由 authentication_windows_use_principal_name authentication_windows_log_level 系统变量提供。 请参见 第5.1.8节“服务器系统变量”

6.4.1.7 LDAP可插入认证

注意

LDAP可插入身份验证是MySQL Enterprise Edition(一种商业产品)中包含的扩展。 要了解有关商业产品的更多信息,请访问 https://www.mysql.com/products/

MySQL企业版支持一种身份验证方法,使MySQL服务器能够使用LDAP(轻量级目录访问协议)通过访问X.500等目录服务来验证MySQL用户。 MySQL使用LDAP来获取用户,凭证和组信息。

LDAP可插入身份验证提供以下功能:

  • 外部身份验证:LDAP身份验证使MySQL Server能够接受来自LDAP目录中MySQL授权表之外定义的用户的连接。

  • 代理用户支持:LDAP身份验证可以根据外部用户所属的LDAP组,向MySQL返回与客户端程序传递的外部用户名不同的用户名。 这意味着LDAP插件可以返回MySQL用户,该用户定义外部LDAP身份验证用户应具有的权限。 例如,名为的LDAP用户 joe 可以连接并有一个名为MySQL用户的权限 developer ,如果用于LDAP组 joe developer

  • 安全性:使用TLS,与LDAP服务器的连接可以是安全的。

下表显示了插件和库文件名。 文件名后缀可能与您的系统不同。 这些文件必须位于由 plugin_dir 系统变量

表6.19 LDAP身份验证的插件和库名称

插件或文件 插件或文件名
服务器端插件名称 authentication_ldap_sasl authentication_ldap_simple
客户端插件名称 authentication_ldap_sasl_client mysql_clear_password
库文件名 authentication_ldap_sasl.so authentication_ldap_sasl_client.so authentication_ldap_simple.so

库文件仅包含 身份验证插件。 客户端 插件内置于 客户端库中。 authentication_ldap_XXX mysql_clear_password libmysqlclient

两个服务器端LDAP插件均使用特定的客户端插件:

  • 服务器端 authentication_ldap_simple 插件执行简单的LDAP身份验证。 对于使用此插件的帐户的连接,客户端程序使用客户端 mysql_clear_password 插件,该插件将密码作为明文发送到服务器。 没有使用密码散列或加密,因此建议在MySQL客户端和服务器之间建立安全连接以防止密码泄露。

  • 服务器端 authentication_ldap_sasl 插件执行基于SASL的LDAP身份验证。 对于使用此插件的帐户的连接,客户端程序使用客户端 authentication_ldap_sasl_client 插件。 客户端和服务器端SASL LDAP插件使用SASL消息在LDAP协议中安全传输凭据,以避免在MySQL客户端和服务器之间发送明文密码。

以下部分提供特定于LDAP可插入身份验证的安装和使用信息:

有关MySQL中可插入身份验证的一般信息,请参见 第6.2.17节“可插入身份验证” 有关 mysql_clear_password 插件的 信息 ,请参见 第6.4.1.4节“客户端明文可插入认证” 有关代理用户信息,请参见 第6.2.18节“代理用户”

注意

如果您的系统支持PAM并允许LDAP作为PAM身份验证方法,则使用LDAP进行MySQL用户身份验证的另一种方法是使用服务器端 authentication_pam 插件。 请参见 第6.4.1.5节“PAM可插拔认证”

LDAP可插入身份验证的先决条件

要对MySQL使用LDAP可插入身份验证,必须满足以下先决条件:

  • 必须有LDAP服务器才能与LDAP身份验证插件进行通信。

  • 要由MySQL进行身份验证的LDAP用户必须存在于LDAP服务器管理的目录中。

  • LDAP客户端库必须在使用服务器端 authentication_ldap_sasl authentication_ldap_simple 插件的 系统上可用 目前,受支持的库是Windows本机LDAP库,或非Windows系统上的OpenLDAP库。

  • 要使用基于SASL的LDAP身份验证:

    • 必须将LDAP服务器配置为与SASL服务器通信。

    • 必须在使用客户端 authentication_ldap_sasl_client 插件的 系统上提供SASL客户端库 目前,唯一受支持的库是Cyrus SASL库。

MySQL用户的LDAP身份验证如何工作

本节概述了MySQL和LDAP如何协同工作以验证MySQL用户。 有关如何设置MySQL帐户以使用特定LDAP身份验证插件的示例,请参阅 使用LDAP可插入身份验证

客户端连接到MySQL服务器,提供MySQL客户端用户名和LDAP密码:

  • 对于简单的LDAP身份验证,客户端和服务器端插件将密码作为明文进行通信。

  • 对于基于SASL的LDAP身份验证,客户端和服务器端插件使用SASL消息在LDAP协议中安全传输凭据,以避免在MySQL客户端和服务器之间发送明文密码。

如果客户端用户名和主机名不匹配MySQL帐户,则拒绝连接。

如果存在匹配的MySQL帐户,则会发生针对LDAP的身份验证。 LDAP服务器查找与用户匹配的条目,并根据LDAP密码对条​​目进行身份验证:

  • 如果MySQL帐户命名LDAP用户可分辨名称(DN),则LDAP身份验证使用该值和客户端提供的LDAP密码。 (要将LDAP用户DN与MySQL帐户关联,请 BY CREATE USER 创建帐户 语句中 包含 指定身份验证字符串 子句 。)

  • 如果MySQL帐户没有命名LDAP用户DN,则LDAP身份验证使用客户端提供的用户名和LDAP密码。 在这种情况下,身份验证插件首先使用根DN和密码作为凭据绑定到LDAP服务器,以根据客户端用户名查找用户DN,然后根据LDAP密码对该用户DN进行身份验证。 如果根DN和密码设置为不正确的值,或者为空(未设置)且LDAP服务器不允许匿名连接,则使用根凭据进行此绑定将失败。

如果LDAP服务器未找到匹配项或多个匹配项,则身份验证将失败并拒绝客户端连接。

如果LDAP服务器找到单个匹配项,则LDAP身份验证成功(假设密码正确),LDAP服务器返回LDAP条目,并且身份验证插件根据该条目确定经过身份验证的用户的名称:

  • 如果LDAP条目具有组属性(默认情况下为该 cn 属性),则插件将其值作为经过身份验证的用户名返回。

  • 如果LDAP条目没有组属性,则身份验证插件将客户端用户名作为经过身份验证的用户名返回。

MySQL服务器将客户端用户名与经过身份验证的用户名进行比较,以确定是否为客户端会话进行了代理:

  • 如果名称相同,则不会发生代理:与客户端用户名匹配的MySQL帐户用于权限检查。

  • 如果名称不同,则会发生代理:MySQL查找与经过身份验证的用户名匹配的帐户。 该帐户成为代理用户,用于进行权限检查。 与客户端用户名匹配的MySQL帐户被视为外部代理用户。

安装LDAP可插入身份验证

本节介绍如何安装LDAP身份验证插件。 有关安装插件的一般信息,请参见 第5.6.1节“安装和卸载插件”

要使服务器可以使用,插件库文件必须位于MySQL插件目录( plugin_dir 系统变量 指定的目录 )中。 如有必要,通过设置 plugin_dir 服务器启动时 的值来配置插件目录位置

服务器端插件库文件基名是 authentication_ldap_sasl authentication_ldap_simple 文件名后缀因平台 .so 而异 (例如, 对于Unix和类Unix系统, .dll 对于Windows)。

要在服务器启动时加载插件,请使用 --plugin-load-add 选项命名包含它们的库文件。 使用此插件加载方法,每次服务器启动时都必须提供选项。 另外,为要配置的任何插件提供的系统变量指定值。

每个服务器端LDAP插件都公开一组系统变量,以便配置其操作。 设置其中大部分是可选的,但您必须设置指定LDAP服务器主机的变量(以便插件知道连接的位置)和LDAP绑定操作的基本专有名称(以限制搜索范围并获得更快的搜索)。 有关所有LDAP系统变量的详细信息,请参见 第6.4.1.11节“可插入的认证系统变量”

要加载插件并为LDAP绑定操作设置LDAP服务器主机和基本专有名称,请在 my.cnf 文件中 放置这些行 .so 根据需要 调整 平台 后缀):

的[mysqld]
插件的负载加= authentication_ldap_sasl.so
authentication_ldap_sasl_server_host = 127.0.0.1
authentication_ldap_sasl_bind_base_dn = “DC =例如,DC = COM”
插件的负载加= authentication_ldap_simple.so
authentication_ldap_simple_server_host = 127.0.0.1
authentication_ldap_simple_bind_base_dn = “DC =例如,DC = COM”

修改后 my.cnf ,重新启动服务器以使新设置生效。

或者,要在运行时注册插件,请使用这些语句( .so 根据需要 调整 后缀):

INSTALL PLUGIN authentication_ldap_sasl
  SONAME'authentication_ldap_sasl.so';
INSTALL PLUGIN authentication_ldap_simple
  SONAME'authentication_ldap_simple.so';

INSTALL PLUGIN 立即加载插件,并将其注册到 mysql.plugins 系统表中,以使服务器为每个后续的正常启动加载它。

在运行时安装插件后,它们的系统变量可用,您可以将它们的设置添加到 my.cnf 文件中,以配置插件以便后续重新启动。 例如:

的[mysqld]
authentication_ldap_sasl_server_host = 127.0.0.1
authentication_ldap_sasl_bind_base_dn = “DC =例如,DC = COM”
authentication_ldap_simple_server_host = 127.0.0.1
authentication_ldap_simple_bind_base_dn = “DC =例如,DC = COM”

修改后 my.cnf ,重新启动服务器以使新设置生效。

或者,要在运行时设置和持久化值,请使用以下语句:

SET PERSIST authentication_ldap_sasl_server_host ='127.0.0.1';
SET PERSIST authentication_ldap_sasl_bind_base_dn ='dc = example,dc = com';
SET PERSIST authentication_ldap_simple_server_host ='127.0.0.1';
SET PERSIST authentication_ldap_simple_bind_base_dn ='dc = example,dc = com';

SET PERSIST 设置正在运行的MySQL实例的值。 它还会保存该值,使其用于后续服务器重新启动。 要更改正在运行的MySQL实例的值而不保存它以便后续重新启动,请使用 GLOBAL 关键字而不是 PERSIST 请参见 第13.7.5.1节“变量赋值的SET语法”

要验证插件安装,请检查 INFORMATION_SCHEMA.PLUGINS 表或使用该 SHOW PLUGINS 语句(请参见 第5.6.2节“获取服务器插件信息” )。 例如:

MySQL的> SELECT PLUGIN_NAME, PLUGIN_STATUS
       FROM INFORMATION_SCHEMA.PLUGINS
       WHERE PLUGIN_NAME LIKE '%ldap%';
+ ---------------------------- + -------- +
| PLUGIN_NAME | PLUGIN_STATUS |
+ ---------------------------- + -------- +
| authentication_ldap_sasl | ACTIVE |
| authentication_ldap_simple | ACTIVE |
+ ---------------------------- + -------- +

如果插件无法初始化,请检查服务器错误日志以获取诊断消息。

要将MySQL帐户与LDAP插件关联,请参阅 使用LDAP可插入身份验证

SELinux的附加说明

在运行启用了SELinux的EL6或EL的系统上,需要更改SELinux策略以使MySQL LDAP插件能够与LDAP服务通信:

  1. 创建 mysqlldap.te 包含以下内容 的文件

    模块mysqlldap 1.0;
    
    要求{
            输入ldap_port_t;
            输入mysqld_t;
            class tcp_socket name_connect;
    }
    
    #============= mysqld_t ==============
    
    允许mysqld_t ldap_port_t:tcp_socket name_connect;
    
  2. 将安全策略模块编译为二进制表示:

    checkmodule -M -m mysqlldap.te -o mysqlldap.mod
    
  3. 创建SELinux策略模块包:

    semodule_package -m mysqlldap.mod -o mysqlldap.pp
    
  4. 安装模块包:

    semodule -i mysqlldap.pp
    
  5. 完成SELinux策略更改后,重新启动MySQL服务器:

    service mysqld restart
    
卸载LDAP可插入身份验证

用于卸载LDAP身份验证插件的方法取决于您安装它们的方式:

  • 如果您在服务器启动时使用 --plugin-load-add 选项 安装了插件 ,请重新启动没有这些选项的服务器。

  • 如果您在运行时使用安装插件 INSTALL PLUGIN ,它们将在服务器重新启动 保持安装状态。 要卸载它们,请使用 UNINSTALL PLUGIN

    UNINSTALL PLUGIN authentication_ldap_sasl;
    UNINSTALL PLUGIN authentication_ldap_simple;
    

此外,从 my.cnf 文件中 删除 任何设置LDAP插件相关系统变量的启动选项。 如果您曾经 SET PERSIST 保留LDAP系统变量,请使用 RESET PERSIST 删除设置。

使用LDAP可插入身份验证

本节介绍如何使用LDAP可插入身份验证启用MySQL帐户连接到MySQL服务器。 假设服务器正在运行,并启用了相应的服务器端插件,如 安装LDAP可插入身份验证中所述 ,并且客户端主机上提供了相应的客户端插件。

本节不介绍LDAP配置或管理。 假设您熟悉这些主题。

两个服务器端LDAP插件均使用特定的客户端插件:

  • 服务器端 authentication_ldap_simple 插件执行简单的LDAP身份验证。 对于使用此插件的帐户的连接,客户端程序使用客户端 mysql_clear_password 插件,该插件将密码作为明文发送到服务器。 没有使用密码散列或加密,因此建议在MySQL客户端和服务器之间建立安全连接以防止密码泄露。

  • 服务器端 authentication_ldap_sasl 插件执行基于SASL的LDAP身份验证。 对于使用此插件的帐户的连接,客户端程序使用客户端 authentication_ldap_sasl_client 插件。 客户端和服务器端SASL LDAP插件使用SASL消息在LDAP协议中安全传输凭据,以避免在MySQL客户端和服务器之间发送明文密码。

MySQL用户的LDAP身份验证的总体要求:

  • 必须有每个要进行身份验证的用户的LDAP目录条目。

  • 必须有一个MySQL用户帐户,该帐户指定服务器端LDAP身份验证插件,并可选择指定关联的LDAP用户可分辨名称(DN)。 (要将LDAP用户DN与MySQL帐户相关联,请 BY CREATE USER 创建帐户 语句中 包含一个 子句 。)如果帐户未指定LDAP字符串,则LDAP身份验证使用客户端指定的用户名来查找LDAP条目。

  • 客户端程序使用适用于MySQL帐户使用的服务器端身份验证插件的连接方法进行连接。 对于LDAP身份验证,连接需要MySQL用户名和LDAP密码。 此外,对于使用服务器端 authentication_ldap_simple 插件的 帐户,可以使用 --enable-cleartext-plugin 启用客户端 mysql_clear_password 插件 选项 调用客户端程序

这里的说明假设以下情形:

  • MySQL用户 betsy 分别 boris betsy_ldap 和/或 LDAP条目进行身份验证 boris_ldap (MySQL和LDAP用户名没有必要不同。在本讨论中使用不同的名称有助于阐明操作上下文是MySQL还是LDAP。)

  • LDAP条目使用该 uid 属性指定用户名。 这可能因LDAP服务器而异。 某些LDAP服务器将该 cn 属性用于用户名而不是 uid 要更改属性,请相应地修改 authentication_ldap_simple_user_search_attr authentication_ldap_sasl_user_search_attr 系统变量。

  • 这些LDAP条目在LDAP服务器管理的目录中可用,以提供唯一标识每个用户的可分辨名称值:

    UID = betsy_ldap,OU =人民,DC =例如,DC = COM
    UID = boris_ldap,OU =人民,DC =例如,DC = COM
    
  • CREATE USER 创建MySQL帐户的语句在 BY 子句中 命名为LDAP用户 ,以指示MySQL帐户对哪个LDAP条目进行身份验证。

设置使用LDAP身份验证的帐户的说明取决于使用的服务器端LDAP插件。

简单LDAP身份验证

要为简单LDAP身份验证配置MySQL帐户,该 CREATE USER 语句指定 authentication_ldap_simple 插件,并可选择命名LDAP用户可分辨名称(DN):

创建用户 user
  使用authentication_ldap_simple进行身份识别
  [BY' LDAP user DN'];

假设MySQL用户 betsy 在LDAP目录中有此条目:

UID = betsy_ldap,OU =人民,DC =例如,DC = COM

然后创建MySQL帐户的语句 betsy 如下所示:

创建用户'betsy'@'localhost'
  使用authentication_ldap_simple进行身份识别
  BY'uid = betsy_ldap,ou = People,dc = example,dc = com';

BY 子句中 指定的身份验证字符串 不包含LDAP密码。 这必须由客户端用户在连接时提供。

客户端通过提供MySQL用户名和LDAP密码以及启用客户端 mysql_clear_password 插件 来连接到MySQL服务器

shell> mysql --user=betsy --password --enable-cleartext-plugin
输入密码:betsy_password (betsy_ldap LDAP password)
注意

客户端 mysql_clear_password 身份验证插件保持密码不变,因此客户端程序将其作为明文发送到MySQL服务器。 这使密码可以原样传递给LDAP服务器。 在没有SASL的情况下使用服务器端LDAP库需要使用明文密码,但在某些配置中可能存在安全问题。 这些措施将风险降至最低:

身份验证过程如下:

  1. 该客户端插件将 betsy betsy_password 作为到MySQL服务器的客户端的用户名和密码,LDAP。

  2. 连接尝试与 'betsy'@'localhost' 帐户 匹配 服务器端LDAP插件发现此帐户具有 'uid=betsy_ldap,ou=People,dc=example,dc=com' 用于命名LDAP用户DN 的身份验证字符串 该插件将此字符串和LDAP密码发送到LDAP服务器。

  3. LDAP服务器查找LDAP条目 betsy_ldap 并且密码匹配,因此LDAP身份验证成功。

  4. LDAP条目没有组属性,因此服务器端插件将客户端用户名( betsy )作为经过身份验证的用户返回。 这是客户端提供的相同用户名,因此不会发生代理,客户端会话使用该 'betsy'@'localhost' 帐户进行权限检查。

如果匹配的LDAP条目包含组属性,则该属性值将是经过身份验证的用户名,如果值不同 betsy ,则会发生代理。 有关使用组属性的示例,请参阅 使用代理进行LDAP身份验证

如果该 CREATE USER 语句不包含 BY 指定 betsy_ldap LDAP专有名称的 子句 ,则认证尝试将使用客户端提供的用户名(在本例中 betsy )。 如果没有LDAP条目 betsy ,则身份验证将失败。

基于SASL的LDAP身份验证

要为SASL LDAP身份验证配置MySQL帐户,该 CREATE USER 语句指定 authentication_ldap_sasl 插件,并可选择命名LDAP用户可分辨名称(DN):

创建用户 user
  使用authentication_ldap_sasl识别
  [BY' LDAP user DN'];

假设MySQL用户 boris 在LDAP目录中有此条目:

UID = boris_ldap,OU =人民,DC =例如,DC = COM

然后创建MySQL帐户的语句 boris 如下所示:

创建用户'boris'@'localhost'
  使用authentication_ldap_sasl识别
  BY'uid = boris_ldap,ou = People,dc = example,dc = com';

BY 子句中 指定的身份验证字符串 不包含LDAP密码。 这必须由客户端用户在连接时提供。

客户端通过提供MySQL用户名和LDAP密码连接到MySQL服务器:

shell> mysql --user=boris --password
输入密码:boris_password (boris_ldap LDAP password)

对于服务器端 authentication_ldap_sasl 插件,客户端使用客户端 authentication_ldap_sasl_client 插件。 如果客户端程序找不到客户端插件,请指定一个 --plugin-dir 选项, 选项命名安装插件库文件的目录。

除了客户端和服务器端SASL LDAP插件使用SASL消息在LDAP协议中安全传输凭据之外, 身份验证过程 boris 类似于之前针对 betsy 简单LDAP身份验证 所描述 的身份验证过程 ,以避免在两者之间发送明文密码。 MySQL客户端和服务器。

LDAP身份验证用户DN后缀

LDAP身份验证插件允许提供用户DN信息的身份验证字符串以 + 前缀字符 开头

  • 如果没有 + 字符,则认证字符串值将被视为未经修改。

  • 如果身份验证字符串以此开头 + ,则插件会根据客户端发送的用户名以及身份验证字符串中指定的DN(已 + 删除) 构造完整的用户DN值 在构造的DN中,客户端用户名将成为指定LDAP用户名的属性的值。 这是 uid 默认情况下; 要更改属性,请相应地修改 authentication_ldap_simple_user_search_attr authentication_ldap_sasl_user_search_attr 系统变量。 身份验证字符串存储为 mysql.user 系统表,在认证之前即时构建完整的用户DN。

此帐户身份验证字符串 + 在开头没有,因此它被视为完整用户DN:

创建用户'baldwin'
  使用authentication_ldap_simple进行身份识别
  BY'uid = admin,ou = People,dc = example,dc = com';

客户端使用帐户( baldwin )中 指定的用户名进行连接 在这种情况下,不使用该名称,因为身份验证字符串没有前缀,因此完全指定了用户DN。

此帐户身份验证字符串 + 在开头有,因此它只是用户DN的一部分:

创建用户'会计'
  使用authentication_ldap_simple进行身份识别
  BY'+ ou = People,dc = example,dc = com';

客户端使用account( accounting )中 指定的用户名连接 ,在这种情况下 ,该用户名 uid 与身份验证字符串一起 用作 构造用户DN 属性: uid=accounting,ou=People,dc=example,dc=com

前面示例中的帐户具有非空用户名,因此客户端始终使用帐户定义中指定的相同名称连接到MySQL服务器。 如果帐户具有空的用户名,例如 LDAP验证和代理中 ''@'%' 描述 的通用匿名 代理帐户 ,则客户端可能会使用不同的用户名连接到MySQL服务器。 但原理是相同的:如果 认证字符串以此 开头 ,则插件使用客户端发送的用户名和认证字符串来构造用户DN。 +

使用代理进行LDAP身份验证

LDAP身份验证插件支持代理,使用户能够以一个用户身份连接到MySQL服务器,但却拥有不同用户的权限。 本节介绍基本的LDAP插件代理支持。 LDAP插件还支持组首选项和代理用户映射的规范; 请参阅 LDAP身份验证组首选项和映射规范

此处描述的身份验证方案使用基于映射LDAP组属性值的代理连接将使用LDAP进行身份验证的MySQL用户连接到定义不同权限集的其他MySQL帐户。 用户不直接通过定义权限的帐户进行连接。 相反,它们通过使用LDAP进行身份验证的默认代理用户进行连接,以便将所有外部登录映射到拥有权限的MySQL帐户。 任何连接的用户都映射到其中一个MySQL帐户,其权限决定了外部用户允许的数据库操作。

这里的说明假设以下情形:

  • LDAP条目分别使用 uid cn 属性指定用户名和组值。 要使用不同的用户和组属性名称,请设置适当的系统变量以配置插件:

  • 这些LDAP条目在LDAP服务器管理的目录中可用,以提供唯一标识每个用户的可分辨名称值:

    UID =芭莎,OU =人民,DC =例如,DC = COM,CN =会计
    UID =罗勒,OU =人民,DC =例如,DC = COM,CN = front_office
    

    组属性值将成为经过身份验证的用户名,因此他们将 代理 accounting front_office 代理帐户 命名

  • 这些示例假定使用SASL LDAP身份验证。 对简单的LDAP身份验证进行适当的调整。

创建默认代理MySQL帐户:

创建用户 ''@'%'
  通过authentication_ldap_simple识别;

代理帐户定义没有 用于命名LDAP用户DN的子句。 从而: BY 'auth_string'

  • 客户端连接时,客户端用户名将用作要搜索的LDAP用户名。

  • 匹配的LDAP条目应包括一个组属性,用于命名代理的MySQL帐户,该帐户定义客户端应具有的权限。

注意

如果您的MySQL安装具有匿名用户,则可能与默认代理用户冲突。 有关此问题的更多信息以及处理它的方法,请参阅 默认代理用户和匿名用户冲突

创建代理帐户并授予其权限:

CREATE USER'accounting'@'localhost'ACCOUNT LOCK;
CREATE USER'front_office'@'localhost'ACCOUNT LOCK;

授予所有特权
  在accountingdb。*
  ''accounting'@'localhost';
授予所有特权
  在frontdb。*
  TO'front_office'@'localhost';

PROXY 权限 授予 每个代理帐户的代理帐户:

授予代理权
  ON'accounting'@'localhost'
  至 ''@'%';
授予代理权
  ON'front_office'@'localhost'
  至 ''@'%';

使用 mysql 命令行客户端连接到MySQL服务器 basha

shell> mysql --user=basha --password
输入密码:basha_password (basha LDAP password)

身份验证发生如下:

  1. ''@'%' 对于客户端用户, 服务器使用该 帐户 验证连接 basha

  2. 匹配的LDAP条目是:

    UID =芭莎,OU =人民,DC =例如,DC = COM,CN =会计
    
  3. 匹配的LDAP条目具有组属性 cn=accounting ,因此 accounting 成为经过身份验证的用户。

  4. 经过身份验证的用户与客户端用户名不同 basha ,其结果 basha 被视为代理 accounting ,并 basha 承担 accounting 帐户 的权限 以下查询应返回输出,如下所示:

    MySQL的> SELECT USER(), CURRENT_USER(), @@proxy_user;
    + ----------------- + ---------------------- + -------- ------ +
    | USER()| CURRENT_USER()| @@ proxy_user |
    + ----------------- + ---------------------- + -------- ------ +
    | basha @ localhost | accounting @ localhost | ''@'%'|
    + ----------------- + ---------------------- + -------- ------ +
    

这表明 basha 使用授予 accounting MySQL帐户 的权限 ,并且代理通过默认代理用户帐户发生。

现在连接 basil

shell> mysql --user=basil --password
输入密码:basil_password (basil LDAP password)

身份验证过程 basil 与之前描述的类似 basha

  1. ''@'%' 对于客户端用户, 服务器使用该 帐户 验证连接 basil

  2. 匹配的LDAP条目是:

    UID =罗勒,OU =人民,DC =例如,DC = COM,CN = front_office
    
  3. 匹配的LDAP条目具有组属性 cn=front_office ,因此 front_office 成为经过身份验证的用户。

  4. 经过身份验证的用户与客户端用户名不同 basil ,其结果 basil 被视为代理 front_office ,并 basil 承担 front_office 帐户 的权限 以下查询应返回输出,如下所示:

    MySQL的> SELECT USER(), CURRENT_USER(), @@proxy_user;
    + ----------------- + ------------------------ + ------ -------- +
    | USER()| CURRENT_USER()| @@ proxy_user |
    + ----------------- + ------------------------ + ------ -------- +
    | 罗勒@ localhost | front_office @ localhost | ''@'%'|
    + ----------------- + ------------------------ + ------ -------- +
    

这表明 basil 使用授予 front_office MySQL帐户 的权限 ,并且代理通过默认代理用户帐户发生。

LDAP身份验证组首选项和映射规范

使用代理的LDAP身份验证中 所述 ,基本LDAP身份验证代理的工作原理是插件使用LDAP服务器返回的第一个组名作为MySQL代理用户帐户名。 如果LDAP服务器返回多个名称,或者除组名称以外的任何名称作为代理用户名,则此简单功能不允许指定要使用的组名称的任何首选项。

从MySQL 8.0.14开始,对于使用LDAP身份验证的MySQL帐户,身份验证字符串可以指定以下信息以实现更大的代理灵活性:

  • 按优先顺序排列的组列表,以便插件使用列表中与LDAP服务器返回的组匹配的第一个组名。

  • 从组名到代理用户名的映射,这样匹配时的组名可以提供指定的名称以用作代理用户。 这提供了使用组名作为代理用户的替代方法。

请考虑以下MySQL代理帐户定义:

创建用户 ''@'%'
  使用authentication_ldap_sasl识别
  BY'+ ou = People,dc = example,dc = com#grp1 = usera,grp2,grp3 = userc';

身份验证字符串具有 ou=People,dc=example,dc=com + 字符 为前缀 的用户DN后缀 因此,如 LDAP身份验证用户DN后缀 中所述,完整用户DN是根据指定的用户DN后缀以及客户端用户名作为 uid 属性 构造的

身份验证字符串的剩余部分以开头 # ,表示组首选项和映射信息的开头。 验证字符串的这一部分列出组名的顺序 grp1 grp2 grp3 LDAP插件将该列表与LDAP服务器返回的组名称集进行比较,以列表顺序查找与返回的名称匹配的列表。 插件使用第一个匹配,或者如果没有匹配,则认证失败。

假设LDAP服务器返回组 grp3 grp2 grp7 LDAP插件使用 grp2 是因为它是认证字符串中匹配的第一个组,即使它不是LDAP服务器返回的第一个组。 如果LDAP服务器返回 grp4 grp2 grp1 ,插件使用 grp1 即使 grp2 也匹配。 grp1 优先级高于 grp2 认证字符串前面列出 的优先级

假设插件找到了组名匹配,它会执行从该组名到MySQL代理用户名的映射(如果有)。 对于示例代理帐户,映射如下所示:

  • 如果匹配的组名是 grp1 grp3 ,则它们在认证字符串中 分别 与用户名 usera userc 该插件使用相应的关联用户名作为代理用户名。

  • 如果匹配的组名称是 grp2 ,则认证字符串中没有关联的用户名。 该插件 grp2 用作代理用户名。

如果LDAP服务器以DN格式返回组,则LDAP插件会解析组DN以从中提取组名称。

要指定LDAP组首选项和映射信息,这些原则适用:

  • 开始组首选项并使用 # 前缀字符 映射身份验证字符串的一部分

  • 组首选项和映射规范是一个或多个项目的列表,以逗号分隔。 每个项目都有表格 项目应按组名称首选项顺序列出。 对于插件选择的组名称作为LDAP服务器返回的组名称集合,这两种语法的效果如下: group_name=user_name group_name

    • 对于指定为 (具有用户名)的项目,组名称映射到用户名,该用户名用作MySQL代理用户名。 group_name=user_name

    • 对于指定为 group_name (没有用户名)的项目,组名称用作MySQL代理用户名。

  • 要引用包含特殊字符(如空格)的组或用户名,请用双引号( " )字符将其括起来。 例如,如果项目的组和用户名为 my group name my user name ,则必须使用引号将其写入组映射中:

    “我的群组名称”=“我的用户名”
    

    如果项目的组和用户名称 my_group_name my_user_name (其中不包含特殊字符),它可能但不一定使用引号写入。 以下任何一项都是有效的:

    my_group_name = my_user_name
    my_group_name = “my_user_name”
    “my_group_name”= my_user_name
    “my_group_name”= “my_user_name”
    
  • 要转义字符,请在其前面加一个反斜杠( \ )。 这特别适用于包含文字双引号或反斜杠,否则不包括字面意思。

  • 验证字符串中不需要存在用户DN,但如果存在,则它必须位于组首选项和映射部分之前。 用户DN可以是完整用户DN,也可以是带有 + 前缀字符 的用户DN后缀

6.4.1.8无登录可插入认证

mysql_no_login 服务器端身份验证插件阻止所有客户端连接到使用它的任何账户。 此类插件的用例包括代理帐户,这些帐户永远不允许直接登录,但只能通过代理帐户和帐户访问,这些帐户和帐户必须能够以提升的权限执行存储的程序和视图,而不会将这些权限暴露给普通用户。

下表显示了插件和库文件名。 文件名后缀可能与您的系统不同。 该文件必须位于 plugin_dir 系统变量 指定的目录中

表6.20无登录身份验证的插件和库名称

插件或文件 插件或文件名
服务器端插件 mysql_no_login
客户端插件 没有
库文件 mysql_no_login.so

以下部分提供了特定于无登录可插入身份验证的安装和使用信息:

有关MySQL中可插入身份验证的一般信息,请参见 第6.2.17节“可插入身份验证” 有关代理用户信息,请参见 第6.2.18节“代理用户”

安装无登录可插入身份验证

本节介绍如何安装无登录身份验证插件。 有关安装插件的一般信息,请参见 第5.6.1节“安装和卸载插件”

要使服务器可以使用,插件库文件必须位于MySQL插件目录( plugin_dir 系统变量 指定的目录 )中。 如有必要,通过设置 plugin_dir 服务器启动时 的值来配置插件目录位置

插件库文件基本名称是 mysql_no_login 文件名后缀因平台 .so 而异 (例如, 对于Unix和类Unix系统, .dll 对于Windows)。

要在服务器启动时加载插件,请使用该 --plugin-load-add 选项命名包含它的库文件。 使用此插件加载方法,每次服务器启动时都必须提供该选项。 例如,将这些行放在服务器 my.cnf 文件中( .so 根据需要 调整 平台 后缀):

的[mysqld]
插件的负载加= mysql_no_login.so

修改后 my.cnf ,重新启动服务器以使新设置生效。

或者,要在运行时注册插件,请使用此语句( .so 根据需要 调整 后缀):

INSTALL PLUGIN mysql_no_login SONAME'mysql_no_login.so';

INSTALL PLUGIN 立即加载插件,并将其注册到 mysql.plugins 系统表中,以使服务器为每个后续的正常启动加载它。

要验证插件安装,请检查 INFORMATION_SCHEMA.PLUGINS 表或使用该 SHOW PLUGINS 语句(请参见 第5.6.2节“获取服务器插件信息” )。 例如:

MySQL的> SELECT PLUGIN_NAME, PLUGIN_STATUS
       FROM INFORMATION_SCHEMA.PLUGINS
       WHERE PLUGIN_NAME LIKE '%login%';
+ ---------------- + --------------- +
| PLUGIN_NAME | PLUGIN_STATUS |
+ ---------------- + --------------- +
| mysql_no_login | ACTIVE |
+ ---------------- + --------------- +

如果插件无法初始化,请检查服务器错误日志以获取诊断消息。

要将MySQL帐户与no-login插件关联,请参阅 使用无登录可插入身份验证

卸载无登录可插入身份验证

用于卸载无登录身份验证插件的方法取决于您的安装方式:

  • 如果您在服务器启动时使用 --plugin-load-add 选项 安装了插件,请在 没有该选项的情况下重新启动服务器。

  • 如果您在运行时使用安装插件 INSTALL PLUGIN ,它将在服务器重新启动 保持安装。 要卸载它,请使用 UNINSTALL PLUGIN

    UNINSTALL PLUGIN mysql_no_login;
    
使用无登录可插入身份验证

本节介绍如何使用禁用登录身份验证插件来阻止从MySQL客户端程序到服务器的连接。 假设服务器在启用服务器端插件的情况下运行,如 安装无登录可插入身份验证中所述

要在 语句 IDENTIFIED WITH 子句中 引用无登录身份验证插件 CREATE USER ,请使用该名称 mysql_no_login

使用身份验证的帐户 mysql_no_login 可以用作 DEFINER 存储的程序和视图对象。 如果此类对象定义还包括 SQL SECURITY DEFINER ,则使用该帐户的权限执行。 DBA可以使用此行为来提供对仅通过良好控制的接口公开的机密或敏感数据的访问。

以下示例简要说明了这些原则。 它定义了一个不允许客户端连接的帐户,并将与之关联的视图仅公开 mysql.user 系统表的 某些列

创建数据库nologindb;
创建用户'nologin'@'localhost'
  用mysql_no_login识别;
全部授权nologindb。*
  TO'nologin'@'localhost';
在mysql.user上选择GRANT
  TO'nologin'@'localhost';
CREATE DEFINER ='nologin'@'localhost'
  SQL安全定义器
  查看nologindb.myview
  AS SELECT用户,主机FROM mysql.user;

要为普通用户提供对视图的受保护访问,请执行以下操作:

在nologindb.myview上选择GRANT
  到'普通用户'@'localhost';

现在,普通用户可以使用该视图访问它所呈现的有限信息:

SELECT * FROM nologindb.myview;

用户尝试访问除视图公开的列以外的列会导致错误,所有尝试从未授予对其访问权限的用户中选择视图也是如此。

注意

由于 nologin 无法直接使用 帐户,因此设置其使用的对象所需的操作必须由 root 具有创建对象和设置 DEFINER 所需特权的帐户或类似帐户 执行

使用身份验证的帐户 mysql_no_login 可以用作代理帐户的代理基本用户:

- 创建代理帐户
创建用户'proxy_base'@'localhost'
  用mysql_no_login识别;
- 授予代理帐户的权限
格兰特......
  上 ...
  到'proxy_base'@'localhost';
- 允许real_user成为代理帐户的代理帐户
授予代理权
  在'proxy_base'@'localhost'
  到'real_user'@'localhost';

这使客户端能够通过代理帐户( real_user 访问MySQL, 但不能通过直接连接代理用户( proxy_base 来绕过代理机制

6.4.1.9套接字对等证书可插入认证

服务器端 auth_socket 身份验证插件对通过Unix套接字文件从本地主机连接的客户 端进行 身份验证。 该插件使用 SO_PEERCRED 套接字选项来获取有关运行客户端程序的用户的信息。 因此,该插件只能用于支持该 SO_PEERCRED 选项的 系统 ,例如Linux。

可以将此插件的源代码作为一个相对简单的示例进行检查,演示如何编写可加载的身份验证插件。

下表显示了插件和库文件名。 该文件必须位于 plugin_dir 系统变量 指定的目录中

表6.21套接字对等凭证认证的插件和库名称

插件或文件 插件或文件名
服务器端插件 auth_socket
客户端插件 没有,请参阅讨论
库文件 auth_socket.so

以下部分提供了特定于套接字可插入身份验证的安装和使用信息:

有关MySQL中可插入身份验证的一般信息,请参见 第6.2.17节“可插入身份验证”

安装套接字可插入身份验证

本节介绍如何安装套接字认证插件。 有关安装插件的一般信息,请参见 第5.6.1节“安装和卸载插件”

要使服务器可以使用,插件库文件必须位于MySQL插件目录( plugin_dir 系统变量 指定的目录 )中。 如有必要,通过设置 plugin_dir 服务器启动时 的值来配置插件目录位置

要在服务器启动时加载插件,请使用该 --plugin-load-add 选项命名包含它的库文件。 使用此插件加载方法,每次服务器启动时都必须提供该选项。 例如,将这些行放在服务器 my.cnf 文件中:

的[mysqld]
插件的负载加= auth_socket.so

修改后 my.cnf ,重新启动服务器以使新设置生效。

或者,要在运行时注册插件,请使用以下语句:

INSTALL PLUGIN auth_socket SONAME'auth_socket.so';

INSTALL PLUGIN 立即加载插件,并将其注册到 mysql.plugins 系统表中,以使服务器为每个后续的正常启动加载它。

要验证插件安装,请检查 INFORMATION_SCHEMA.PLUGINS 表或使用该 SHOW PLUGINS 语句(请参见 第5.6.2节“获取服务器插件信息” )。 例如:

MySQL的> SELECT PLUGIN_NAME, PLUGIN_STATUS
       FROM INFORMATION_SCHEMA.PLUGINS
       WHERE PLUGIN_NAME LIKE '%socket%';
+ ------------- + --------------- +
| PLUGIN_NAME | PLUGIN_STATUS |
+ ------------- + --------------- +
| auth_socket | ACTIVE |
+ ------------- + --------------- +

如果插件无法初始化,请检查服务器错误日志以获取诊断消息。

要将MySQL帐户与套接字插件关联,请参阅 使用套接字可插入身份验证

卸载套接字可插入身份验证

用于卸载套接字认证插件的方法取决于您的安装方式:

  • 如果您在服务器启动时使用 --plugin-load-add 选项 安装了插件,请在 没有该选项的情况下重新启动服务器。

  • 如果您在运行时使用安装插件 INSTALL PLUGIN ,它将在服务器重新启动 保持安装。 要卸载它,请使用 UNINSTALL PLUGIN

    UNINSTALL PLUGIN auth_socket;
    
使用套接字可插入身份验证

套接字插件检查套接字用户名(操作系统用户名)是否与客户端程序为服务器指定的MySQL用户名匹配。 如果名称不匹配,插件将检查套接字用户名是否 authentication_string mysql.user 系统表行 列中 指定的名称匹配 如果找到匹配项,则插件允许连接。 authentication_string 可以使用 IDENTIFIED ...AS CREATE USER 子句 指定 ALTER USER

假设为一个操作系统用户创建了一个MySQL帐户,该用户将 valerie 通过 auth_socket 插件对本地主机通过套接字文件进行连接 进行身份验证

创建用户'valerie'@'localhost'用auth_socket识别;

如果本地主机上具有登录名 的用户使用通过套接字文件连接 的选项 stefanie 调用 mysql --user=valerie ,则服务器将使用该服务器 auth_socket 对客户端进行身份验证。 插件确定 --user 选项value( valerie )与客户端用户的名称( stephanie )不同并拒绝连接。 如果名为的用户 valerie 尝试相同的操作,则插件会发现用户名和MySQL用户名都是 valerie 并且允许连接。 但是,即使 valerie 连接是使用不同的协议(如TCP / IP)进行 连接,插件也会拒绝连接

要允许 valerie stephanie 操作系统用户通过使用该帐户的套接字文件连接访问MySQL,可以通过两种方式完成:

  • 在帐户创建时为一个用户命名,一个跟随 CREATE USER ,另一个在认证字符串中:

    创建用户'valerie'@'localhost'用auth_socket AS'stephanie'识别;
    
  • 如果您已经习惯 CREATE USER 为单个用户创建帐户,请使用 ALTER USER 添加第二个用户:

    创建用户'valerie'@'localhost'用auth_socket识别;
    ALTER USER'valerie'@'localhost'用auth_socket AS'stephanie'识别;
    

要访问帐户都 valerie stephanie 指定 --user=valerie 在连接时。

6.4.1.10测试可插拔认证

MySQL包含一个测试插件,用于检查帐户凭据并将成功或失败记录到服务器错误日志中。 这是一个可加载的插件(未内置),必须在使用前安装。

测试插件源代码与服务器源分开,与内置本机插件不同,因此可以将其作为一个相对简单的示例进行检查,演示如何编写可加载的身份验证插件。

注意

此插件用于测试和开发目的,不适用于生产环境或公共网络上的服务器。

下表显示了插件和库文件名。 文件名后缀可能与您的系统不同。 该文件必须位于 plugin_dir 系统变量 指定的目录中

表6.22测试验证的插件和库名称

插件或文件 插件或文件名
服务器端插件 test_plugin_server
客户端插件 auth_test_plugin
库文件 auth_test_plugin.so

以下部分提供了特定于测试可插入身份验证的安装和使用信息:

有关MySQL中可插入身份验证的一般信息,请参见 第6.2.17节“可插入身份验证”

安装测试可插拔认证

本节介绍如何安装测试身份验证插件。 有关安装插件的一般信息,请参见 第5.6.1节“安装和卸载插件”

要使服务器可以使用,插件库文件必须位于MySQL插件目录( plugin_dir 系统变量 指定的目录 )中。 如有必要,通过设置 plugin_dir 服务器启动时 的值来配置插件目录位置

要在服务器启动时加载插件,请使用该 --plugin-load-add 选项命名包含它的库文件。 使用此插件加载方法,每次服务器启动时都必须提供该选项。 例如,将这些行放在服务器 my.cnf 文件中( .so 根据需要 调整 平台 后缀):

的[mysqld]
插件的负载加= auth_test_plugin.so

修改后 my.cnf ,重新启动服务器以使新设置生效。

或者,要在运行时注册插件,请使用此语句( .so 根据需要 调整 后缀):

INSTALL PLUGIN test_plugin_server SONAME'auth_test_plugin.so';

INSTALL PLUGIN 立即加载插件,并将其注册到 mysql.plugins 系统表中,以使服务器为每个后续的正常启动加载它。

要验证插件安装,请检查 INFORMATION_SCHEMA.PLUGINS 表或使用该 SHOW PLUGINS 语句(请参见 第5.6.2节“获取服务器插件信息” )。 例如:

MySQL的> SELECT PLUGIN_NAME, PLUGIN_STATUS
       FROM INFORMATION_SCHEMA.PLUGINS
       WHERE PLUGIN_NAME LIKE '%test_plugin%';
+ -------------------- + --------------- +
| PLUGIN_NAME | PLUGIN_STATUS |
+ -------------------- + --------------- +
| test_plugin_server | ACTIVE |
+ -------------------- + --------------- +

如果插件无法初始化,请检查服务器错误日志以获取诊断消息。

要将MySQL帐户与测试插件相关联,请参阅 使用测试可插入身份验证

卸载测试可插拔身份验证

用于卸载测试身份验证插件的方法取决于您的安装方式:

  • 如果您在服务器启动时使用 --plugin-load-add 选项 安装了插件,请在 没有该选项的情况下重新启动服务器。

  • 如果您在运行时使用安装插件 INSTALL PLUGIN ,它将在服务器重新启动 保持安装。 要卸载它,请使用 UNINSTALL PLUGIN

    UNINSTALL PLUGIN test_plugin_server;
    
使用测试可插入身份验证

要使用测试身份验证插件,请在 IDENTIFIED WITH 子句中 创建一个帐户并命名该插件

创建用户'testuser'@'localhost'
使用test_plugin_server识别
BY' testpassword';

然后 在连接到服务器时为该帐户 提供 --user --password 选项。 例如:

shell> mysql --user=testuser --password
输入密码:testpassword

插件从客户端获取密码,并将其与 系统表中 authentication_string 帐户行列中 存储的值进行比较 mysql.user 如果两个值匹配,则插件将该 authentication_string 值作为新的有效用户ID返回。

您可以在服务器错误日志中查找指示验证是否成功的消息(请注意密码是否报告为 用户 ):

[注意]插件test_plugin_server报告:
'成功验证用户testpassword'

6.4.1.11可插拔认证系统变量

除非安装了适当的服务器端插件,否则这些变量不可用:

  • authentication_ldap_sasl 对于具有表单名称的系统变量 authentication_ldap_sasl_xxx

  • authentication_ldap_simple 对于具有表单名称的系统变量 authentication_ldap_simple_xxx

表6.23身份验证插件系统变量摘要

名称 CMD线 选项文件 系统变量 状态变量 Var范围 动态
authentication_ldap_sasl_auth_method_name 全球
authentication_ldap_sasl_bind_base_dn 全球
authentication_ldap_sasl_bind_root_dn 全球
authentication_ldap_sasl_bind_root_pwd 全球
authentication_ldap_sasl_ca_path 全球
authentication_ldap_sasl_group_search_attr 全球
authentication_ldap_sasl_group_search_filter 全球
authentication_ldap_sasl_init_pool_size 全球
authentication_ldap_sasl_log_status 全球
authentication_ldap_sasl_max_pool_size 全球
authentication_ldap_sasl_server_host 全球
authentication_ldap_sasl_server_port 全球
authentication_ldap_sasl_tls 全球
authentication_ldap_sasl_user_search_attr 全球
authentication_ldap_simple_auth_method_name 全球
authentication_ldap_simple_bind_base_dn 全球
authentication_ldap_simple_bind_root_dn 全球
authentication_ldap_simple_bind_root_pwd 全球
authentication_ldap_simple_ca_path 全球
authentication_ldap_simple_group_search_attr 全球
authentication_ldap_simple_group_search_filter 全球
authentication_ldap_simple_init_pool_size 全球
authentication_ldap_simple_log_status 全球
authentication_ldap_simple_max_pool_size 全球
authentication_ldap_simple_server_host 全球
authentication_ldap_simple_server_port 全球
authentication_ldap_simple_tls 全球
authentication_ldap_simple_user_search_attr 全球
authentication_windows_log_level 全球 没有
authentication_windows_use_principal_name 全球 没有

  • authentication_ldap_sasl_auth_method_name

    属性
    命令行格式 --authentication-ldap-sasl-auth-method-name=value
    介绍 8.0.11
    系统变量 authentication_ldap_sasl_auth_method_name
    范围 全球
    动态
    SET_VAR 提示适用 没有
    类型
    默认值 SCRAM-SHA-1

    对于SASL LDAP身份验证,请使用身份验证方法名称。 认证插件和LDAP服务器之间的通信根据此认证方法进行。 允许使用以下身份验证方法值:

    • SCRAM-SHA-1 :身份验证使用SASL质询 - 响应机制来确保密码安全性。

      客户端 authentication_ldap_sasl_client 插件与SASL服务器通信,使用密码创建质询并获取SASL请求缓冲区,然后将此缓冲区传递给服务器端 authentication_ldap_sasl 插件。 客户端和服务器端SASL LDAP插件使用SASL消息在LDAP协议中安全传输凭据,以避免在MySQL客户端和服务器之间发送明文密码。

  • authentication_ldap_sasl_bind_base_dn

    属性
    命令行格式 --authentication-ldap-sasl-bind-base-dn=value
    介绍 8.0.11
    系统变量 authentication_ldap_sasl_bind_base_dn
    范围 全球
    动态
    SET_VAR 提示适用 没有
    类型
    默认值 NULL

    对于SASL LDAP身份验证,基本专有名称(DN)。 此变量可用于通过将搜索范围锚定在 搜索树 中的特定位置( 基础 来限制搜索范围

    假设一组LDAP用户条目的成员都具有以下形式:

    uid = user_name,ou = People,dc = example,dc = com
    

    另一组LDAP用户条目的成员每个都有这种形式:

    uid = user_name,ou = Admin,dc = example,dc = com
    

    然后搜索工作类似于不同的基本DN值:

    • 如果基本DN为 ou=People,dc=example,dc=com :搜索仅在第一组中查找用户条目。

    • 如果基本DN为 ou=Admin,dc=example,dc=com :搜索仅在第二组中查找用户条目。

    • 如果基本DN是 ou=dc=example,dc=com :搜索在第一组或第二组中查找用户条目。

    通常,更具体的基本DN值会导致更快的搜索,因为它们会更多地限制搜索范围。

  • authentication_ldap_sasl_bind_root_dn

    属性
    命令行格式 --authentication-ldap-sasl-bind-root-dn=value
    介绍 8.0.11
    系统变量 authentication_ldap_sasl_bind_root_dn
    范围 全球
    动态
    SET_VAR 提示适用 没有
    类型
    默认值 NULL

    对于SASL LDAP身份验证,根据可分辨名称(DN)。 此变量与 authentication_ldap_sasl_bind_root_pwd 作为用于对LDAP服务器进行身份验证的凭据 结合使用 ,以执行搜索。 身份验证使用一个或两个LDAP绑定操作,具体取决于MySQL帐户是否为LDAP用户DN命名:

    • 如果帐户未命名用户DN: authentication_ldap_sasl 使用 authentication_ldap_sasl_bind_root_dn 执行初始LDAP绑定 authentication_ldap_sasl_bind_root_pwd (默认情况下这些都是空的,因此如果未设置它们,LDAP服务器必须允许匿名连接。)生成的绑定LDAP句柄用于根据客户端用户名搜索用户DN。 authentication_ldap_sasl 使用用户DN和客户端提供的密码执行第二次绑定。

    • 如果该帐户确实为用户DN命名:在这种情况下,不需要第一次绑定操作。 authentication_ldap_sasl 使用用户DN和客户端提供的密码执行单个绑定。 这比MySQL帐户未指定LDAP用户DN更快。

  • authentication_ldap_sasl_bind_root_pwd

    属性
    命令行格式 --authentication-ldap-sasl-bind-root-pwd=value
    介绍 8.0.11
    系统变量 authentication_ldap_sasl_bind_root_pwd
    范围 全球
    动态
    SET_VAR 提示适用 没有
    类型
    默认值 NULL

    对于SASL LDAP身份验证,为根专有名称的密码。 此变量与 authentication_ldap_sasl_bind_root_dn 一起使用 请参阅该变量的说明。

  • authentication_ldap_sasl_ca_path

    属性
    命令行格式 --authentication-ldap-sasl-ca-path=value
    介绍 8.0.11
    系统变量 authentication_ldap_sasl_ca_path
    范围 全球
    动态
    SET_VAR 提示适用 没有
    类型
    默认值 NULL

    对于SASL LDAP身份验证,证书颁发机构文件的绝对路径。 如果希望身份验证插件执行LDAP服务器证书的验证,请指定此文件。

    注意

    除了将 authentication_ldap_sasl_ca_path 变量 设置为 文件名之外,还必须将相应的证书颁发机构证书添加到文件中并启用 authentication_ldap_sasl_tls 系统变量。

  • authentication_ldap_sasl_group_search_attr

    属性
    命令行格式 --authentication-ldap-sasl-group-search-attr=value
    介绍 8.0.11
    系统变量 authentication_ldap_sasl_group_search_attr
    范围 全球
    动态
    SET_VAR 提示适用 没有
    类型
    默认值 cn

    对于SASL LDAP身份验证,指定LDAP目录条目中的组名称的属性的名称。 如果 authentication_ldap_sasl_group_search_attr 其默认值为 cn ,则搜索将 cn 值作为组名 返回 例如,如果有一个LDAP项 uid 的值 user1 具有 cn 的属性 mygroup ,搜索 user1 返回 mygroup 的组名。

    如果不需要组或代理身份验证,则此变量应为空字符串。

    如果是组搜索属性 isMemberOf ,则LDAP身份验证直接检索用户属性 isMemberOf 值并将其指定为组信息。 如果组搜索属性不是 isMemberOf ,则LDAP身份验证将搜索用户所属的所有组。 (后者是默认行为。)此行为基于如何以两种方式存储LDAP组信息:1)组条目可以具有名为 memberUid member 具有用户名的值 的属性 ; 2)用户条目可以具有以 isMemberOf 组名称 命名的属性

  • authentication_ldap_sasl_group_search_filter

    属性
    命令行格式 --authentication-ldap-sasl-group-search-filter=value
    介绍 8.0.11
    系统变量 authentication_ldap_sasl_group_search_filter
    范围 全球
    动态
    SET_VAR 提示适用 没有
    类型
    默认值 (|(&(objectClass=posixGroup)(memberUid=%s))(&(objectClass=group)(member=%s)))

    对于SASL LDAP身份验证,自定义组搜索筛选器。

    搜索过滤器值可以包含 {UA} {UD} 表示用户名和完整用户DN。 例如, {UA} 用诸如的用户名 替换 "admin" ,而 {UD} 替换为使用完整的DN,例如 "uid=admin,ou=People,dc=example,dc=com" 以下值是默认值,它支持OpenLDAP和Active Directory:

    (|(&(objectClass的= posixGroup)(memberUid = {UA}))
      (&(objectClass的=基团)(成员= {} UD)))
    

    在某些情况下,对于用户场景, memberOf 是一个不包含组信息的简单用户属性。 为了提高灵活性,可选 {GA} 前缀可与组搜索属性一起使用。 具有{GA}前缀的任何组属性都被视为具有组名的用户属性。 例如,值为 {GA}MemberOf ,如果组值是DN,则返回组DN中的第一个属性值作为组名。

  • authentication_ldap_sasl_init_pool_size

    属性
    命令行格式 --authentication-ldap-sasl-init-pool-size=#
    介绍 8.0.11
    系统变量 authentication_ldap_sasl_init_pool_size
    范围 全球
    动态
    SET_VAR 提示适用 没有
    类型 整数
    默认值 10
    最低价值 0
    最大价值 32767

    对于SASL LDAP身份验证,LDAP服务器连接池的初始大小。 根据LDAP服务器的平均并发身份验证请求数选择此变量的值。

    该插件使用 authentication_ldap_sasl_init_pool_size authentication_ldap_sasl_max_pool_size 一起进行连接池管理:

    对插件系统变量设置的更改可能对池中已有的连接没有影响。 例如,修改LDAP服务器主机,端口或TLS设置不会影响现有连接。 但是,如果原始变量值无效且无法初始化连接池,则插件会尝试为下一个LDAP请求重新初始化池。 在这种情况下,新的系统变量值用于重新初始化尝试。

    如果 authentication_ldap_sasl_max_pool_size=0 要禁用池,则插件打开的每个LDAP连接都使用系统变量当时具有的值。

  • authentication_ldap_sasl_log_status

    属性
    命令行格式 --authentication-ldap-sasl-log-status=#
    介绍 8.0.11
    系统变量 authentication_ldap_sasl_log_status
    范围 全球
    动态
    SET_VAR 提示适用 没有
    类型 整数
    默认值 1
    最低价值 1
    最大价值 5

    对于SASL LDAP身份验证,请记录级别。 下表显示了允许的级别值及其含义。

    表6.24 authentication_ldap_sasl_log_status的日志级别

    期权价值 记录的消息类型
    1 没有消息
    2 错误消息
    3 错误和警告消息
    4 错误,警告和信息消息
    5 所有消息

    在客户端,可以通过设置 AUTHENTICATION_LDAP_CLIENT_LOG 环境变量 将消息记录到标准输出 允许值和默认值与for相同 authentication_ldap_sasl_log_status

    AUTHENTICATION_LDAP_CLIENT_LOG 环境变量仅适用于SASL LDAP认证。 它对简单的LDAP身份验证没有影响,因为在这种情况下客户端插件是 mysql_clear_password ,它对LDAP操作一无所知。

  • authentication_ldap_sasl_max_pool_size

    属性
    命令行格式 --authentication-ldap-sasl-max-pool-size=#
    介绍 8.0.11
    系统变量 authentication_ldap_sasl_max_pool_size
    范围 全球
    动态
    SET_VAR 提示适用 没有
    类型 整数
    默认值 1000
    最低价值 0
    最大价值 32767

    对于SASL LDAP身份验证,LDAP服务器连接池的最大大小。 要禁用连接池,请将此变量设置为0。

    此变量与 authentication_ldap_sasl_init_pool_size 一起使用 请参阅该变量的说明。

  • authentication_ldap_sasl_server_host

    属性
    命令行格式 --authentication-ldap-sasl-server-host=host_name
    介绍 8.0.11
    系统变量 authentication_ldap_sasl_server_host
    范围 全球
    动态
    SET_VAR 提示适用 没有
    类型

    对于SASL LDAP身份验证,LDAP服务器主机。 此变量的允许值取决于身份验证方法:

  • authentication_ldap_sasl_server_port

    属性
    命令行格式 --authentication-ldap-sasl-server-port=port_num
    介绍 8.0.11
    系统变量 authentication_ldap_sasl_server_port
    范围 全球
    动态
    SET_VAR 提示适用 没有
    类型 整数
    默认值 389
    最低价值 1
    最大价值 32376

    对于SASL LDAP身份验证,LDAP服务器TCP / IP端口号。

    从MySQL 8.0.14开始,如果LDAP端口号配置为636或3269,则插件使用LDAPS(LDAP over SSL)而不是LDAP。 (LDAPS与 startTLS 不同 。)

  • authentication_ldap_sasl_tls

    属性
    命令行格式 --authentication-ldap-sasl-tls[={OFF|ON}]
    介绍 8.0.11
    系统变量 authentication_ldap_sasl_tls
    范围 全球
    动态
    SET_VAR 提示适用 没有
    类型 布尔
    默认值 OFF

    对于SASL LDAP身份验证,插件与LDAP服务器的连接是否安全。 如果启用此变量,则插件使用TLS安全地连接到LDAP服务器。 如果启用此变量,您可能还希望设置 authentication_ldap_sasl_ca_path 变量。

    MySQL LDAP插件支持StartTLS方法,该方法在普通LDAP连接之上初始化TLS。 ldaps 方法已弃用,MySQL不支持它。

  • authentication_ldap_sasl_user_search_attr

    属性
    命令行格式 --authentication-ldap-sasl-user-search-attr=value
    介绍 8.0.11
    系统变量 authentication_ldap_sasl_user_search_attr
    范围 全球
    动态
    SET_VAR 提示适用 没有
    类型
    默认值 uid

    对于SASL LDAP身份验证,指定LDAP目录条目中的用户名的属性的名称。 如果未提供用户专有名称,则认证插件将使用此属性搜索名称。 例如,如果 authentication_ldap_sasl_user_search_attr 值为 uid ,则搜索用户名会 user1 查找 uid 值为的 条目 user1

  • authentication_ldap_simple_auth_method_name

    属性
    命令行格式 --authentication-ldap-simple-auth-method-name=value
    介绍 8.0.11
    系统变量 authentication_ldap_simple_auth_method_name
    范围 全球
    动态
    SET_VAR 提示适用 没有
    类型
    默认值 SIMPLE

    对于简单LDAP身份验证,身份验证方法名称。 认证插件和LDAP服务器之间的通信根据此认证方法进行。 允许使用以下身份验证方法值:

    • SIMPLE :此身份验证方法使用一个或两个LDAP绑定操作,具体取决于MySQL帐户是否命名LDAP用户可分辨名称。 请参阅说明 authentication_ldap_simple_bind_root_dn

    • AD-FOREST authentication_ldap_simple 搜索Active Directory林中的所有域,对每个Active Directory域执行LDAP绑定,直到在某个域中找到该用户。

    注意

    对于简单的LDAP身份验证,建议还要将TLS参数设置为要求与LDAP服务器的通信通过安全连接进行。

  • authentication_ldap_simple_bind_base_dn

    属性
    命令行格式 --authentication-ldap-simple-bind-base-dn=value
    介绍 8.0.11
    系统变量 authentication_ldap_simple_bind_base_dn
    范围 全球
    动态
    SET_VAR 提示适用 没有
    类型
    默认值 NULL

    对于简单LDAP身份验证,基本专有名称(DN)。 此变量可用于通过将搜索范围锚定在 搜索树 中的特定位置( 基础 来限制搜索范围

    假设一组LDAP用户条目的成员都具有以下形式:

    uid = user_name,ou = People,dc = example,dc = com
    

    另一组LDAP用户条目的成员每个都有这种形式:

    uid = user_name,ou = Admin,dc = example,dc = com
    

    然后搜索工作类似于不同的基本DN值:

    • 如果基本DN为 ou=People,dc=example,dc=com :搜索仅在第一组中查找用户条目。

    • 如果基本DN为 ou=Admin,dc=example,dc=com :搜索仅在第二组中查找用户条目。

    • 如果基本DN是 ou=dc=example,dc=com :搜索在第一组或第二组中查找用户条目。

    通常,更具体的基本DN值会导致更快的搜索,因为它们会更多地限制搜索范围。

  • authentication_ldap_simple_bind_root_dn

    属性
    命令行格式 --authentication-ldap-simple-bind-root-dn=value
    介绍 8.0.11
    系统变量 authentication_ldap_simple_bind_root_dn
    范围 全球
    动态
    SET_VAR 提示适用 没有
    类型
    默认值 NULL

    对于简单LDAP身份验证,根专有名称(DN)。 此变量与 authentication_ldap_simple_bind_root_pwd 作为用于对LDAP服务器进行身份验证的凭据 结合使用 ,以执行搜索。 身份验证使用一个或两个LDAP绑定操作,具体取决于MySQL帐户是否为LDAP用户DN命名:

    • 如果帐户未命名用户DN: authentication_ldap_simple 使用 authentication_ldap_simple_bind_root_dn 执行初始LDAP绑定 authentication_ldap_simple_bind_root_pwd (默认情况下这些都是空的,因此如果未设置它们,LDAP服务器必须允许匿名连接。)生成的绑定LDAP句柄用于根据客户端用户名搜索用户DN。 authentication_ldap_simple 使用用户DN和客户端提供的密码执行第二次绑定。

    • 如果该帐户确实为用户DN命名:在这种情况下,不需要第一次绑定操作。 authentication_ldap_simple 使用用户DN和客户端提供的密码执行单个绑定。 这比MySQL帐户未指定LDAP用户DN更快。

  • authentication_ldap_simple_bind_root_pwd

    属性
    命令行格式 --authentication-ldap-simple-bind-root-pwd=value
    介绍 8.0.11
    系统变量 authentication_ldap_simple_bind_root_pwd
    范围 全球
    动态
    SET_VAR 提示适用 没有
    类型
    默认值 NULL

    对于简单LDAP身份验证,根专有名称的密码。 此变量与 authentication_ldap_simple_bind_root_dn 一起使用 请参阅该变量的说明。

  • authentication_ldap_simple_ca_path

    属性
    命令行格式 --authentication-ldap-simple-ca-path=value
    介绍 8.0.11
    系统变量 authentication_ldap_simple_ca_path
    范围 全球
    动态
    SET_VAR 提示适用 没有
    类型
    默认值 NULL

    对于简单LDAP身份验证,证书颁发机构文件的绝对路径。 如果希望身份验证插件执行LDAP服务器证书的验证,请指定此文件。

    注意

    除了将 authentication_ldap_simple_ca_path 变量 设置为 文件名之外,还必须将相应的证书颁发机构证书添加到文件中并启用 authentication_ldap_simple_tls 系统变量。

  • authentication_ldap_simple_group_search_attr

    属性
    命令行格式 --authentication-ldap-simple-group-search-attr=value
    介绍 8.0.11
    系统变量 authentication_ldap_simple_group_search_attr
    范围 全球
    动态
    SET_VAR 提示适用 没有
    类型
    默认值 cn

    对于简单LDAP身份验证,指定LDAP目录条目中的组名称的属性的名称。 如果 authentication_ldap_simple_group_search_attr 其默认值为 cn ,则搜索将 cn 值作为组名 返回 例如,如果有一个LDAP项 uid 的值 user1 具有 cn 的属性 mygroup ,搜索 user1 返回 mygroup 的组名。

    如果是组搜索属性 isMemberOf ,则LDAP身份验证直接检索用户属性 isMemberOf 值并将其指定为组信息。 如果组搜索属性不是 isMemberOf ,则LDAP身份验证将搜索用户所属的所有组。 (后者是默认行为。)此行为基于如何以两种方式存储LDAP组信息:1)组条目可以具有名为 memberUid member 具有用户名的值 的属性 ; 2)用户条目可以具有以 isMemberOf 组名称 命名的属性

  • authentication_ldap_simple_group_search_filter

    属性
    命令行格式 --authentication-ldap-simple-group-search-filter=value
    介绍 8.0.11
    系统变量 authentication_ldap_simple_group_search_filter
    范围 全球
    动态
    SET_VAR 提示适用 没有
    类型
    默认值 (|(&(objectClass=posixGroup)(memberUid=%s))(&(objectClass=group)(member=%s)))

    对于简单的LDAP身份验证,自定义组搜索过滤器。

    搜索过滤器值可以包含 {UA} {UD} 表示用户名和完整用户DN。 例如, {UA} 用诸如的用户名 替换 "admin" ,而 {UD} 替换为使用完整的DN,例如 "uid=admin,ou=People,dc=example,dc=com" 以下值是默认值,它支持OpenLDAP和Active Directory:

    (|(&(objectClass的= posixGroup)(memberUid = {UA}))
      (&(objectClass的=基团)(成员= {} UD)))
    

    在某些情况下,对于用户场景, memberOf 是一个不包含组信息的简单用户属性。 为了提高灵活性,可选 {GA} 前缀可与组搜索属性一起使用。 具有{GA}前缀的任何组属性都被视为具有组名的用户属性。 例如,值为 {GA}MemberOf ,如果组值是DN,则返回组DN中的第一个属性值作为组名。

  • authentication_ldap_simple_init_pool_size

    属性
    命令行格式 --authentication-ldap-simple-init-pool-size=#
    介绍 8.0.11
    系统变量 authentication_ldap_simple_init_pool_size
    范围 全球
    动态
    SET_VAR 提示适用 没有
    类型 整数
    默认值 10
    最低价值 0
    最大价值 32767

    对于简单LDAP身份验证,LDAP服务器连接池的初始大小。 根据LDAP服务器的平均并发身份验证请求数选择此变量的值。

    该插件使用 authentication_ldap_simple_init_pool_size authentication_ldap_simple_max_pool_size 一起进行连接池管理:

    对插件系统变量设置的更改可能对池中已有的连接没有影响。 例如,修改LDAP服务器主机,端口或TLS设置不会影响现有连接。 但是,如果原始变量值无效且无法初始化连接池,则插件会尝试为下一个LDAP请求重新初始化池。 在这种情况下,新的系统变量值用于重新初始化尝试。

    如果 authentication_ldap_simple_max_pool_size=0 要禁用池,则插件打开的每个LDAP连接都使用系统变量当时具有的值。

  • authentication_ldap_simple_log_status

    属性
    命令行格式 --authentication-ldap-simple-log-status=#
    介绍 8.0.11
    系统变量 authentication_ldap_simple_log_status
    范围 全球
    动态
    SET_VAR 提示适用 没有
    类型 整数
    默认值 1
    最低价值 1
    最大价值 5

    对于简单的LDAP身份验证,请记录级别。 下表显示了允许的级别值及其含义。

    表6.25 authentication_ldap_simple_log_status的日志级别

    期权价值 记录的消息类型
    1 没有消息
    2 错误消息
    3 错误和警告消息
    4 错误,警告和信息消息
    5 所有消息

  • authentication_ldap_simple_max_pool_size

    属性
    命令行格式 --authentication-ldap-simple-max-pool-size=#
    介绍 8.0.11
    系统变量 authentication_ldap_simple_max_pool_size
    范围 全球
    动态
    SET_VAR 提示适用 没有
    类型 整数
    默认值 1000
    最低价值 0
    最大价值 32767

    对于简单LDAP身份验证,LDAP服务器连接池的最大大小。 要禁用连接池,请将此变量设置为0。

    此变量与 authentication_ldap_simple_init_pool_size 一起使用 请参阅该变量的说明。

  • authentication_ldap_simple_server_host

    属性
    命令行格式 --authentication-ldap-simple-server-host=host_name
    介绍 8.0.11
    系统变量 authentication_ldap_simple_server_host
    范围 全球
    动态
    SET_VAR 提示适用 没有
    类型

    对于简单的LDAP身份验证,LDAP服务器主机。 此变量的允许值取决于身份验证方法:

    • 对于 authentication_ldap_simple_auth_method_name=SIMPLE :LDAP服务器主机可以是主机名或IP地址。

    • 为了 authentication_ldap_simple_auth_method_name=AD-FOREST LDAP服务器主机可以是Active Directory域名。 例如,对于LDAP服务器URL ldap://example.mem.local:389 ,服务器名称可以是 mem.local

      Active Directory林设置可以具有多个域(LDAP服务器IP),可以使用DNS发现这些域。 在Unix和类Unix系统上,可能需要一些额外的设置来配置DNS服务器,其中SRV记录指定Active Directory域的LDAP服务器。 假设您的配置具有以下属性:

      • 提供有关Active Directory域的信息的名称服务器具有IP地址 10.172.166.100

      • 该LDAP服务器都有名称 ldap1.mem.local 通过 ldap3.mem.local 和IP地址 10.172.166.101 通过 10.172.166.103

      您希望使用SRV搜索可以发现LDAP服务器。 例如,在命令行中,这样的命令应该列出LDAP服务器:

      host -t SRV _ldap._tcp.mem.local
      

      执行DNS配置,如下所示:

      1. 添加一行以 /etc/resolv.conf 指定提供有关Active Directory域的信息的名称服务器:

        名称服务器10.172.166.100
        
      2. 使用LDAP服务器的SRV记录为名称服务器配置相应的区域文件:

        _ldap._tcp.mem.local。86400 IN SRV 0 100 389 ldap1.mem.local。
        _ldap._tcp.mem.local。86400 IN SRV 0 100 389 ldap2.mem.local。
        _ldap._tcp.mem.local。86400 IN SRV 0 100 389 ldap3.mem.local。
        
      3. /etc/hosts 如果无法解析服务器主机 可能还需要为LDAP服务器指定IP地址 例如,将这样的行添加到文件中:

        10.172.166.101 ldap1.mem.local
        10.172.166.102 ldap2.mem.local
        10.172.166.103 ldap3.mem.local
        

      通过如上所述配置DNS,服务器端LDAP插件可以发现LDAP服务器,并将尝试在所有域中进行身份验证,直到身份验证成功或没有其他服务器。

      Windows不需要如上所述的此类设置。 给定值中的LDAP服务器主机 authentication_ldap_simple_server_host ,Windows LDAP库将搜索所有域并尝试进行身份验证。

  • authentication_ldap_simple_server_port

    属性
    命令行格式 --authentication-ldap-simple-server-port=port_num
    介绍 8.0.11
    系统变量 authentication_ldap_simple_server_port
    范围 全球
    动态
    SET_VAR 提示适用 没有
    类型 整数
    默认值 389
    最低价值 1
    最大价值 32376

    对于简单LDAP身份验证,LDAP服务器TCP / IP端口号。

    从MySQL 8.0.14开始,如果LDAP端口号配置为636或3269,则插件使用LDAPS(LDAP over SSL)而不是LDAP。 (LDAPS与 startTLS 不同 。)

  • authentication_ldap_simple_tls

    属性
    命令行格式 --authentication-ldap-simple-tls[={OFF|ON}]
    介绍 8.0.11
    系统变量 authentication_ldap_simple_tls
    范围 全球
    动态
    SET_VAR 提示适用 没有
    类型 布尔
    默认值 OFF

    对于简单的LDAP身份验证,插件与LDAP服务器的连接是否安全。 如果启用此变量,则插件使用TLS安全地连接到LDAP服务器。 如果启用此变量,您可能还希望设置 authentication_ldap_simple_ca_path 变量。

    MySQL LDAP插件支持StartTLS方法,该方法在普通LDAP连接之上初始化TLS。 ldaps 方法已弃用,MySQL不支持它。

  • authentication_ldap_simple_user_search_attr

    属性
    命令行格式 --authentication-ldap-simple-user-search-attr=value
    介绍 8.0.11
    系统变量 authentication_ldap_simple_user_search_attr
    范围 全球
    动态
    SET_VAR 提示适用 没有
    类型
    默认值 uid

    对于简单LDAP身份验证,指定LDAP目录条目中的用户名的属性的名称。 如果未提供用户专有名称,则认证插件将使用此属性搜索名称。 例如,如果 authentication_ldap_simple_user_search_attr 值为 uid ,则搜索用户名会 user1 查找 uid 值为的 条目 user1

6.4.2连接控制插件

MySQL Server包含一个插件库,使管理员能够在连续几次连接尝试失败后,将服务器响应的延迟时间增加到客户端。 此功能提供了一种威慑力,可以减缓尝试访问MySQL用户帐户的暴力攻击。 插件库包含两个插件:

  • CONNECTION_CONTROL 检查传入连接并根据需要向服务器响应添加延迟。 此插件还公开了可以配置其操作的系统变量以及提供基本监视信息的状态变量。

    CONNECTION_CONTROL 插件使用审计插件接口(请参见 第29.2.4.8节“编写审计插件” )。 为了收集信息,它订阅 MYSQL_AUDIT_CONNECTION_CLASSMASK 事件类,进程 MYSQL_AUDIT_CONNECTION_CONNECT 和子 MYSQL_AUDIT_CONNECTION_CHANGE_USER 事件以检查服务器是否应该在响应客户端连接尝试之前引入延迟。

  • CONNECTION_CONTROL_FAILED_LOGIN_ATTEMPTS 实现一个 INFORMATION_SCHEMA 表,为失败的连接尝试公开更详细的监视信息。

以下部分提供有关连接控件插件安装和配置的信息。 有关该 CONNECTION_CONTROL_FAILED_LOGIN_ATTEMPTS 表的 信息 ,请参见 第25.41.1节“INFORMATION_SCHEMA CONNECTION_CONTROL_FAILED_LOGIN_ATTEMPTS表”

6.4.2.1连接控制插件安装

本节介绍如何安装连接控制插件, CONNECTION_CONTROL 以及 CONNECTION_CONTROL_FAILED_LOGIN_ATTEMPTS 有关安装插件的一般信息,请参见 第5.6.1节“安装和卸载插件”

要使服务器可以使用,插件库文件必须位于MySQL插件目录( plugin_dir 系统变量 指定的目录 )中。 如有必要,通过设置 plugin_dir 服务器启动时 的值来配置插件目录位置

插件库文件基本名称是 connection_control 文件名后缀因平台 .so 而异 (例如, 对于Unix和类Unix系统, .dll 对于Windows)。

要在服务器启动时加载插件,请使用该 --plugin-load-add 选项命名包含它们的库文件。 使用此插件加载方法,每次服务器启动时都必须提供该选项。 例如,将这些行放在服务器 my.cnf 文件中( .so 根据需要 调整 平台 后缀):

的[mysqld]
插件的负载加= connection_control.so

修改后 my.cnf ,重新启动服务器以使新设置生效。

或者,要在运行时注册插件,请使用这些语句( .so 根据需要 调整 后缀):

安装PLUGIN CONNECTION_CONTROL
  SONAME'connection_control.so';
安装PLUGIN CONNECTION_CONTROL_FAILED_LOGIN_ATTEMPTS
  SONAME'connection_control.so';

INSTALL PLUGIN 立即加载插件,并将其注册到 mysql.plugins 系统表中,以使服务器为每个后续的正常启动加载它。

要验证插件安装,请检查 INFORMATION_SCHEMA.PLUGINS 表或使用该 SHOW PLUGINS 语句(请参见 第5.6.2节“获取服务器插件信息” )。 例如:

MySQL的> SELECT PLUGIN_NAME, PLUGIN_STATUS
       FROM INFORMATION_SCHEMA.PLUGINS
       WHERE PLUGIN_NAME LIKE 'connection%';
------------------------------------------ + ------ + --------- +
| PLUGIN_NAME | PLUGIN_STATUS |
------------------------------------------ + ------ + --------- +
| CONNECTION_CONTROL | ACTIVE |
| CONNECTION_CONTROL_FAILED_LOGIN_ATTEMPTS | ACTIVE |
------------------------------------------ + ------ + --------- +

如果插件无法初始化,请检查服务器错误日志以获取诊断消息。

如果插件先前已注册 INSTALL PLUGIN 或已加载 --plugin-load-add ,则可以使用 服务器启动时 --connection-control --connection-control-failed-login-attempts 选项来控制插件激活。 例如,要在启动时加载插件并防止它们在运行时被删除,请使用以下选项:

的[mysqld]
插件的负载加= connection_control.so
连接控制= FORCE_PLUS_PERMANENT
连接控制失败的登录者试图= FORCE_PLUS_PERMANENT

如果希望在没有给定连接控件插件的情况下阻止服务器运行,请使用选项值of FORCE FORCE_PLUS_PERMANENT 强制服务器启动失败,如果插件未成功初始化。

注意

可以安装一个插件而不安装另一个插件,但必须安装这两个插件才能实现完全的连接控制功能。 特别是,仅安装 CONNECTION_CONTROL_FAILED_LOGIN_ATTEMPTS 插件几乎没用,因为没有 CONNECTION_CONTROL 插件提供填充 CONNECTION_CONTROL_FAILED_LOGIN_ATTEMPTS 的数据,从 表中检索将始终为空。

连接延迟配置

为了使您能够配置其操作, CONNECTION_CONTROL 插件公开了几个系统变量:

要完全禁用检查失败的连接尝试,请设置 connection_control_failed_connections_threshold 为零。 如果 connection_control_failed_connections_threshold 非零,则通过许多连续失败的连接尝试,延迟量为零。 此后,延迟量是高于阈值的失败尝试次数乘以 connection_control_min_connection_delay 毫秒。 例如,使用默认值 connection_control_failed_connections_threshold connection_control_min_connection_delay 值分别为3和1000,客户端连续尝试连接失败前三次没有延迟,第四次失败尝试延迟1000毫秒,第五次失败尝试延迟2000毫秒,依此类推允许的最大延迟 connection_control_max_connection_delay

您可以 CONNECTION_CONTROL 在服务器启动或运行时 设置 系统变量。 假设您希望在服务器开始延迟其响应之前允许连续四次失败的连接尝试,并在此之后将每次额外失败的延迟增加1500毫秒。 要在服务器启动时设置相关变量,请将这些行放在服务器 my.cnf 文件中:

的[mysqld]
插件的负载加= connection_control.so
connection_control_failed_connections_threshold = 4
connection_control_min_connection_delay = 1500

要在运行时设置和保持变量,请使用以下语句:

SET PERSIST connection_control_failed_connections_threshold = 4;
SET PERSIST connection_control_min_connection_delay = 1500;

SET PERSIST 设置正在运行的MySQL实例的值。 它还会保存该值,使其用于后续服务器重新启动。 要更改正在运行的MySQL实例的值而不保存它以便后续重新启动,请使用 GLOBAL 关键字而不是 PERSIST 请参见 第13.7.5.1节“变量赋值的SET语法”

connection_control_min_connection_delay connection_control_max_connection_delay 系统变量具有固定的最小和的分别在1000和2147483647,最大值。 此外,每个变量的允许值范围还取决于另一个变量的当前值:

因此,要进行某些配置所需的更改,您可能需要按特定顺序设置变量。 假设当前最小和最大延迟为1000和2000,并且您要将它们设置为3000和5000.您不能先设置 connection_control_min_connection_delay 为3000,因为它大于当前 connection_control_max_connection_delay 值2000.而是设置 connection_control_max_connection_delay 为5000,然后设置 connection_control_min_connection_delay 到3000。

连接失败评估

CONNECTION_CONTROL 安装插件,它会检查连接尝试,并跟踪他们是否成功或失败。 为此,失败的连接尝试是客户端用户和主机与已知的MySQL帐户匹配但是提供的凭据不正确或与任何已知帐户不匹配的连接尝试。

失败连接计数基于每次连接尝试的用户/主机组合。 确定适用的用户名和主机名需要考虑代理并发生如下:

  • 如果客户端用户代理另一个用户,则使用代理用户的信息。 例如,如果 external_user@example.com 代理 proxy_user@example.com ,连接计数使用代理用户 external_user@example.com ,而不是代理用户 proxy_user@example.com 两者都 必须在 系统表中 具有有效条目, external_user@example.com 并且 proxy_user@example.com 必须在 mysql.user 系统表中定义它们之间的代理关系 mysql.proxies_priv (请参见 第6.2.18节“代理用户” )。

  • 如果客户端用户不代理另一个用户,但确实匹配 mysql.user 条目,则计数使用 CURRENT_USER() 与该条目对应 值。 例如,如果 user1 从主机连接 的用户 host1.example.com user1@host1.example.com 条目 匹配 ,则计数使用 user1@host1.example.com 如果用户相匹配的 user1@%.example.com user1@%.com user1@% 进入相反,统计用途 user1@%.example.com user1@%.com 或者 user1@% 分别。

对于刚才描述的情况,连接尝试与某些 mysql.user 条目 匹配 ,请求是成功还是失败取决于客户端是否提供正确的身份验证凭据。 例如,如果客户端提供的密码不正确,则连接尝试失败。

如果连接尝试不匹配任何 mysql.user 条目,则尝试失败。 在这种情况下,没有 CURRENT_USER() 值可用,连接失败计数使用客户端和客户端主机提供的用户名,由服务器确定。 例如,如果客户端尝试 user2 从主机 host2.example.com 以用户 身份进行连接 ,则客户端请求中将提供用户名部分,服务器将确定主机信息。 用于计数的用户/主机组合是 user2@host2.example.com

注意

服务器维护有关哪些客户端主机可能连接到服务器的信息(实质上是 mysql.user 条目 的主机值的并集 )。 如果客户端尝试从任何其他主机进行连接,则服务器会在连接设置的早期阶段拒绝该尝试:

ERROR 1130(HY000):主持人' host_name'不是
允许连接到这个MySQL服务器

因为这种类型的拒绝很早就发生了,所以 CONNECTION_CONTROL 没有看到它,也不计算它。

连接失败监控

要监视失败的连接,请使用以下信息源:

connection_control_failed_connections_threshold 在运行时 为值分配将 所有累积的失败连接计数器重置为零,这具有以下可见效果:

6.4.2.2连接控制系统和状态变量

本节介绍 CONNECTION_CONTROL 插件提供 的系统和状态变量, 以使其配置和监视其操作。

连接控制系统变量

如果 CONNECTION_CONTROL 安装 插件,它会公开这些系统变量:

连接控制状态变量

如果 CONNECTION_CONTROL 安装 插件,则会公开此状态变量:

6.4.3密码验证组件

validate_password 组件用于测试密码并提高安全性。 此组件公开系统变量,使您可以定义密码策略和组件监视的状态变量。

注意

在MySQL 8.0.4中, validate_password 插件重新实现为 validate_password 组件。 以下说明介绍了如何使用组件,而不是插件。 有关使用该插件的说明,请参阅 密码验证插件 的MySQL 5.7参考手册

插件形式 validate_password 仍然可用,但已弃用,将在未来的MySQL版本中删除。 使用该插件的MySQL安装应该转换为使用该组件。 请参见 第6.4.3.3节“转换到密码验证组件”

validate_password 组件实现了这些功能:

例如, validate_password 检查以下语句中的明文密码。 在默认密码策略下,密码要求密码长度至少为8个字符,密码很弱,并且语句产生错误:

MySQL的> ALTER USER USER() IDENTIFIED BY 'abc';
ERROR 1819(HY000):您的密码不符合当前要求
政策要求

未检查指定为散列值的密码,因为原始密码值不可用于检查:

MySQL的> ALTER USER 'jeffrey'@'localhost'
       IDENTIFIED WITH mysql_native_password
       AS '*0D3CED9BEC10A777AEC23CCC353A8C08A633045E';
查询OK,0行受影响(0.01秒)

要配置密码检查,请修改具有表单名称的系统变量 ; 这些是控制密码策略的参数。 请参见 第6.4.3.2节“密码验证选项和变量” validate_password.xxx

如果 validate_password 未安装,则 系统变量不可用,不检查语句中的密码,并且 函数始终返回0.例如,如果未安装插件,则可以为帐户分配短于8个字符的密码。 validate_password.xxx VALIDATE_PASSWORD_STRENGTH()

假设 validate_password 安装后,它会执行三个级别口令检查的: LOW MEDIUM ,和 STRONG 默认是 MEDIUM ; 要改变这一点,修改值 validate_password.policy 策略实施越来越严格的密码测试。 以下描述涉及默认参数值,可以通过更改相应的系统变量来修改这些值。

此外,还 validate_password 支持拒绝与当前会话的有效用户帐户的用户名部分匹配的密码(正向或反向)。 要提供对此功能的控制,请 validate_password 公开一个 validate_password.check_user_name 默认启用 系统变量。

6.4.3.1密码验证组件安装和卸载

本节介绍如何安装和卸载 validate_password 密码验证组件。 有关安装和卸载组件的一般信息,请参见 第5.5节“MySQL服务器组件”

注意

如果您使用 MySQL Yum存储库 MySQL SLES存储库 Oracle提供的RPM软件包 安装MySQL 8.0 ,那么 validate_password 在首次启动MySQL服务器后 组件将默认启用。

使用Yum或RPM软件包从5.7升级到MySQL 8.0会使 validate_password 插件保持原位。 要从 validate_password 插件转换到 validate_password 组件,请参见 第6.4.3.3节“转换到密码验证组件”

要使服务器可以使用,组件库文件必须位于MySQL插件目录( plugin_dir 系统变量 指定的目录 )中。 如有必要,通过设置 plugin_dir 服务器启动时 的值来配置插件目录位置

要安装 validate_password 组件,请使用以下语句:

INSTALL COMPONENT'file:// component_validate_password';

组件安装是一次性操作,无需在每个服务器启动时完成。 INSTALL COMPONENT 加载组件,并将其注册到 mysql.component 系统表中,以便在后续服务器启动期间加载它。

卸载 validate_password 组件,请使用以下语句:

UNINSTALL COMPONENT'file:// component_validate_password';

UNINSTALL COMPONENT 卸载组件,并从 mysql.component 系统表中 取消注册, 以使其在后续服务器启动期间不被加载。

6.4.3.2密码验证选项和变量

本节介绍 validate_password 用于配置和监视其操作 的系统和状态变量

密码验证组件系统变量

如果 validate_password 组件已启用,则会公开几个允许配置密码检查的系统变量:

MySQL的> SHOW VARIABLES LIKE 'validate_password.%';
+ -------------------------------------- + -------- +
| Variable_name | 价值|
+ -------------------------------------- + -------- +
| validate_password.check_user_name | ON |
| validate_password.dictionary_file | |
| validate_password.length | 8 |
| validate_password.mixed_case_count | 1 |
| validate_password.number_count | 1 |
| validate_password.policy | MEDIUM |
| validate_password.special_char_count | 1 |
+ -------------------------------------- + -------- +

要更改密码的检查方式,可以在服务器启动时或运行时设置这些系统变量。 以下列表描述了每个变量的含义。

  • validate_password.check_user_name

    属性
    命令行格式 --validate-password.check-user-name[={OFF|ON}]
    介绍 8.0.4
    系统变量 validate_password.check_user_name
    范围 全球
    动态
    SET_VAR 提示适用 没有
    类型 布尔
    默认值 ON

    是否 validate_password 将密码与当前会话的有效用户帐户的用户名部分进行比较,如果匹配则拒绝它们。 除非 validate_password 已安装, 否则此变量不可用

    默认情况下, validate_password.check_user_name 已启用。 此变量控制用户名匹配,与值无关 validate_password.policy

    validate_password.check_user_name 启用时,它具有以下作用:

    • 检查发生在 validate_password 调用的 所有上下文中 ,包括使用诸如 ALTER USER SET PASSWORD 更改当前用户密码 的语句 ,以及调用诸如的函数 VALIDATE_PASSWORD_STRENGTH()

    • 用于比较的用户名取自 当前会话 的值 USER() CURRENT_USER() 函数 的值 这意味着具有足够权限来设置其他用户密码的用户可以将密码设置为该用户的名称,并且不能将该用户的密码设置为执行该语句的用户的名称。 例如, 'root'@'localhost' 可以设定密码 'jeffrey'@'localhost' 'jeffrey' ,但不能设置密码 'root

    • 仅使用 USER() CURRENT_USER() 函数值 的用户名部分, 不是主机名部分。 如果用户名为空,则不进行比较。

    • 如果密码与用户名或其反向相同,则会发生匹配并拒绝密码。

    • 用户名匹配区分大小写。 密码和用户名值在逐个字节的基础上作为二进制字符串进行比较。

    • 如果密码与用户名匹配,则 VALIDATE_PASSWORD_STRENGTH() 无论如何 validate_password 设置 其他 系统变量,都 返回0

  • validate_password.dictionary_file

    属性
    命令行格式 --validate-password.dictionary-file=file_name
    介绍 8.0.4
    系统变量 validate_password.dictionary_file
    范围 全球
    动态
    SET_VAR 提示适用 没有
    类型 文件名

    validate_password 用于检查密码 的字典文件的路径名 除非 validate_password 已安装, 否则此变量不可用

    默认情况下,此变量具有空值,不执行字典检查。 要进行字典检查,变量值必须为非空。 如果文件被命名为相对路径,则相对于服务器数据目录进行解释。 文件内容应为小写,每行一个字。 内容被视为具有字符集 utf8 允许的最大文件大小为1MB。

    对于密码检查期间使用的字典文件,密码策略必须设置为2( STRONG ); 请参阅 validate_password.policy 系统变量 的说明 假设这是真的,将长度为4到100的密码的每个子字符串与字典文件中的字进行比较。 任何匹配都会导致密码被拒绝。 比较不区分大小写。

    因为 VALIDATE_PASSWORD_STRENGTH() ,根据所有策略检查密码,包括 STRONG ,因此强度评估包括字典检查,无论 validate_password.policy 如何

    validate_password.dictionary_file 可以在运行时设置,并且分配值会导致在不重新启动服务器的情况下读取指定的文件。

  • validate_password.length

    属性
    命令行格式 --validate-password.length=#
    介绍 8.0.4
    系统变量 validate_password.length
    范围 全球
    动态
    SET_VAR 提示适用 没有
    类型 整数
    默认值 8
    最低价值 0

    validate_password 需要密码 的最小字符数 除非 validate_password 已安装, 否则此变量不可用

    validate_password.length 最小值是其他几个相关的系统变量的函数。 该值不能设置为小于此表达式的值:

    validate_password.number_count
    + validate_password.special_char_count
    +(2 * validate_password.mixed_case_count)
    

    如果 validate_password 调整 validate_password.length 由于前面的约束而导致 的值 ,则会将消息写入错误日志。

  • validate_password.mixed_case_count

    属性
    命令行格式 --validate-password.mixed-case-count=#
    介绍 8.0.4
    系统变量 validate_password.mixed_case_count
    范围 全球
    动态
    SET_VAR 提示适用 没有
    类型 整数
    默认值 1
    最低价值 0

    validate_password 如果密码策略是 MEDIUM 强或更强 ,则 需要密码 的小写和大写字符的最小数量 除非 validate_password 已安装, 否则此变量不可用

    对于给定 validate_password.mixed_case_count 值,密码必须包含许多小写字符和许多大写字符。

  • validate_password.number_count

    属性
    命令行格式 --validate-password.number-count=#
    介绍 8.0.4
    系统变量 validate_password.number_count
    范围 全球
    动态
    SET_VAR 提示适用 没有
    类型 整数
    默认值 1
    最低价值 0

    validate_password 密码策略为 MEDIUM 或更强时 需要密码 的最小数字(数字)字符数 除非 validate_password 已安装, 否则此变量不可用

  • validate_password.policy

    属性
    命令行格式 --validate-password.policy=value
    介绍 8.0.4
    系统变量 validate_password.policy
    范围 全球
    动态
    SET_VAR 提示适用 没有
    类型 列举
    默认值 1
    有效值

    0

    1

    2

    密码策略强制执行 validate_password 除非 validate_password 已安装, 否则此变量不可用

    validate_password.policy 影响如何 validate_password 使用其他策略设置系统变量,除了检查用户名的密码,由用户名独立控制 validate_password.check_user_name

    validate_password.policy 可使用的数值0,1,2,或相应的符号值来指定值 LOW MEDIUM STRONG 下表描述了为每个策略执行的测试。 对于长度测试,所需长度是 validate_password.length 系统变量 的值 同样,其他测试所需的值由其他 变量 给出 validate_password.xxx

    政策 测试已执行
    0 要么 LOW 长度
    1 要么 MEDIUM 长度; 数字,小写/大写和特殊字符
    2 要么 STRONG 长度; 数字,小写/大写和特殊字符; 字典文件
  • validate_password.special_char_count

    属性
    命令行格式 --validate-password.special-char-count=#
    介绍 8.0.4
    系统变量 validate_password.special_char_count
    范围 全球
    动态
    SET_VAR 提示适用 没有
    类型 整数
    默认值 1
    最低价值 0

    validate_password 如果密码策略是 MEDIUM 强或更强 ,则 需要密码 的非字母数字字符的最小数量 除非 validate_password 已安装, 否则此变量不可用

密码验证组件状态变量

如果 validate_password 组件已启用,则会公开提供操作信息的状态变量:

MySQL的> SHOW STATUS LIKE 'validate_password.%';
+ ----------------------------------------------- +  - -------------------- +
| Variable_name | 价值|
+ ----------------------------------------------- +  - -------------------- +
| validate_password.dictionary_file_last_parsed | 2018-01-15 08:33:49 |
| validate_password.dictionary_file_words_count | 1902年|
+ ----------------------------------------------- +  - -------------------- +

以下列表描述了每个状态变量的含义。

密码验证插件选项
注意

在MySQL 8.0.4中, validate_password 插件重新实现为 validate_password 组件。 validate_password 插件已弃用,将在未来的MySQL版本中删除。 因此,其选项也已弃用,将被删除。 使用该插件的MySQL安装应该转换为使用该组件。 请参见 第6.4.3.3节“转换到密码验证组件”

要控制 validate_password 插件的 激活 ,请使用此选项:

密码验证插件系统变量
注意

在MySQL 8.0.4中, validate_password 插件重新实现为 validate_password 组件。 validate_password 插件已弃用,将在未来的MySQL版本中删除。 因此,它的系统变量也已弃用,将被删除。 使用 validate_password 组件 的相应系统变量 ; 请参阅 密码验证组件系统变量 使用该插件的MySQL安装应该转换为使用该组件。 请参见 第6.4.3.3节“转换到密码验证组件”

密码验证插件状态变量
注意

在MySQL 8.0.4中, validate_password 插件重新实现为 validate_password 组件。 validate_password 插件已弃用,将在未来的MySQL版本中删除。 因此,其状态变量也已弃用,将被删除。 使用 validate_password 组件 的相应状态变量 ; 请参阅 密码验证组件状态变量 使用该插件的MySQL安装应该转换为使用该组件。 请参见 第6.4.3.3节“转换到密码验证组件”

6.4.3.3转换到密码验证组件

注意

在MySQL 8.0.4中, validate_password 插件重新实现为 validate_password 组件。 validate_password 插件已弃用,将在未来的MySQL版本中删除。

当前使用该 validate_password 插件的 MySQL安装 应该转换为使用该 validate_password 组件。 为此,请使用以下过程。 该过程在卸载插件之前安装组件,以避免出现没有密码验证的时间窗口。 (组件和插件可以同时安装。在这种情况下,服务器会尝试使用该组件,如果组件不可用,则回退到插件。)

  1. 安装 validate_password 组件:

    INSTALL COMPONENT'file:// component_validate_password';
    
  2. 测试 validate_password 组件以确保它按预期工作。 如果需要设置任何 系统变量,可以在运行时使用 (必须在下一步中执行必须进行的任何选项文件更改。) validate_password.xxx SET GLOBAL

  3. 调整对插件系统和状态变量的任何引用,以引用相应的组件系统和状态变量。 假设您在启动时使用如下选项文件配置插件:

    的[mysqld]
    验证密码= FORCE_PLUS_PERMANENT
    validate_password_dictionary_file =的/ usr /共享/字典/字
    validate_password_length = 10
    validate_password_number_count = 2
    

    要调整选项文件,请省略该 --validate-password 选项(它仅适用于插件,而不是组件),并修改系统变量引用:

    的[mysqld]
    validate_password.dictionary_file =的/ usr /共享/字典/字
    validate_password.length = 10
    validate_password.number_count = 2
    

    对于在运行时引用 validate_password 插件系统和状态变量的 应用程序,需要进行类似的调整

  4. 卸载 validate_password 插件:

    UNINSTALL PLUGIN validate_password;
    

    如果 validate_password 使用 --plugin-load --plugin-load-add 选项 在服务器启动时加载插件 ,请从服务器启动过程中省略该选项。 例如,如果该选项列在服务器选项文件中,请将其从文件中删除。

  5. 重启服务器。

6.4.4 MySQL密钥环

MySQL服务器支持密钥环,使内部服务器组件和插件能够安全地存储敏感信息,以便以后检索。 该实现是基于插件的:

警告

keyring_file keyring_encrypted_file 加密密钥管理插件不打算作为一个合规性解决方案。 PCI,FIPS等安全标准要求使用密钥管理系统来保护,管理和保护密钥保险库或硬件安全模块(HSM)中的加密密钥。

MySQL中密钥环的用途包括:

  • InnoDB 存储引擎使用密钥环存储它的表空间加密密钥。 InnoDB 可以使用任何支持的密钥环插件。

  • MySQL Enterprise Audit使用密钥环存储审核日志文件加密密码。 审核日志插件可以使用任何支持的密钥环插件。

  • 为MySQL服务器激活二进制日志加密时(通过设置) binlog_encryption=ON ),用于加密二进制日志文件和中继日志文件的文件密码的二进制日志加密密钥存储在密钥环中。 任何支持的密钥环插件都可用于存储二进制日志加密密钥。 只要服务器上有使用它们加密的文件,就会保留二进制日志加密密钥。 手动轮换二进制日志主密钥时,将从密钥环中清除不再应用于任何保留的二进制日志文件或中继日志文件的所有二进制日志加密密钥。 如果无法初始化保留的二进制日志文件或中继日志文件以进行重新加密,则不会删除相关的二进制日志加密密钥,以防将来恢复文件。 例如, 如果二进制日志索引文件中列出的文件当前不可读,或者通道初始化失败,则可能出现这种情况。 有关更多信息,请参阅 第17.3.10节“加密二进制日志文件和中继日志文件”

有关一般密钥环安装说明,请参见 第6.4.4.1节“密钥环插件安装” 有关给定密钥环插件的特定信息,请参阅描述该插件的部分。

有关使用密钥环UDF的信息,请参见 第6.4.4.8节“通用密钥环密钥管理功能”

密钥环插件和UDF访问密钥环服务,该服务为密钥环提供服务器组件的接口。 有关访问密钥环插件服务和编写密钥环插件的信息,请参见 第29.3.2节“密钥环服务” 第29.2.4.12节“编写密钥环插件”

6.4.4.1密钥环插件安装

密钥环服务消费者需要安装密钥环插件。 MySQL提供以下插件选择:

  • keyring_file :一个插件,用于将密钥环数据存储在服务器主机本地的文件中。 适用于所有MySQL发行版。

  • keyring_encrypted_file :一个插件,用于将密钥环数据存储在服务器主机本地的加密文件中。 可在MySQL Enterprise Edition发行版中使用。

  • keyring_okv :使用与KMIP兼容的后端密钥环存储产品(如Oracle Key Vault和Gemalto SafeNet KeySecure Appliance)的插件。 可在MySQL Enterprise Edition发行版中使用。

  • keyring_aws :与Amazon Web Services密钥管理服务通信的插件,作为密钥生成的后端,并使用本地文件进行密钥存储。 可在MySQL Enterprise Edition发行版中使用。

本节介绍如何安装您选择的密钥环插件。 有关安装插件的一般信息,请参见 第5.6.1节“安装和卸载插件”

如果您打算将密钥环用户定义函数(UDF)与密钥环插件结合使用,请使用 第6.4.4.8节“通用密钥环密钥管理功能”中 的说明在安装密钥环之后安装UDF

要使服务器可以使用,插件库文件必须位于MySQL插件目录( plugin_dir 系统变量 指定的目录 )中。 如有必要,通过设置 plugin_dir 服务器启动时 的值来配置插件目录位置

每个密钥环插件的安装类似。 以下说明使用 keyring_file 不同密钥环插件的用户可以替换其名称 keyring_file

keyring_file 插件的库文件基本名称是 keyring_file 文件名后缀因平台 .so 而异 (例如, 对于Unix和类Unix系统, .dll 对于Windows)。

注意

一次只能启用一个密钥环插件。 不支持启用多个密钥环插件,结果可能与预期不符。

必须在服务器启动序列期间尽早加载密钥环插件,以便服务器组件可以在自己的初始化期间根据需要访问它。 例如, InnoDB 存储引擎使用密钥环进行表空间加密,因此必须在 InnoDB 初始化 之前加载密钥环插件并使其可用

要加载插件,请使用该 --early-plugin-load 选项命名包含它的插件库文件。 例如,在插件库文件后缀为的平台上 .so ,在服务器 my.cnf 文件中 使用这些行 .so 根据需要 调整 平台 后缀):

的[mysqld]
早期插件负荷= keyring_file.so

在启动服务器之前,请检查所选密钥环插件的注释,以查看它是否允许或需要其他配置:

执行任何特定于插件的配置后,请验证插件安装。 在MySQL服务器运行时,检查 INFORMATION_SCHEMA.PLUGINS 表或使用该 SHOW PLUGINS 语句(请参见 第5.6.2节“获取服务器插件信息” )。 例如:

MySQL的> SELECT PLUGIN_NAME, PLUGIN_STATUS
       FROM INFORMATION_SCHEMA.PLUGINS
       WHERE PLUGIN_NAME LIKE 'keyring%';
+ -------------- + --------------- +
| PLUGIN_NAME | PLUGIN_STATUS |
+ -------------- + --------------- +
| keyring_file | ACTIVE |
+ -------------- + --------------- +

如果插件无法初始化,请检查服务器错误日志以获取诊断消息。

如果服务器组件尝试访问密钥环服务时没有密钥环插件可用,则该组件不能使用该服务。 因此,组件可能无法初始化或可能使用有限的功能进行初始化。 例如,如果 InnoDB 在初始化时发现存在加密表空间,则会尝试访问密钥环。 如果密钥环不可用,则 InnoDB 只能访问未加密的表空间。 要确保也 InnoDB 可以访问加密的表空间,请使用 --early-plugin-load 加载密钥环插件。

插件可以通过其他方法加载,例如 --plugin-load --plugin-load-add 选项或 INSTALL PLUGIN 语句。 但是,对于某些服务器组件,使用这些方法加载的密钥环插件可能在服务器启动顺序中可用得太晚,例如 InnoDB

  • 插件加载使用 --plugin-load 初始化 --plugin-load-add 后发生 InnoDB

  • 使用的插件 INSTALL PLUGIN mysql.plugin 系统表 中注册 并自动加载,以便后续重新启动服务器。 但是,因为 mysql.plugin 是一个 InnoDB 表,所以在启动期间只能在 InnoDB 初始化 之后加载其中指定的任何插件

6.4.4.2使用keyring_file基于文件的插件

keyring_file 插件是一个密钥环插件,用于将密钥环数据存储在服务器主机本地的文件中。

警告

keyring_file 用于加密密钥管理 插件不是作为法规遵从性解决方案。 PCI,FIPS等安全标准要求使用密钥管理系统来保护,管理和保护密钥保险库或硬件安全模块(HSM)中的加密密钥。

要安装 keyring_file 插件,请使用 第6.4.4.1节“密钥环插件安装”中 的常规密钥环安装说明 以及 keyring_file 此处的 特定配置信息

要在服务器启动过程中使用, keyring_file 必须使用该 --early-plugin-load 选项 加载 所述 keyring_file_data 系统变量任选配置由所使用的文件的位置 keyring_file 的插件用于数据存储。 默认值是特定于平台的。 要显式配置文件位置,请在启动时设置变量值。 例如,在服务器 my.cnf 文件中 使用这些行 .so 根据需要 调整平台的 后缀和文件位置):

的[mysqld]
早期插件负荷= keyring_file.so
keyring_file_data =的/ usr /本地/ MySQL的/ MySQL的-钥匙圈/钥匙圈

密钥环操作是事务性的: keyring_file 插件在写入操作期间使用备份文件,以确保在操作失败时它可以回滚到原始文件。 备份文件的名称与 keyring_file_data 系统变量 的值相同 ,后缀为 .backup

有关其他信息 keyring_file_data ,请参见 第6.4.4.11节“密钥环系统变量”

要确保仅在存在正确的密钥环存储文件时刷新 keyring_file 密钥,请在文件中存储 密钥环 的SHA-256校验和。 在更新文件之前,插件会验证它是否包含预期的校验和。

keyring_file 插件支持组成标准密钥环服务接口的功能。 这些功能执行的密钥环操作可在两个级别访问:

示例(使用UDF):

SELECT keyring_key_generate('MyKey','AES',32);
SELECT keyring_key_remove('MyKey');

允许的密钥类型 keyring_file 第6.4.4.7节“支持的密钥环密钥类型”中描述

6.4.4.3使用keyring_encrypted_file密钥环插件

注意

keyring_encrypted_file 插件是MySQL企业版(一种商业产品)中包含的扩展。 要了解有关商业产品的更多信息,请访问 https://www.mysql.com/products/

keyring_encrypted_file 插件是一个密钥环插件,用于将密钥环数据存储在服务器主机本地的加密文件中。 这个插件从MySQL 5.7.21开始提供。

警告

keyring_encrypted_file 用于加密密钥管理 插件不是作为法规遵从性解决方案。 PCI,FIPS等安全标准要求使用密钥管理系统来保护,管理和保护密钥保险库或硬件安全模块(HSM)中的加密密钥。

要安装 keyring_encrypted_file 插件,请使用 第6.4.4.1节“密钥环插件安装”中 的常规密钥环安装说明 以及 keyring_encrypted_file 此处的 特定配置信息

要在服务器启动过程中使用, keyring_encrypted_file 必须使用该 --early-plugin-load 选项 加载 要指定加密密钥环数据文件的密码,请设置 keyring_encrypted_file_password 系统变量。 (密码是必需的;如果在服务器启动时未指定,则 keyring_encrypted_file 初始化失败。) keyring_encrypted_file_data 系统变量可选地配置 keyring_encrypted_file 插件用于数据存储 的文件的位置 默认值是特定于平台的。 要显式配置文件位置,请在启动时设置变量值。 例如,在服务器 my.cnf 文件中 使用这些行 (调整 .so 根据需要为您的平台添加后缀和文件位置,并替换您选择的密码):

的[mysqld]
早期插件负荷= keyring_encrypted_file.so
keyring_encrypted_file_data =的/ usr /本地/ MySQL的/ MySQL的-钥匙圈/钥匙圈加密
keyring_encrypted_file_password =password

因为 my.cnf 文件在写入时存储密码,所以它应该具有限制模式,并且只能用于运行MySQL服务器的帐户。

密钥环操作是事务性的: keyring_encrypted_file 插件在写入操作期间使用备份文件,以确保在操作失败时它可以回滚到原始文件。 备份文件的名称与 keyring_encrypted_file_data 系统变量 的值相同 ,后缀为 .backup

有关用于配置 keyring_encrypted_file 插件 的系统变量的其他信息 ,请参见 第6.4.4.11节“密钥环系统变量”

要确保仅在存在正确的密钥环存储文件时刷新 keyring_encrypted_file 密钥,请在文件中存储 密钥环 的SHA-256校验和。 在更新文件之前,插件会验证它是否包含预期的校验和。 另外, keyring_encrypted_file 在写入文件之前使用AES加密文件内容,并在读取文件之后解密文件内容。

keyring_encrypted_file 插件支持组成标准密钥环服务接口的功能。 这些功能执行的密钥环操作可在两个级别访问:

示例(使用UDF):

SELECT keyring_key_generate('MyKey','AES',32);
SELECT keyring_key_remove('MyKey');

允许的密钥类型 keyring_encrypted_file 第6.4.4.7节“支持的密钥环密钥类型”中描述

6.4.4.4使用keyring_okv KMIP插件

注意

keyring_okv 插件是MySQL企业版(一种商业产品)中包含的扩展。 要了解有关商业产品的更多信息,请访问 https://www.mysql.com/products/

密钥管理互操作性协议(KMIP)支持密钥管理服务器与其客户端之间的加密密钥通信。 keyring_okv 密钥环插件使用KMIP 1.1协议作为一个KMIP后端的一个客户端安全地通信。 钥匙圈材料仅由后端产生,而不是由后端产生 keyring_okv 该插件适用于这些与KMIP兼容的产品:

  • Oracle Key Vault

  • 金雅拓SafeNet KeySecure设备

keyring_okv 插件支持组成标准密钥环服务接口的功能。 这些功能执行的密钥环操作可在两个级别访问:

示例(使用UDF):

SELECT keyring_key_generate('MyKey','AES',32);
SELECT keyring_key_remove('MyKey');

允许的密钥类型 keyring_okv 第6.4.4.7节“支持的密钥环密钥类型”中描述

要安装 keyring_okv 插件,请使用 第6.4.4.1节“密钥环插件安装”中 的常规密钥环安装说明 以及 keyring_okv 此处的 特定配置信息

一般keyring_okv配置

无论 keyring_okv 插件使用 哪个KMIP后端 进行密钥环存储, keyring_okv_conf_dir 系统变量都会 keyring_okv 为其支持文件 配置所用目录的位置 默认值为空,因此在插件可以与KMIP后端通信之前,必须将变量设置为命名正确配置的目录。 除非您这样做,否则 keyring_okv 在服务器启动期间向错误日志写入一条消息,它无法通信:

[警告]插件keyring_okv报告:'对于keyring_okv来说
初始化后,请将keyring_okv_conf_dir变量指向一个目录
包含Oracle Key Vault配置文件和ssl材料'

keyring_okv_conf_dir 变量必须命名包含以下项目的目录:

  • okvclient.ora :包含 keyring_okv 将与之通信 的KMIP后端的详细信息的文件

  • ssl :包含证书,并建立与KMIP后端的安全连接所需的密钥文件的目录 CA.pem cert.pem key.pem 如果密钥文件受密码保护,则该 ssl 目录可以包含名为 password.txt 包含解密密钥文件所需密码 的单行文本 文件。

具有证书和密钥文件 okvclient.ora 文件和 ssl 目录都是 keyring_okv 正常工作 所必需的 用于使用这些文件填充配置目录的过程取决于与其一起使用的KMIP后端 keyring_okv ,如其他地方所述。

keyring_okv 作为其支持文件的位置 使用的配置目录 应具有限制模式,并且只能由用于运行MySQL服务器的帐户访问。 例如,在Unix和类Unix系统上,要使用该 /usr/local/mysql/mysql-keyring-okv 目录,以下命令(执行为 root )创建目录并设置其模式和所有权:

cd / usr / local / mysql
mkdir mysql-keyring-okv
chmod 750 mysql-keyring-okv
chown mysql mysql-keyring-okv
chgrp mysql mysql-keyring-okv

要在服务器启动过程中使用, keyring_okv 必须使用该 --early-plugin-load 选项 加载 另外,设置 keyring_okv_conf_dir 系统变量以告知 keyring_okv 在哪里可以找到其配置目录。 例如,在服务器 my.cnf 文件中 使用这些行 .so 根据需要 调整平台的 后缀和目录位置):

的[mysqld]
早期插件负荷= keyring_okv.so
keyring_okv_conf_dir =的/ usr /本地/ MySQL的/ MySQL的-钥匙圈 -  OKV

有关其他信息 keyring_okv_conf_dir ,请参见 第6.4.4.11节“密钥环系统变量”

为Oracle Key Vault配置keyring_okv

此处的讨论假定您熟悉Oracle Key Vault。 一些相关的信息来源:

在Oracle Key Vault术语中,使用Oracle Key Vault存储和检索安全对象的客户端称为端点。 要与Oracle Key Vault通信,必须注册为端点并通过下载和安装端点支持文件进行注册。

以下过程简要总结了设置 keyring_okv 与Oracle Key Vault一起使用 的过程

  1. keyring_okv 要使用 插件 创建配置目录

  2. 使用Oracle Key Vault注册端点以获取注册令牌。

  3. 使用注册令牌获取 okvclient.jar 客户端软件下载。

  4. 安装客户端软件以填充 keyring_okv 包含Oracle Key Vault支持文件 配置目录。

使用以下过程配置 keyring_okv Oracle Key Vault以协同工作。 此说明仅总结了如何与Oracle Key Vault交互。 有关详细信息,请访问 Oracle Key Vault 站点并查阅Oracle Key Vault管理员指南。

  1. 创建将包含Oracle Key Vault支持文件的配置目录,并确保将 keyring_okv_conf_dir 系统变量设置为命名该目录(有关详细信息,请参阅 常规keyring_okv配置 )。

  2. 以具有系统管理员角色的用户身份登录Oracle Key Vault管理控制台。

  3. 选择Endpoints选项卡以到达Endpoints页面。 在“端点”页面上,单击“添加”。

  4. 提供所需的端点信息,然后单击“注册” 端点类型应为Other。 成功注册会产生注册令牌​​。

  5. 从Oracle Key Vault服务器注销。

  6. 再次连接到Oracle Key Vault服务器,这次没有登录。使用端点注册令牌注册并请求 okvclient.jar 软件下载。 将此文件保存到您的系统。

  7. okvclient.jar 使用以下命令 安装 文件(您必须具有JDK 1.4或更高版本):

    java -jar okvclient.jar -d dir_name[-v]
    

    -d 选项 后面的目录名称 是安装解压缩文件的位置。 -v 如果给定 选项,则会生成日志信息,如果命令失败,则可能会有用。

    当命令要求提供Oracle Key Vault端点密码时,请不要提供密码。 而是,按Enter键。 (结果是端点连接到Oracle Key Vault时不需要密码。)

  8. 上面的命令生成一个 okvclient.ora 文件,该文件应 -d 位于前面的 java -jar 命令中 选项所 指定的目录下的此位置

    INSTALL_DIR / CONF / okvclient.ora
    

    文件内容包括如下所示的行:

    SERVER = host_ipport_num
    STANDBY_SERVER = host_ipport_num
    

    keyring_okv 插件试图与服务器通过指定的主机上运行的沟通 SERVER 变回退到 STANDBY_SERVER 如果失败:

    • 对于 SERVER 变量, okvclient.ora 文件中 的设置 是必需的。

    • 对于 STANDBY_SERVER 变量, okvclient.ora 文件中 的设置 是可选的。

  9. 转到Oracle Key Vault安装程序目录并通过运行以下命令测试设置:

    okvutil / bin / okvutil list
    

    输出应该如下所示:

    唯一ID类型标识符
    255AB8DE-C97F-482C-E053-0100007F28B9对称键 - 
    264BF6E0-A20E-7C42-E053-0100007FB29C对称密钥 - 
    

    对于新的Oracle Key Vault服务器(没有任何密钥的服务器),输出看起来像这样,表示Vault中没有密钥:

    找不到任何物体
    
  10. 使用此命令 ssl okvclient.jar 文件中 提取 包含SSL材料的 目录:

    jar xf okvclient.jar ssl
    
  11. 将Oracle Key Vault支持文件( okvclient.ora 文件和 ssl 目录) 复制 到配置目录中。

  12. (可选)如果要对密钥文件进行密码保护,请使用 密码保护keyring_okv密钥文件中的说明

完成上述步骤后,重启MySQL服务器。 它加载 keyring_okv 插件并 keyring_okv 使用其配置目录中的文件与Oracle Key Vault进行通信。

为金雅拓SafeNet KeySecure设备配置keyring_okv

金雅拓SafeNet KeySecure设备使用KMIP协议(版本1.1或1.2)。 keyring_okv 密钥环插件(它支持KMIP 1.1)可以使用KeySecure作为钥匙圈存储其KMIP后端。

使用以下过程配置 keyring_okv 和KeySecure一起工作。 该描述仅总结了如何与KeySecure进行交互。 有关详细信息,请参阅“ KeySecure用户指南”中的“ 添加KMIP服务器 ”一节

  1. 创建将包含KeySecure支持文件的配置目录,并确保将 keyring_okv_conf_dir 系统变量设置为命名该目录(有关详细信息,请参阅 常规keyring_okv配置 )。

  2. 在配置目录中,创建一个名为“ ssl 用于存储所需SSL证书和密钥文件” 的子目录

  3. 在配置目录中,创建一个名为的文件 okvclient.ora 它应该具有以下格式:

    SERVER = host_ipport_num
    STANDBY_SERVER = host_ipport_num
    

    例如,如果KeySecure在主机198.51.100.20上运行并侦听端口9002,则 okvclient.ora 文件如下所示:

    SERVER = 198.51.100.20:9002
    STANDBY_SERVER = 198.51.100.20:9002
    
  4. 以管理员身份连接到KeySecure管理控制台,并具有证书颁发机构访问权限的凭据。

  5. 导航到安全>>本地CA并创建本地证书颁发机构(CA)。

  6. 转到可信CA列表。 选择Default,然后单击Properties。 然后选择“编辑可信证书颁发机构列表”并添加刚刚创建的CA.

  7. 下载CA并将其 ssl 作为名为的文件 保存在 目录中 CA.pem

  8. 导航到安全>>证书请求并创建证书。 然后,您将能够下载 包含证书PEM文件 的压缩 tar 文件。

  9. 从下载的文件中提取PEM文件。 例如,如果文件名是 csr_w_pk_pkcs8.gz ,则使用以下命令对其进行解压缩和解压缩:

    tar zxvf csr_w_pk_pkcs8.gz
    

    提取操作产生两个文件: certificate_request.pem private_key_pkcs8.pem

  10. 使用此 openssl 命令解密私钥并创建名为的文件 key.pem

    openssl pkcs8 -in private_key_pkcs8.pem -out key.pem
    
  11. key.pem 文件 复制 ssl 目录中。

  12. 将证书请求复制 certificate_request.pem 到剪贴板中。

  13. 导航到安全>>本地CA. 选择您之前创建的CA(您下载的用于创建 CA.pem 文件的 CA ),然后单击“签名请求”。 从剪贴板粘贴证书请求,选择客户端的证书目的(密钥环是KeySecure的客户端),然后单击“签名请求”。 结果是在新页面中使用所选CA签名的证书。

  14. 签名的证书复制到剪贴板,然后将剪贴板中的内容保存为一个文件名为 cert.pem ssl 目录中。

  15. (可选)如果要对密钥文件进行密码保护,请使用 密码保护keyring_okv密钥文件中的说明

完成上述步骤后,重启MySQL服务器。 它加载 keyring_okv 插件并 keyring_okv 使用其配置目录中的文件与KeySecure进行通信。

密码保护keyring_okv密钥文件

您可以选择使用密码保护密钥文件,并提供包含密码的文件以使密钥文件能够被解密。 为此,请将位置更改为 ssl 目录并执行以下步骤:

  1. 加密 key.pem 密钥文件。 例如,使用这样的命令,并在提示符处输入加密密码:

    外壳> openssl rsa -des3 -in key.pem -out key.pem.new
    输入PEM密码短语:
    验证 - 输入PEM密码短语:
    
  2. 将加密密码保存 password.txt ssl 目录中 指定的单行文本文件

  3. 验证是否可以使用以下命令解密加密的密钥文件。 解密的文件应显示在控制台上:

    外壳> openssl rsa -in key.pem.new -passin file:password.txt
    
  4. 删除原始 key.pem 文件并重命名 key.pem.new key.pem

  5. 根据需要更改新 key.pem 文件和 password.txt 文件 的所有权和访问模式, 以确保它们与 ssl 目录中的 其他文件具有相同的限制

6.4.4.5使用keyring_aws Amazon Web Services密钥环插件

注意

keyring_aws 插件是MySQL企业版(一种商业产品)中包含的扩展。 要了解有关商业产品的更多信息,请访问 https://www.mysql.com/products/

keyring_aws 插件是一个密钥环插件,它与Amazon Web Services密钥管理服务(AWS KMS)通信,作为密钥生成的后端,并使用本地文件进行密钥存储。 所有密钥环材料都由AWS服务器专门生成,而不是由 keyring_aws

keyring_aws 可在以下平台上使用:

  • Debian 8

  • EL7

  • macOS 10.13和10.14

  • SLES 12

  • Ubuntu 14.04和16.04

  • 视窗

此处的讨论假设您熟悉AWS,特别是KMS。 一些相关的信息来源:

以下部分提供 keyring_aws 密钥环插件的 配置和使用信息

keyring_aws配置

要安装 keyring_aws 插件,请使用 第6.4.4.1节“密钥环插件安装”中 的常规安装说明 以及此处的插件特定配置信息。

插件库文件包含 keyring_aws 插件和两个用户定义的函数(UDF), keyring_aws_rotate_cmk() 以及 keyring_aws_rotate_keys()

要进行配置 keyring_aws ,您必须获取秘密访问密钥,该密钥提供与AWS KMS通信的凭据并将其写入配置文件:

  1. 创建AWS KMS帐户。

  2. 使用AWS KMS创建秘密访问密钥ID和秘密访问密钥。 访问密钥用于验证您和您的应用程序的身份。

  3. 使用AWS KMS帐户创建客户主密钥(CMK)ID。 在MySQL启动时,将 keyring_aws_cmk_id 系统变量设置为CMK ID值。 此变量是必需的,没有默认值。 (如果需要,可以在运行时更改其值 SET GLOBAL 。)

  4. 如有必要,请创建配置文件所在的目录。 该目录应具有限制模式,并且只能用于运行MySQL服务器的帐户。 例如,在Unix和类Unix系统上,要 /usr/local/mysql/mysql-keyring/keyring_aws_conf 用作文件名,以下命令(执行为 root )创建其父目录并设置目录模式和所有权:

    shell> cd /usr/local/mysql
    shell> mkdir mysql-keyring
    shell> chmod 750 mysql-keyring
    shell> chown mysql mysql-keyring
    shell>chgrp mysql mysql-keyring
    

    在MySQL启动时,将 keyring_aws_conf_file 系统变量 设置 /usr/local/mysql/mysql-keyring/keyring_aws_conf 以指示服务器的配置文件位置。

  5. 准备 keyring_aws 配置文件,该文件应包含两行:

    • 第1行:秘密访问密钥ID

    • 第2行:秘密访问密钥

    例如,如果密钥ID是 wwwwwwwwwwwwwEXAMPLE 密钥 xxxxxxxxxxxxx/yyyyyyy/zzzzzzzzEXAMPLEKEY ,则配置文件如下所示:

    wwwwwwwwwwwwwEXAMPLE
    XXXXXXXXXXXXX / YYYYYYY / zzzzzzzzEXAMPLEKEY
    

要在服务器启动过程中使用, keyring_aws 必须使用该 --early-plugin-load 选项 加载 所述 keyring_aws_cmk_id 系统变量是强制性的,构成从AWS KMS服务器获得的顾客主密钥(CMK)的标识。 keyring_aws_conf_file keyring_aws_data_file 系统变量有选择地配置由所使用的文件的位置 keyring_aws 插件配置信息和数据的存储。 文件位置变量默认值是特定于平台的。 要显式配置位置,请在启动时设置变量值。 例如,在服务器 my.cnf 文件中 使用这些行 (调整 .so 必要时,为您的平台添加后缀和文件位置):

的[mysqld]
早期插件负荷= keyring_aws.so
keyring_aws_cmk_id = '阿尔恩:AWS:公里:美西2:111122223333:键/ ABCD1234-ef56-AB12-CD34-ef56abcd1234'
keyring_aws_conf_file =的/ usr /本地/ MySQL的/ MySQL的-钥匙圈/ keyring_aws_conf
keyring_aws_data_file =的/ usr /本地/ MySQL的/ MySQL的-钥匙圈/ keyring_aws_data

要使 keyring_aws 插件成功启动,配置文件必须存在并包含有效的秘密访问密钥信息,如前所述进行初始化。 存储文件不需要存在。 如果没有, keyring_aws 尝试创建它(如果需要,还可以创建其父目录)。

有关用于配置 keyring_aws 插件 的系统变量的其他信息 ,请参见 第6.4.4.11节“密钥环系统变量”

启动MySQL服务器并安装与 keyring_aws 插件 关联的UDF 这是一次性操作,通过执行以下语句执行( .so 根据需要 调整 平台 后缀):

创建功能keyring_aws_rotate_cmk RETURNS INTEGER
  SONAME'keyring_aws.so';
创建功能keyring_aws_rotate_keys返回INTEGER
  SONAME'keyring_aws.so';
keyring_aws操作

在插件启动时, keyring_aws 插件从其配置文件中读取AWS秘密访问密钥ID和密钥。 它还将其存储文件中包含的任何加密密钥读入其内存缓存中。

在操作期间, keyring_aws 在内存缓存中维护加密密钥,并将存储文件用作本地永久存储。 每个密钥环操作都是事务性的: keyring_aws 要么成功地更改内存中的密钥缓存和密钥环存储文件,要么操作失败并且密钥环状态保持不变。

要确保仅在存在正确的密钥环存储文件时刷新 keyring_aws 密钥,请在文件中存储 密钥环 的SHA-256校验和。 在更新文件之前,插件会验证它是否包含预期的校验和。

keyring_aws 插件支持组成标准密钥环服务接口的功能。 这些功能执行的密钥环操作可在两个级别访问:

示例(使用UDF):

SELECT keyring_key_generate('MyKey','AES',32);
SELECT keyring_key_remove('MyKey');

此外, UDF keyring_aws_rotate_cmk() 和“ keyring_aws_rotate_keys() UDF ”“ 扩展 密钥环插件接口,以提供标准密钥环服务接口未涵盖的AWS相关功能。 只有通过调用UDF才能访问这些功能。 没有相应的C语言密钥服务功能。

允许的密钥类型 keyring_aws 第6.4.4.7节“支持的密钥环密钥类型”中描述

keyring_aws凭据更改

假设 keyring_aws 插件在服务器启动时已正确初始化,则可以更改用于与AWS KMS通信的凭据:

  1. 使用AWS KMS创建新的秘密访问密钥ID和秘密访问密钥。

  2. 将新凭据存储在配置文件( keyring_aws_conf_file 系统变量 指定的文件 )中。 文件格式如前所述。

  3. 重新初始化 keyring_aws 插件,以便重新读取配置文件。 假设新凭据有效,插件应该成功初始化。

    有两种方法可以重新初始化插件:

    • 重启服务器。 这样更简单,没有副作用,但不适合需要最少服务器停机且尽可能少重启的安装。

    • 通过执行以下语句重新初始化插件而不重新启动服务器( .so 根据需要 调整 平台 后缀):

      UNINSTALL PLUGIN keyring_aws;
      安装PLUGIN keyring_aws SONAME'keyring_aws.so';
      
      注意

      除了在运行时加载插件外, INSTALL PLUGIN 还有将插件注册到 mysql.plugin 系统表 中的副作用 因此,如果您决定停止使用 keyring_aws --early-plugin-load 则从用于启动服务器的选项集中 删除该 选项 是不够 的。 这会阻止插件提前加载,但是当服务器到达启动序列中加载注册插件的点时,服务器仍会尝试加载它 mysql.plugin

      因此,如果您执行 刚刚描述 UNINSTALL PLUGIN 加号 INSTALL PLUGIN 序列来更改AWS KMS凭据,然后停止使用 keyring_aws ,则 UNINSTALL PLUGIN 除了删除 --early-plugin-load 选项 之外 ,还需要 再次 执行 以取消注册该插件

6.4.4.6在密钥环密钥库之间迁移密钥

MySQL服务器支持一种操作模式,可以在底层密钥环密钥库之间迁移密钥。 这使DBA能够将MySQL安装从一个密钥环插件切换到另一个密钥环插件。 迁移服务器(即,以密钥迁移模式启动的服务器)不接受客户端连接。 相反,它只运行足够长的时间来迁移密钥,然后退出。 迁移服务器向控制台报告错误(标准错误输出)。

可以执行脱机或在线密钥迁移:

  • 如果您确定本地主机上没有正在运行的服务器正在使用源或目标密钥库,则可以进行脱机迁移。 在这种情况下,迁移服务器可以修改密钥库,而无法在迁移期间运行服务器修改密钥库内容。

  • 如果本地主机上正在运行的服务器正在使用源或目标密钥库,则必须执行联机迁移。 在这种情况下,迁移服务器连接到正在运行的服务器,并指示它在密钥迁移过程中暂停密钥环操作。

密钥迁移操作的结果是目标密钥库包含迁移之前的密钥以及源密钥库中的密钥。 源密钥库在迁移之前和之后是相同的,因为密钥是复制的,而不是移动的。 如果要复制的密钥已存在于目标密钥库中,则会发生错误,并且目标密钥库将还原到其预迁移状态。

在密钥迁移模式下调用服务器的用户不能是 root 操作系统用户,并且必须具有读取和写入密钥环文件的权限。

要执行密钥迁移操作,请确定需要哪些密钥迁移选项。 迁移选项指示涉及哪些密钥环插件,以及是否执行脱机或在线迁移:

  • 要指示源和目标密钥环插件,请指定以下选项:

    这些选项告诉服务器以密钥迁移模式运行。 所有关键迁移操作都必须使用这两个选项。 源插件和目标插件必须不同,迁移服务器必须支持这两个插件。

  • 对于脱机迁移,不需要其他密钥迁移选项。

    警告

    不要执行涉及正在运行的服务器正在使用的密钥库的脱机迁移。

  • 对于联机迁移,某些正在运行的服务器当前正在使用源或目标密钥库。 指定指示如何连接到正在运行的服务器的密钥迁移选项。 这是必要的,以便迁移服务器可以连接到正在运行的服务器并告诉它在迁移操作期间暂停密钥环的使用。

    使用以下任何选项表示在线迁移:

有关密钥迁移选项的其他详细信息,请参见 第6.4.4.10节“密钥环命令选项”

使用刚才描述的密钥迁移选项启动迁移服务器,可能还有其他选项。 请记住以下注意事项:

  • 可能需要其他服务器选项,例如两个密钥环插件的其他配置参数。 例如,如果 keyring_file 是其中一个插件,则必须 keyring_file_data 在密钥环数据文件位置不是默认位置时 设置 系统变量。 其他非密钥环选项也可能是必需的。 指定这些选项的一种方法是使用 --defaults-file 命名包含所需选项的选项文件。

  • 如果从与通常用于运行MySQL的系统帐户不同的系统帐户调用迁移服务器,则可能会创建在正常操作期间服务器无法访问的密钥环目录或文件。 假设 mysqld 通常以 mysql 操作系统用户 身份 运行,但您在登录时调用迁移服务器 isabel 迁移服务器创建的任何新目录或文件都将归其所有 isabel 当服务器运行时, mysql 操作系统用户尝试访问所拥有的文件系统对象 时,后续启动将失败 isabel

    要避免此问题,请以 root 操作系统用户 身份启动迁移服务器, 并提供一个 选项,其中 通常用于运行MySQL的系统帐户。 --user=user_name user_name

  • 迁移服务器期望路径名选项值为完整路径。 可能无法按预期解析相对路径名称。

脱机密钥迁移的示例命令行:

mysqld --defaults-file = / usr / local / mysql / etc / my.cnf
  --keyring迁移源= keyring_file.so
  --keyring迁移目的地= keyring_encrypted_file.so
  --keyring_encrypted_file_password =password

在线密钥迁移的示例命令行:

mysqld --defaults-file = / usr / local / mysql / etc / my.cnf
  --keyring迁移源= keyring_file.so
  --keyring迁移目的地= keyring_encrypted_file.so
  --keyring_encrypted_file_password =password
  --keyring迁移主机=本地主机
  --keyring迁移用户=根
  --keyring迁移密码=root_password

密钥迁移服务器执行迁移操作,如下所示:

  1. (仅限联机迁移)使用连接选项连接到正在运行的服务器。 用于连接的帐户必须具有修改全局 keyring_operations 系统变量 所需的权限 ENCRYPTION_KEY_ADMIN 除了 SYSTEM_VARIABLES_ADMIN 或之外 SUPER )。

  2. (仅限联机迁移) keyring_operations 在正在运行的服务器上 禁用 (正在运行的服务器必须支持 keyring_operations 。)

  3. 加载源和目标密钥环插件。

  4. 将密钥环中的密钥复制到目标密钥环。

  5. 卸载密钥环插件。

  6. (仅限联机迁移) keyring_operations 在正在运行的服务器上 启用

  7. (仅限联机迁移)断开与正在运行的服务器的连接。

  8. 出口。

如果在密钥迁移期间发生错误,则会删除复制到目标插件的所有密钥,从而保持目标密钥库不变。

重要

对于联机迁移操作,迁移服务器负责 keyring_operations 在正在运行的服务器上 启用和禁用 但是,如果迁移服务器异常退出(例如,如果有人强行终止它),则可能 keyring_operations 无法在正在运行的服务器上重新启用,从而无法执行密钥环操作。 在这种情况下,可能需要连接到正在运行的服务器并 keyring_operations 手动 启用

成功进行在线密钥迁移操作后,可能需要重新启动正在运行的服务器:

  • 如果正在运行的服务器正在使用源密钥库,则无需在迁移后重新启动它。

  • 如果正在运行的服务器在迁移之前使用源密钥库,但在迁移后应使用目标密钥库,则必须重新配置它以使用目标密钥环插件并重新启动。

  • 如果正在运行的服务器正在使用目标密钥库并将继续使用它,则应在迁移后重新启动它以加载迁移到目标密钥库的所有密钥。

注意

MySQL服务器密钥迁移模式支持暂停单个正在运行的服务器。 要在多个密钥服务器使用所涉及的密钥库时执行密钥迁移,请使用以下过程:

  1. 手动连接到每个正在运行的服务器,并设置 keyring_operations=OFF

  2. 使用迁移服务器执行脱机密钥迁移。

  3. 手动连接到每个正在运行的服务器,并设置 keyring_operations=ON

所有正在运行的服务器必须支持 keyring_operations=ON 系统变量

6.4.4.7支持的密钥环密钥类型

MySQL Keyring支持生成不同类型的密钥(加密算法)和长度。 可用的密钥类型取决于安装的密钥环插件。 给定插件还可以对每个键类型的键长度施加约束。

表6.26“密钥环插件密钥类型” 总结了每个密钥环插件允许的密钥类型。 长度以字节为单位。 对于使用 第6.4.4.8节“通用密钥环密钥管理函数”中 描述的密钥环用户定义函数(UDF)之一生成的密钥 ,由于UDF的限制,长度不能超过2,048字节接口。

表6.26密钥环插件密钥类型

插件名称 允许的密钥类型 密钥类型的允许密钥长度
keyring_encrypted_file

AES

DSA

RSA

没有特别限制

没有特别限制

没有特别限制

keyring_file

AES

DSA

RSA

没有特别限制

没有特别限制

没有特别限制

keyring_okv AES 16,24,32
keyring_aws AES 16,24,32

6.4.4.8通用密钥环密钥管理功能

MySQL服务器支持密钥环服务,该服务使内部服务器组件和插件能够安全地存储敏感信息,以便以后检索。

MySQL服务器还包括用于密钥环密钥管理的SQL接口,实现为一组通用用户定义函数(UDF),用于访问内部密钥环服务提供的功能。 密钥环UDF包含在一个插件库文件中,该文件还包含一个 keyring_udf 必须在UDF调用之前启用 插件。 对于要使用的这些UDF, 需要启用 密钥环插件,例如 keyring_file keyring_okv 必须启用。

这里描述的UDF是通用的,旨在与任何密钥环插件一起使用。 给定的密​​钥环插件可能具有自己的UDF,仅用于该插件; 请参见 第6.4.4.9节“特定于插件的密钥环密钥管理功能”

以下部分提供了密钥环UDF的安装说明,并演示了如何使用它们。 有关UDF调用的密钥环服务函数的信息,请参见 第29.3.2节“密钥环服务” 有关一般密钥环信息,请参见 第6.4.4节“MySQL密钥环”

6.4.4.8.1安装或卸载通用密钥环功能

本节介绍如何安装或卸载密钥环用户定义函数(UDF),这些函数在包含插件的插件库文件中实现 keyring_udf 有关安装或卸载插件和UDF的一般信息,请参见 第5.6.1节“安装和卸载插件” 第5.7.1节“安装和卸载用户定义的函数”

密钥环UDF启用密钥环密钥管理操作,但 keyring_udf 也必须安装插件,因为没有它,UDF将无法正常工作。 尝试在没有 keyring_udf 插件的 情况下使用UDF会 导致错误。

要使服务器可以使用,插件库文件必须位于MySQL插件目录( plugin_dir 系统变量 指定的目录 )中。 如有必要,通过设置 plugin_dir 服务器启动时 的值来配置插件目录位置

插件库文件基本名称是 keyring_udf 文件名后缀因平台 .so 而异 (例如, 对于Unix和类Unix系统, .dll 对于Windows)。

要安装 keyring_udf 插件和UDF,请使用 INSTALL PLUGIN CREATE FUNCTION 语句( .so 根据需要 调整 平台 后缀):

安装PLUGIN keyring_udf SONAME'keyring_udf.so';
CREATE FUNCTION keyring_key_generate RETURNS INTEGER
  SONAME'keyring_udf.so';
CREATE FUNCTION keyring_key_fetch RETURNS STRING
  SONAME'keyring_udf.so';
CREATE FUNCTION keyring_key_length_fetch RETURNS INTEGER
  SONAME'keyring_udf.so';
CREATE FUNCTION keyring_key_type_fetch RETURNS STRING
  SONAME'keyring_udf.so';
CREATE FUNCTION keyring_key_store RETURNS INTEGER
  SONAME'keyring_udf.so';
创建功能keyring_key_remove RETURNS INTEGER
  SONAME'keyring_udf.so';

如果在主复制服务器上使用插件和UDF,请将它们安装在所有从属服务器上,以避免复制问题。

如上所述安装后,插件和UDF将保持安装状态,直到卸载为止。 要删除它们,请使用 UNINSTALL PLUGIN DROP FUNCTION 语句:

UNINSTALL PLUGIN keyring_udf;
DROP FUNCTION keyring_key_generate;
DROP FUNCTION keyring_key_fetch;
DROP FUNCTION keyring_key_length_fetch;
DROP FUNCTION keyring_key_type_fetch;
DROP FUNCTION keyring_key_store;
DROP FUNCTION keyring_key_remove;
6.4.4.8.2使用通用密钥环功能

在使用密钥环用户定义函数(UDF)之前,请按照 第6.4.4.8.1节“安装或卸载通用密钥环功能”中 提供的说明进行 安装

密钥环UDF受这些约束:

  • 要使用任何密钥环UDF, keyring_udf 必须启用 插件。 否则,会发生错误:

    ERROR 1123(HY000):无法初始化函数'keyring_key_generate';
    此功能需要未安装的keyring_udf插件。
    请安装
    

    要安装 keyring_udf 插件,请参见 第6.4.4.8.1节“安装或卸载通用密钥环功能”

  • 密钥环UDF调用密钥环服务功能(参见 第29.3.2节“密钥环服务” )。 服务功能反过来使用安装的任何密钥环插件(例如, keyring_file keyring_okv )。 因此,要使用任何密钥环UDF,必须启用一些底层密钥环插件。 否则,会发生错误:

    ERROR 3188(HY000):函数'keyring_key_generate'失败,因为
    底层密钥环服务返回错误。请检查一下
    密钥环插件已安装且提供的参数有效
    对于你正在使用的密钥环。
    

    要安装密钥环插件,请参见 第6.4.4.1节“密钥环插件安装”

  • 要使用任何密钥环UDF,用户必须拥有全局 EXECUTE 特权。 否则,会发生错误:

    ERROR 1123(HY000):无法初始化函数'keyring_key_generate';
    用户无权执行此功能。用户需要
    有执行
    

    要将全局 EXECUTE 特权 授予 用户,请使用以下语句:

    GRANT EXECUTE ON *。* TO user;
    

    或者,如果您 EXECUTE 仍然 希望 在允许用户访问特定密钥管理操作的同时 避免授予全局 特权, 则可以定义 包装器 存储的程序(本节稍后将介绍的技术)。

  • 由给定用户存储在密钥环中的密钥可以稍后由同一用户操纵。 也就是说, CURRENT_USER() 键操作时函数 的值 必须与密钥环中存储密钥时的值相同。 (此约束排除了使用密钥环UDF来操纵实例范围的密钥,例如由 InnoDB 支持表空间加密 而创建的 密钥。)

    为了使多个用户能够对同一个键执行操作, 可以定义 包装器 存储的程序(本节稍后描述的技术)。

  • 密钥环UDF支持底层密钥环插件支持的密钥类型和长度,由于UDF接口的限制,密钥不能超过2,048字节(16,384位)的附加约束。 请参见 第6.4.4.7节“支持的密钥环密钥类型”

要创建一个新的随机密钥并将其存储在密钥环中,请调用 keyring_key_generate() ,向其传递密钥的ID,密钥类型(加密方法)及其长度(以字节为单位)。 以下调用创建一个名为的2,048位DSA加密密钥 MyKey

MySQL的> SELECT keyring_key_generate('MyKey', 'DSA', 256);
+ ------------------------------------------- +
| keyring_key_generate('MyKey','DSA',256)|
+ ------------------------------------------- +
| 1 |
+ ------------------------------------------- +

返回值1表示成功。 如果无法创建密钥,则返回值为, NULL 并发生错误。 这可能是一个原因是底层密钥环插件不支持密钥类型和密钥长度的指定组合; 请参见 第6.4.4.7节“支持的密钥环密钥类型”

为了能够检查返回类型而不管是否发生错误,请使用 并测试变量值: SELECT ... INTO @var_name

MySQL的> SELECT keyring_key_generate('', '', -1) INTO @x;
ERROR 3188(HY000):函数'keyring_key_generate'失败,因为
底层密钥环服务返回错误。请检查一下
密钥环插件已安装且提供的参数有效
对于你正在使用的密钥环。
MySQL的> SELECT @x;
+ ------ +
| @x |
+ ------ +
| NULL |
+ ------ +
mysql> SELECT keyring_key_generate('x', 'AES', 16) INTO @x;
mysql>SELECT @x;
+ ------ +
| @x |
+ ------ +
| 1 |
+ ------ +

此技术也适用于其他密钥环UDF,其失败返回值和错误。

传递给的ID keyring_key_generate() 提供了一种在后续UDF调用中引用键的方法。 例如,使用密钥ID将其类型作为字符串或其长度(以字节为单位)检索为整数:

MySQL的> SELECT keyring_key_type_fetch('MyKey');
+ --------------------------------- +
| keyring_key_type_fetch('MyKey')|
+ --------------------------------- +
| DSA |
+ --------------------------------- +
MySQL的> SELECT keyring_key_length_fetch('MyKey');
+ ----------------------------------- +
| keyring_key_length_fetch('MyKey')|
+ ----------------------------------- +
| 256 |
+ ----------------------------------- +

要检索密钥值,请将密钥ID传递给 keyring_key_fetch() 以下示例用于 HEX() 显示键值,因为它可能包含不可打印的字符。 该示例还使用了一个简短的密钥,但请注意,较长的密钥可提供更好的安全性:

MySQL的> SELECT keyring_key_generate('MyShortKey', 'DSA', 8);
+ ---------------------------------------------- +
| keyring_key_generate('MyShortKey','DSA',8)|
+ ---------------------------------------------- +
| 1 |
+ ---------------------------------------------- +
MySQL的> SELECT HEX(keyring_key_fetch('MyShortKey'));
+ -------------------------------------- +
| HEX(keyring_key_fetch('MyShortKey'))|
+ -------------------------------------- +
| 1DB3B0FC3328A24C |
+ -------------------------------------- +

密钥环UDF将密钥ID,类型和值视为二进制字符串,因此比较区分大小写。 例如,ID MyKey mykey 引用不同的键。

要删除密钥,请将密钥ID传递给 keyring_key_remove()

MySQL的> SELECT keyring_key_remove('MyKey');
+ ----------------------------- +
| keyring_key_remove('MyKey')|
+ ----------------------------- +
| 1 |
+ ----------------------------- +

要混淆和存储您提供的密钥,请将密钥ID,类型和值传递给 keyring_key_store()

MySQL的> SELECT keyring_key_store('AES_key', 'AES', 'Secret string');
+ ------------------------------------------------- ----- +
| keyring_key_store('AES_key','AES','秘密字符串')|
+ ------------------------------------------------- ----- +
| 1 |
+ ------------------------------------------------- ----- +

如前所述,用户必须具有 EXECUTE 调用密钥环UDF 的全局 特权,并且最初在密钥环中存储密钥的用户必须是稍后对密钥执行后续操作的同一用户,这取决于 CURRENT_USER() 对每个 密钥环的 有效值。 UDF调用。 要允许对没有全局 EXECUTE 权限或可能不是关键 所有者 ”的 用户进行关键操作,请 使用以下技术:

  1. 定义 包装器 存储的程序,这些程序封装了所需的键操作,其 DEFINER 值等于密钥所有者。

  2. EXECUTE 特定存储程序 权限 授予 应该能够调用它们的各个用户。

  3. 如果包装程序存储程序实现的操作不包括密钥创建,请使用名为 DEFINER 存储程序定义中 的帐户预先创建任何必需的密钥

这种技术使得密钥可以在用户之间共享,并为DBA提供更细粒度的控制,使他们可以使用密钥执行操作,而无需授予全局权限。

以下示例说明如何设置 SharedKey DBA拥有的 名为共享密钥 ,以及 get_shared_key() 提供对当前密钥值的访问权限 存储函数。 具有该 EXECUTE 功能特权 的任何用户都可以检索该值,该 特权是在 key_schema 架构中 创建的

从MySQL管理帐户( 'root'@'localhost' 在此示例中)中,创建管理模式和存储的函数以访问密钥:


MySQL的> CREATE SCHEMA key_schema;

MySQL的> CREATE DEFINER = 'root'@'localhost'
       FUNCTION key_schema.get_shared_key()
       RETURNS BLOB READS SQL DATA
       RETURN keyring_key_fetch('SharedKey');

从管理帐户中,确保共享密钥存在:

MySQL的> SELECT keyring_key_generate('SharedKey', 'DSA', 8);
+ --------------------------------------------- +
| keyring_key_generate('SharedKey','DSA',8)|
+ --------------------------------------------- +
| 1 |
+ --------------------------------------------- +

从管理帐户中,创建要授予密钥访问权限的普通用户帐户:


MySQL的> CREATE USER 'key_user'@'localhost'
       IDENTIFIED BY 'key_user_pwd';

从该 key_user 帐户验证,如果没有适当的 EXECUTE 权限,新帐户将无法访问共享密钥:

MySQL的> SELECT HEX(key_schema.get_shared_key());
ERROR 1370(42000):执行命令被拒绝用户'key_user'@'localhost'
用于例行'key_schema.get_shared_key'

从管理帐户,授 EXECUTE key_user 了存储功能:

MySQL的> GRANT EXECUTE ON FUNCTION key_schema.get_shared_key
       TO 'key_user'@'localhost';

key_user 帐户中,验证密钥现在是否可访问:

MySQL的> SELECT HEX(key_schema.get_shared_key());
+ ---------------------------------- +
| HEX(key_schema.get_shared_key())|
+ ---------------------------------- +
| 9BAFB9E75CEEB013 |
+ ---------------------------------- +
6.4.4.8.3通用密钥环功能参考

对于每个通用密钥环用户定义函数(UDF),本节描述其用途,调用顺序和返回值。 有关可以调用这些UDF的条件的信息,请参见 第6.4.4.8.2节“使用通用密钥环函数”

  • keyring_key_fetch(key_id)

    给定密钥ID,反混淆并返回密钥值。

    参数:

    • key_id :一个指定密钥ID的字符串。

    返回值:

    NULL 如果密钥不存在,则 返回键值作为成功字符串 ,或者返回 NULL 失败错误。

    注意

    keyring_key_fetch() 由于UDF接口的限制, 使用的密钥环值 限制为2,048字节。 可以使用密钥环服务函数存储长度超过该长度的密钥环值(请参见 第29.3.2节“密钥环服务” ),但如果使用 keyring_key_fetch() ,则截断为2,048字节。

    例:

    MySQL的> SELECT keyring_key_generate('RSA_key', 'RSA', 16);
    + -------------------------------------------- +
    | keyring_key_generate('RSA_key','RSA',16)|
    + -------------------------------------------- +
    | 1 |
    + -------------------------------------------- +
    MySQL的> SELECT HEX(keyring_key_fetch('RSA_key'));
    + ----------------------------------- +
    | HEX(keyring_key_fetch('RSA_key'))|
    + ----------------------------------- +
    | 91C2253B696064D3556984B6630F891A |
    + ----------------------------------- +
    MySQL的> SELECT keyring_key_type_fetch('RSA_key');
    + ----------------------------------- +
    | keyring_key_type_fetch('RSA_key')|
    + ----------------------------------- +
    | RSA |
    + ----------------------------------- +
    MySQL的> SELECT keyring_key_length_fetch('RSA_key');
    + ------------------------------- +
    | keyring_key_length_fetch('RSA_key')|
    + ------------------------------- +
    | 16 |
    + ------------------------------- +
    

    该示例用于 HEX() 显示键值,因为它可能包含不可打印的字符。 该示例还使用了一个简短的密钥,但请注意,较长的密钥可提供更好的安全性。

  • keyring_key_generate(key_id, key_type, key_length)

    生成具有给定ID,类型和长度的新随机密钥,并将其存储在密钥环中。 类型和长度值必须与底层密钥环插件支持的值一致,并且由于UDF接口的限制,密钥不能超过2,048字节(16,384位)的附加约束。 有关每个插件允许的类型,请参见 第29.3.2节“密钥环服务”

    参数:

    • key_id :一个指定密钥ID的字符串。

    • key_type :一个指定键类型的字符串。

    • key_length :一个整数,指定密钥长度(以字节为单位)。 最大长度为2,048。

    返回值:

    成功返回1,或 NULL 失败错误。

    例:

    MySQL的> SELECT keyring_key_generate('RSA_key', 'RSA', 384);
    + --------------------------------------------- +
    | keyring_key_generate('RSA_key','RSA',384)|
    + --------------------------------------------- +
    | 1 |
    + --------------------------------------------- +
    
  • keyring_key_length_fetch(key_id)

    给定密钥ID,返回密钥长度。

    参数:

    • key_id :一个指定密钥ID的字符串。

    返回值:

    NULL 如果密钥不存在,则 返回以字节为单位的密钥长度,作为成功的整数 ,或者 NULL 为失败而返回错误。

    例:

    请参阅说明 keyring_key_fetch()

  • keyring_key_remove(key_id)

    从密钥环中删除具有给定ID的密钥。

    参数:

    • key_id :一个指定密钥ID的字符串。

    返回值:

    成功或 NULL 失败 返回1

    例:

    MySQL的> SELECT keyring_key_remove('AES_key');
    + ------------------------------- +
    | keyring_key_remove('AES_key')|
    + ------------------------------- +
    | 1 |
    + ------------------------------- +
    
  • keyring_key_store(key_id, key_type, key)

    在密钥环中对密钥进行模糊处理和存储。

    参数:

    • key_id :一个指定密钥ID的字符串。

    • key_type :一个指定键类型的字符串。

    • key :一个指定键值的字符串。

    返回值:

    成功返回1,或 NULL 失败错误。

    例:

    MySQL的> SELECT keyring_key_store('new key', 'DSA', 'My key value');
    + ------------------------------------------------- ---- +
    | keyring_key_store('新密钥','DSA','我的密钥值')|
    + ------------------------------------------------- ---- +
    | 1 |
    + ------------------------------------------------- ---- +
    
  • keyring_key_type_fetch(key_id)

    给定密钥ID,返回密钥类型。

    参数:

    • key_id :一个指定密钥ID的字符串。

    返回值:

    NULL 如果密钥不存在,则 返回密钥类型作为成功字符串 ,或者返回 NULL 失败错误。

    例:

    请参阅说明 keyring_key_fetch()

6.4.4.9特定于插件的密钥环密钥管理功能

对于每个密钥环插件特定的用户定义函数(UDF),本节描述其用途,调用顺序和返回值。 有关通用密钥环UDF的信息,请参见 第6.4.4.8节“通用密钥环密钥管理功能”

  • keyring_aws_rotate_cmk()

    此UDF与 keyring_aws 插件 相关联 它的使用需要 SUPER 特权。

    keyring_aws_rotate_cmk() 旋转客户主密钥(CMK)。 轮换仅更改AWS KMS用于后续数据密钥加密操作的密钥。 AWS KMS维护以前的CMK版本,因此使用以前的CMK生成的密钥在轮换后仍可解密。

    轮换会更改AWS KMS内使用的CMK值,但不会更改用于引用它的ID,因此无需 keyring_aws_cmk_id 在调用后 更改 系统变量 keyring_aws_rotate_cmk()

    参数:

    没有。

    返回值:

    成功返回1,或 NULL 失败错误。

  • keyring_aws_rotate_keys()

    此UDF与 keyring_aws 插件 相关联 它的使用需要 SUPER 特权。

    keyring_aws_rotate_keys() 旋转存储在 系统变量 keyring_aws 命名 存储文件 中的密钥 keyring_aws_data_file 旋转将存储在文件中的每个密钥发送到AWS KMS,以使用 keyring_aws_cmk_id 系统变量的值作为CMK值 进行重新加密 ,并将新的加密密钥存储在文件中。

    keyring_aws_rotate_keys() 在这些情况下对密钥重新加密很有用:

    参数:

    没有。

    返回值:

    成功返回1,或 NULL 失败错误。

6.4.4.10密钥环命令选项

MySQL支持以下与密钥环相关的命令行选项:

6.4.4.11密钥环系统变量

MySQL Keyring插件支持以下系统变量。 使用它们配置密钥环插件操作。 除非安装了适当的密钥环插件,否则这些变量不可用(请参见 第6.4.4.1节“密钥环插件安装” )。

  • keyring_aws_cmk_id

    属性
    命令行格式 --keyring-aws-cmk-id=value
    介绍 8.0.11
    系统变量 keyring_aws_cmk_id
    范围 全球
    动态
    SET_VAR 提示适用 没有
    类型

    从AWS KMS服务器获取并由 keyring_aws 插件 使用的客户主密钥(CMK)ID 除非安装了该插件,否则此变量不可用,但如果已安装,则此变量的值是必需的。

  • keyring_aws_conf_file

    属性
    命令行格式 --keyring-aws-conf-file=file_name
    介绍 8.0.11
    系统变量 keyring_aws_conf_file
    范围 全球
    动态 没有
    SET_VAR 提示适用 没有
    类型 文件名
    默认值 platform specific

    keyring_aws 密钥环插件 的配置文件的位置 除非安装了该插件,否则此变量不可用。

    在插件启动时, keyring_aws 从配置文件中读取AWS秘密访问密钥ID和密钥。 要使 keyring_aws 插件成功启动,配置文件必须存在且包含有效的秘密访问密钥信息,如上所述进行初始化 第6.4.4.5节“使用keyring_aws Amazon Web Services密钥环插件”中

    默认文件名 keyring_aws_conf 位于默认密钥环文件目录中。 此默认目录的位置与 keyring_file_data 系统变量 的位置相同 有关详细信息,请参阅该变量的说明,以及在手动创建目录时要考虑的注意事项。

  • keyring_aws_data_file

    属性
    命令行格式 --keyring-aws-data-file
    介绍 8.0.11
    系统变量 keyring_aws_data_file
    范围 全球
    动态 没有
    SET_VAR 提示适用 没有
    类型 文件名
    默认值 platform specific

    keyring_aws 密钥环插件 的存储文件的位置 除非安装了该插件,否则此变量不可用。

    在插件启动时,如果 keyring_aws_data_file 指定 的值 指定了不存在的文件,则 keyring_aws 插件会尝试创建它(如果需要,还会创建其父目录)。 如果文件存在,则将文件中 keyring_aws 包含的任何加密密钥读入其内存缓存中。 keyring_aws 不会将未加密的密钥缓存在内存中。

    默认文件名 keyring_aws_data 位于默认密钥环文件目录中。 此默认目录的位置与 keyring_file_data 系统变量 的位置相同 有关详细信息,请参阅该变量的说明,以及在手动创建目录时要考虑的注意事项。

  • keyring_aws_region

    属性
    命令行格式 --keyring-aws-region=value
    介绍 8.0.11
    系统变量 keyring_aws_region
    范围 全球
    动态
    SET_VAR 提示适用 没有
    类型 列举
    默认值 us-east-1
    有效值

    ap-northeast-1

    ap-northeast-2

    ap-south-1

    ap-southeast-1

    ap-southeast-2

    eu-central-1

    eu-west-1

    sa-east-1

    us-east-1

    us-west-1

    us-west-2

    AWS区域。

  • keyring_encrypted_file_data

    属性
    命令行格式 --keyring-encrypted-file-data=file_name
    介绍 8.0.11
    系统变量 keyring_encrypted_file_data
    范围 全球
    动态
    SET_VAR 提示适用 没有
    类型 文件名
    默认值 platform specific

    keyring_encrypted_file 插件 用于安全数据存储的数据文件的路径名 除非安装了该插件,否则此变量不可用。 文件位置应位于仅供密钥环插件使用的目录中。 例如,不要将文件放在数据目录下。

    密钥环操作是事务性的: keyring_encrypted_file 插件在写入操作期间使用备份文件,以确保在操作失败时它可以回滚到原始文件。 备份文件的名称与 keyring_encrypted_file_data 系统变量 的值相同 ,后缀为 .backup

    不要 keyring_encrypted_file 对多个MySQL实例 使用相同的 数据文件。 每个实例都应该有自己唯一的数据文件。

    默认文件名 keyring_encrypted 位于特定于平台的目录中,并且取决于 CMake 选项 的值, 如下表所示。 如果要从源构建,请显式指定文件的默认目录,请使用 CMake 选项。 INSTALL_LAYOUT INSTALL_MYSQLKEYRINGDIR

    INSTALL_LAYOUT 默认 keyring_encrypted_file_data
    DEB RPM SLES SVR4 /var/lib/mysql-keyring/keyring_encrypted
    除此以外 keyring/keyring_encrypted CMAKE_INSTALL_PREFIX 价值 之下

    在插件启动时,如果 keyring_encrypted_file_data 指定 的值 指定了不存在的文件,则 keyring_encrypted_file 插件会尝试创建它(如果需要,还会创建其父目录)。

    如果手动创建目录,它应该具有限制模式,并且只能用于运行MySQL服务器的帐户。 例如,在Unix和类Unix系统上,要使用该 /usr/local/mysql/mysql-keyring 目录,以下命令(执行为 root )创建目录并设置其模式和所有权:

    cd / usr / local / mysql
    mkdir mysql-keyring
    chmod 750 mysql-keyring
    chown mysql mysql-keyring
    chgrp mysql mysql-keyring
    

    如果 keyring_encrypted_file 插件无法创建或访问其数据文件,它会将错误消息写入错误日志。 如果尝试运行时分配 keyring_encrypted_file_data 导致错误,则变量值保持不变。

    重要

    一旦 keyring_encrypted_file 插件创建了其数据文件并开始使用它,重要的是不要删除该文件。 丢失文件将导致使用其密钥加密的数据无法访问。 (只要您更改 keyring_encrypted_file_data 要匹配 的值, 可以重命名或移动文件 。)

  • keyring_encrypted_file_password

    属性
    命令行格式 --keyring-encrypted-file-password=password
    介绍 8.0.11
    系统变量 keyring_encrypted_file_password
    范围 全球
    动态
    SET_VAR 提示适用 没有
    类型

    keyring_encrypted_file 插件 使用的密码 除非安装了该插件,否则此变量不可用。 密码是插件操作必需的; 如果未在服务器启动时指定,则 keyring_encrypted_file 初始化失败。

    如果在选项文件中指定了此变量,则该文件应具有限制模式,并且只能由用于运行MySQL服务器的帐户访问。

    重要

    一旦 keyring_encrypted_file_password 值已定,改变它不转动钥匙圈密码,可以使服务器无法访问。 如果提供的密码不正确,则 keyring_encrypted_file 插件无法从加密的密钥环文件加载密钥。

    密码值无法在运行时使用 SHOW VARIABLES Performance Schena global_variables 表显示,因为显示值已经过模糊处理。

  • keyring_file_data

    属性
    命令行格式 --keyring-file-data=file_name
    系统变量 keyring_file_data
    范围 全球
    动态
    SET_VAR 提示适用 没有
    类型 文件名
    默认值 platform specific

    keyring_file 插件 用于安全数据存储的数据文件的路径名 除非安装了该插件,否则此变量不可用。 文件位置应位于仅供密钥环插件使用的目录中。 例如,不要将文件放在数据目录下。

    密钥环操作是事务性的: keyring_file 插件在写入操作期间使用备份文件,以确保在操作失败时它可以回滚到原始文件。 备份文件的名称与 keyring_file_data 系统变量 的值相同 ,后缀为 .backup

    不要 keyring_file 对多个MySQL实例 使用相同的 数据文件。 每个实例都应该有自己唯一的数据文件。

    默认文件名 keyring 位于特定于平台的目录中,并且取决于 CMake 选项 的值, 如下表所示。 如果要从源构建,请显式指定文件的默认目录,请使用 CMake 选项。 INSTALL_LAYOUT INSTALL_MYSQLKEYRINGDIR

    INSTALL_LAYOUT 默认 keyring_file_data
    DEB RPM SLES SVR4 /var/lib/mysql-keyring/keyring
    除此以外 keyring/keyring CMAKE_INSTALL_PREFIX 价值 之下

    在插件启动时,如果 keyring_file_data 指定 的值 指定了不存在的文件,则 keyring_file 插件会尝试创建它(如果需要,还会创建其父目录)。

    如果手动创建目录,它应该具有限制模式,并且只能用于运行MySQL服务器的帐户。 例如,在Unix和类Unix系统上,要使用该 /usr/local/mysql/mysql-keyring 目录,以下命令(执行为 root )创建目录并设置其模式和所有权:

    cd / usr / local / mysql
    mkdir mysql-keyring
    chmod 750 mysql-keyring
    chown mysql mysql-keyring
    chgrp mysql mysql-keyring
    

    如果 keyring_file 插件无法创建或访问其数据文件,它会将错误消息写入错误日志。 如果尝试运行时分配 keyring_file_data 导致错误,则变量值保持不变。

    重要

    一旦 keyring_file 插件创建了其数据文件并开始使用它,重要的是不要删除该文件。 例如, InnoDB 使用该文件存储用于解密使用 InnoDB 表空间加密的 表中的数据的主密钥 ; 请参见 第15.6.3.9节“InnoDB静态数据加密” 丢失文件将导致此类表中的数据无法访问。 (只要更改了值,就可以重命名或移动文件 keyring_file_data 匹配。)建议您在创建第一个加密表之后以及主密钥轮换之前和之后立即创建密钥环数据文件的单独备份。

  • keyring_okv_conf_dir

    属性
    命令行格式 --keyring-okv-conf-dir=dir_name
    介绍 8.0.11
    系统变量 keyring_okv_conf_dir
    范围 全球
    动态
    SET_VAR 提示适用 没有
    类型 目录名称
    默认值 empty string

    存储 keyring_okv 插件 使用的配置信息的目录的路径名 除非安装了该插件,否则此变量不可用。 该位置应该是仅供 keyring_okv 插件 使用的目录 例如,不要在数据目录下找到该目录。

    默认 keyring_okv_conf_dir 值为空。 要使 keyring_okv 插件能够访问Oracle Key Vault,必须将该值设置为包含Oracle Key Vault配置和SSL材料的目录。 有关设置此目录的说明,请参见 第6.4.4.4节“使用keyring_okv KMIP插件”

    该目录应具有限制模式,并且只能用于运行MySQL服务器的帐户。 例如,在Unix和类Unix系统上,要使用该 /usr/local/mysql/mysql-keyring-okv 目录,以下命令(执行为 root )创建目录并设置其模式和所有权:

    cd / usr / local / mysql
    mkdir mysql-keyring-okv
    chmod 750 mysql-keyring-okv
    chown mysql mysql-keyring-okv
    chgrp mysql mysql-keyring-okv
    

    如果 keyring_okv_conf_dir 指定 的值 指定了不存在的目录,或者不包含允许建立与Oracle Key Vault连接的配置信息, keyring_okv 则会将错误消息写入错误日志。 如果尝试运行时分配 keyring_okv_conf_dir 导致错误,则变量值和密钥环操作保持不变。

  • keyring_operations

    属性
    介绍 8.0.4
    系统变量 keyring_operations
    范围 全球
    动态
    SET_VAR 提示适用 没有
    类型 布尔
    默认值 ON

    是否启用密钥环操作。 在密钥迁移操作期间使用此变量。 请参见 第6.4.4.6节“在密钥环密钥库之间迁移密钥” 修改此变量所需的权限是 ENCRYPTION_KEY_ADMIN 其中之一 SYSTEM_VARIABLES_ADMIN SUPER

6.4.5 MySQL企业审计

注意

MySQL Enterprise Audit是商业产品MySQL企业版中的扩展。 要了解有关商业产品的更多信息,请访问 https://www.mysql.com/products/

MySQL企业版包括MySQL Enterprise Audit,使用名为的服务器插件实现 audit_log MySQL Enterprise Audit使用开放的MySQL Audit API来启用标准的,基于策略的监视,记录和阻止在特定MySQL服务器上执行的连接和查询活动。 MySQL Enterprise Audit旨在满足Oracle审计规范,为受内部和外部监管准则管理的应用程序提供开箱即用,易于使用的审计和合规性解决方案。

安装后,审计插件使MySQL Server能够生成包含服务器活动审计记录的日志文件。 日志内容包括客户端连接和断开连接的时间,以及它们在连接时执行的操作,例如它们访问的数据库和表。

安装审计插件后(请参见 第6.4.5.2节“安装或卸载MySQL Enterprise Audit” ),它会写入审计日志文件。 默认情况下,该文件 audit.log 在服务器数据目录中 命名 要更改文件名,请设置 audit_log_file 在服务器启动时 系统变量。

默认情况下,审核日志文件内容以新式XML格式编写,无需压缩或加密。 要选择文件格式,请 audit_log_format 在服务器启动时 设置 系统变量。 有关文件格式和内容的详细信息,请参见 第6.4.5.4节“审核日志文件格式”

有关控制日志记录方式的更多信息,包括审计日志文件命名和格式选择,请参见 第6.4.5.5节“审计日志记录配置” 要对审计事件执行过滤,请参见 第6.4.5.6节“审计日志过滤” 有关用于配置审核日志插件的参数的说明,请参见 第6.4.5.8.4节“审核日志选项和变量”

如果启用了审计日志插件,则为性能架构(请参见 第26章, MySQL性能架构 )会为其提供工具。 要识别相关工具,请使用以下查询:

从performance_schema.setup_instruments中选择名称
名称在哪里'%/ alog /%';

6.4.5.1审核日志组件

MySQL Enterprise Audit基于审计日志插件和相关组件:

  • 名为的服务器端插件 audit_log 检查可审计事件,并确定是否将它们写入审核日志。

  • 用户定义的函数可以处理控制日志记录行为,加密密码和日志文件读取的过滤定义。

  • mysql 系统数据库 中的表 提供过滤器和用户帐户数据的持久存储。

  • 系统变量使审计日志配置和状态变量能够提供运行时操作信息。

  • 一个 AUDIT_ADMIN 特权使用户能够管理审计日志。

6.4.5.2安装或卸载MySQL Enterprise Audit

本节介绍如何安装或卸载MySQL Enterprise Audit,它是使用 第6.4.5.1节“审核日志组件”中 所述的审核日志插件和相关组件实现的 有关安装插件的一般信息,请参见 第5.6.1节“安装和卸载插件”

重要

按照说明阅读完整部分。 部分程序因环境而异。

注意

如果已安装, audit_log 即使禁用 插件也会涉及一些最小的开销。 为避免此开销,请不要安装MySQL Enterprise Audit,除非您打算使用它。

要使服务器可以使用,插件库文件必须位于MySQL插件目录( plugin_dir 系统变量 指定的目录 )中。 如有必要,通过设置 plugin_dir 服务器启动时 的值来配置插件目录位置

要安装MySQL Enterprise Audit,请查看 share MySQL安装目录并选择适合您平台的脚本。 可用脚本的不同之处在于用于引用插件库文件的后缀:

  • audit_log_filter_win_install.sql :为 .dll 用作文件名后缀的 Windows系统选择此脚本

  • audit_log_filter_linux_install.sql :为Linux和类似系统选择此脚本, .so 用作文件名后缀。

运行脚本如下。 此处的示例使用Linux安装脚本。 为您的系统进行适当的替换。

shell> mysql -u root -p < audit_log_filter_linux_install.sql
输入密码:(enter root password here)
注意

一些MySQL版本引入了对MySQL Enterprise Audit表结构的更改。 要确保您的表是从早期版本的MySQL 8.0升级的最新表,请执行MySQL升级过程,确保使用强制更新的选项(请参见 第2.11节“升级MySQL” )。 如果您更喜欢仅为MySQL Enterprise Audit表运行update语句,请参阅以下讨论。

从MySQL 8.0.12开始,对于新的MySQL安装, MySQL Enterprise Audit使用 表中的 USER HOST audit_log_user 具有更好地对应 系统表中 User Host 的定义的定义 mysql.user 要升级已安装MySQL Enterprise Audit的安装,建议您更改表定义,如下所示:

ALTER TABLE mysql.audit_log_user
  DROP FOREIGN KEY audit_log_user_ibfk_1;
ALTER TABLE mysql.audit_log_filter
  CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_as_ci;
ALTER TABLE mysql.audit_log_user
  CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_as_ci;
ALTER TABLE mysql.audit_log_user
  MODIFY COLUMN USER VARCHAR(32);
ALTER TABLE mysql.audit_log_user
  添加外键(FILTERNAME)参考mysql.audit_log_filter(NAME);
注意

要在主/从复制,组复制或InnoDB集群的上下文中使用MySQL Enterprise Audit,必须在主节点或主节点上运行安装脚本之前准备从节点或辅助节点。 这是必要的,因为 INSTALL PLUGIN 脚本中 语句不会被复制。

  1. 在每个从属节点或辅助节点上, INSTALL PLUGIN 从安装脚本中 提取 语句并手动执行。

  2. 在主节点或主节点上,按前面所述运行安装脚本。

要验证插件安装,请检查 INFORMATION_SCHEMA.PLUGINS 表或使用该 SHOW PLUGINS 语句(请参见 第5.6.2节“获取服务器插件信息” )。 例如:

MySQL的> SELECT PLUGIN_NAME, PLUGIN_STATUS
       FROM INFORMATION_SCHEMA.PLUGINS
       WHERE PLUGIN_NAME LIKE 'audit%';
+ ------------- + --------------- +
| PLUGIN_NAME | PLUGIN_STATUS |
+ ------------- + --------------- +
| audit_log | ACTIVE |
+ ------------- + --------------- +

如果插件无法初始化,请检查服务器错误日志以获取诊断消息。

安装MySQL Enterprise Audit后,您可以使用该 --audit-log 选项来控制后续服务器启动 audit_log 插件激活。 例如,要防止在运行时删除插件,请使用以下选项:

的[mysqld]
审计日志= FORCE_PLUS_PERMANENT

如果希望在没有审计插件的情况下阻止服务器运行,请使用 --audit-log 值为 FORCE FORCE_PLUS_PERMANENT 强制服务器启动失败,如果插件未成功初始化。

重要

默认情况下,基于规则的审核日志筛选不会为任何用户记录可审核事件。 这与传统审核日志行为不同,后者记录所有用户的所有可审核事件(请参见 第6.4.5.7节“传统模式审核日志过滤” )。 如果您希望使用基于规则的过滤生成日志行为,请创建一个简单的过滤器以启用日志记录并将其分配给默认帐户:

SELECT audit_log_filter_set_filter('log_all','{“filter”:{“log”:true}}');
SELECT audit_log_filter_set_user('%','log_all');

分配给的过滤器 % 用于来自任何未明确分配过滤器的帐户的连接(最初对所有帐户都是如此)。

如上所述安装后,MySQL Enterprise Audit将一直安装,直到卸载为止。 要删除它,请执行以下语句:

DROP TABLE IF EXISTS mysql.audit_log_user;
DROP TABLE IF EXISTS mysql.audit_log_filter;
UNINSTALL PLUGIN audit_log;
DROP FUNCTION audit_log_filter_set_filter;
DROP FUNCTION audit_log_filter_remove_filter;
DROP FUNCTION audit_log_filter_set_user;
DROP FUNCTION audit_log_filter_remove_user;
DROP FUNCTION audit_log_filter_flush;
DROP FUNCTION audit_log_encryption_password_get;
DROP FUNCTION audit_log_encryption_password_set;
DROP FUNCTION audit_log_read;
DROP FUNCTION audit_log_read_bookmark;

6.4.5.3 MySQL企业审计安全注意事项

默认情况下,审计日志插件生成的审计日志文件的内容未加密,可能包含敏感信息,例如SQL语句的文本。 出于安全原因,审计日志文件应写入只能由MySQL服务器访问的目录以及具有查看日志的合法理由的用户。 默认文件名 audit.log 位于数据目录中。 这可以通过 audit_log_file 在服务器启动时 设置 系统变量 来更改 由于日志轮换,可能存在其他审核日志文件。

为了提高安全性,请启用审核日志文件加密。 请参阅 审核日志文件加密

6.4.5.4审核日志文件格式

只要发生可审计事件,MySQL服务器就会调用审计日志插件将审计记录写入其日志文件。 通常,插件启动后编写的第一个审计记录包含服务器描述和启动选项。 后面的元素表示客户端连接和断开连接事件,执行的SQL语句等事件。 仅记录顶级语句,而不记录存储程序(如触发器或存储过程)中的语句。 语句引用的文件内容( LOAD DATA 如未记录)。

要选择审核日志插件用于写入其日志文件的日志格式,请 audit_log_format 在服务器启动时 设置 系统变量。 这些格式可用:

  • 新式XML格式( audit_log_format=NEW ):与旧式XML格式相比,与Oracle Audit Vault具有更好兼容性的XML格式。 MySQL 8.0默认使用新式XML格式。

  • 旧式XML格式( audit_log_format=OLD ):旧MySQL系列中默认使用的原始审核日志格式。

  • JSON格式( audit_log_format=JSON

默认情况下,审核日志文件内容以新式XML格式编写,无需压缩或加密。

注意

有关更改日志格式时要考虑的问题的信息,请参阅 审核日志文件格式

以下部分描述了可用的审计日志记录格式:

新式XML审核日志文件格式

这是一个新格式XML格式的示例日志文件( audit_log_format=NEW ),为了便于阅读,稍微重新格式化:

<?xml version =“1.0”encoding =“utf-8”?>
<AUDIT>
 <AUDIT_RECORD>
  <TIMESTAMP> 2017-10-16T14:06:33 UTC </ TIMESTAMP>
  <RECORD_ID> 1_2017-10-16T14:06:33 </ RECORD_ID>
  <NAME>审核</ NAME>
  <SERVER_ID> 1 </ SERVER_ID>
  <VERSION> 1 </ VERSION>
  <STARTUP_OPTIONS>的/ usr /本地/ MySQL的/斌/ mysqld的
    --socket =的/ usr /本地/ MySQL的/的mysql.sock
    --port = 3306 </ STARTUP_OPTIONS>
  <OS_VERSION> i686的Linux的</ OS_VERSION>
  <MYSQL_VERSION> 21年5月7日日志</ MYSQL_VERSION>
 </ AUDIT_RECORD>
 <AUDIT_RECORD>
  <TIMESTAMP> 2017-10-16T14:09:38 UTC </ TIMESTAMP>
  <RECORD_ID> 2_2017-10-16T14:06:33 </ RECORD_ID>
  <名称>连接</ NAME>
  <CONNECTION_ID> 5 </ CONNECTION_ID>
  <STATUS> 0 </ STATUS>
  <STATUS_CODE> 0 </ STATUS_CODE>
  <USER>根</ USER>
  <OS_LOGIN />
  <HOST>本地主机</ HOST>
  <IP> 127.0.0.1 </ IP>
  <COMMAND_CLASS>连接</ COMMAND_CLASS>
  <CONNECTION_TYPE> SSL / TLS </ CONNECTION_TYPE>
  <PRIV_USER>根</ PRIV_USER>
  <PROXY_USER />
  <DB>测试</ DB>
 </ AUDIT_RECORD>

...

 <AUDIT_RECORD>
  <TIMESTAMP> 2017-10-16T14:09:38 UTC </ TIMESTAMP>
  <RECORD_ID> 6_2017-10-16T14:06:33 </ RECORD_ID>
  <NAME>查询</ NAME>
  <CONNECTION_ID> 5 </ CONNECTION_ID>
  <STATUS> 0 </ STATUS>
  <STATUS_CODE> 0 </ STATUS_CODE>
  <USER> root [root] @ localhost [127.0.0.1] </ USER>
  <OS_LOGIN />
  <HOST>本地主机</ HOST>
  <IP> 127.0.0.1 </ IP>
  <COMMAND_CLASS> drop_table </ COMMAND_CLASS>
  <SQLTEXT> DROP TABLE IF EXISTS t </ SQLTEXT>
 </ AUDIT_RECORD>

...

 <AUDIT_RECORD>
  <TIMESTAMP> 2017-10-16T14:09:39 UTC </ TIMESTAMP>
  <RECORD_ID> 8_2017-10-16T14:06:33 </ RECORD_ID>
  <NAME>退出</ NAME>
  <CONNECTION_ID> 5 </ CONNECTION_ID>
  <STATUS> 0 </ STATUS>
  <STATUS_CODE> 0 </ STATUS_CODE>
  <USER>根</ USER>
  <OS_LOGIN />
  <HOST>本地主机</ HOST>
  <IP> 127.0.0.1 </ IP>
  <COMMAND_CLASS>连接</ COMMAND_CLASS>
  <CONNECTION_TYPE> SSL / TLS </ CONNECTION_TYPE>
 </ AUDIT_RECORD>

...

 <AUDIT_RECORD>
  <TIMESTAMP> 2017-10-16T14:09:43 UTC </ TIMESTAMP>
  <RECORD_ID> 11_2017-10-16T14:06:33 </ RECORD_ID>
  <NAME>退出</ NAME>
  <CONNECTION_ID> 6 </ CONNECTION_ID>
  <STATUS> 0 </ STATUS>
  <STATUS_CODE> 0 </ STATUS_CODE>
  <USER>根</ USER>
  <OS_LOGIN />
  <HOST>本地主机</ HOST>
  <IP> 127.0.0.1 </ IP>
  <COMMAND_CLASS>连接</ COMMAND_CLASS>
  <CONNECTION_TYPE> SSL / TLS </ CONNECTION_TYPE>
 </ AUDIT_RECORD>
 <AUDIT_RECORD>
  <TIMESTAMP> 2017-10-16T14:09:45 UTC </ TIMESTAMP>
  <RECORD_ID> 12_2017-10-16T14:06:33 </ RECORD_ID>
  <NAME> NOAUDIT </ NAME>
  <SERVER_ID> 1 </ SERVER_ID>
 </ AUDIT_RECORD>
</ AUDIT>

审计日志文件使用UTF-8(每个字符最多4个字节)写为XML。 根元素是 <AUDIT> 根元素包含 <AUDIT_RECORD> 元素,每个元素都提供有关审计事件的信息。 当审计日志插件开始编写新的日志文件时,它会写入XML声明并打开 <AUDIT> 根元素标记。 当插件关闭日志文件时,它会写入关闭的 </AUDIT> 根元素标记。 文件打开时,结束标记不存在。

元素中的 <AUDIT_RECORD> 元素具有以下特征:

  • 一些元素出现在每个 <AUDIT_RECORD> 元素中。 其他是可选的,可能会出现,具体取决于审计记录类型。

  • <AUDIT_RECORD> 不保证 元素内 元素的 顺序

  • 元素值不是固定长度。 如稍后给出的元素描述中所示,可以截断长值。

  • < > " ,和 & 字符被编码为 &lt; &gt; &quot; ,和 &amp; ,分别。 NUL字节(U + 00)被编码为 ? 字符。

  • 无效为XML字符的字符使用数字字符引用进行编码。 有效的XML字符是:

    #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
    

以下元素在每个元素中都是必需的 <AUDIT_RECORD>

  • <NAME>

    一个字符串,表示生成审计事件的指令类型,例如服务器从客户端收到的命令。

    例:

    <NAME>查询</ NAME>
    

    一些共同的 <NAME> 价值:

    审计启动审计时,可能是服务器启动时间
    连接当客户端连接时,也称为登录
    查询SQL语句(直接执行)
    准备SQL语句的准备; 通常后跟Execute
    执行SQL语句的执行; 通常遵循准备
    关机服务器关机
    退出当客户端断开连接时
    NoAudit审计已被关闭
    

    可能的值是 Audit Binlog Dump Change user Close stmt Connect Out Connect Create DB Daemon Debug Delayed insert Drop DB Execute Fetch Field List Init DB Kill Long Data NoAudit Ping Prepare Processlist Query Quit Refresh Register Slave Reset stmt Set option Shutdown Sleep Statistics Table Dump Time

    除了 Audit 和之外 NoAudit ,这些值对应 头文件中 列出 命令值 例如, 对应于 分别。 COM_xxx my_command.h Create DB Change user COM_CREATE_DB COM_CHANGE_USER

  • <RECORD_ID>

    审计记录的唯一标识符。 该值由格式中的序列号和时间戳组成 SEQ_TIMESTAMP 当审核日志插件打开审核日志文件时,它会将序列号初始化为审核日志文件的大小,然后为记录的每个记录将序列递增1。 时间戳是UTC值, 格式表示审核日志插件打开文件的日期和时间。 YYYY-MM-DDThh:mm:ss

    例:

    <RECORD_ID> 12_2017-10-16T14:06:33 </ RECORD_ID>
    
  • <TIMESTAMP>

    一个字符串,表示 格式 的UTC值, 表示生成审计事件的日期和时间。 例如,与从客户端接收的SQL语句的执行相对应的事件具有 在语句结束之后而不是在语句结束时发生 值。 YYYY-MM-DDThh:mm:ss UTC <TIMESTAMP>

    例:

    <TIMESTAMP> 2017-10-16T14:09:45 UTC </ TIMESTAMP>
    

以下元素在 <AUDIT_RECORD> 元素中 是可选的 其中许多只出现特定的 <NAME> 元素值。

  • <COMMAND_CLASS>

    一个字符串,指示执行的操作类型。

    例:

    <COMMAND_CLASS> drop_table </ COMMAND_CLASS>
    

    值对应于 命令计数器。 例如, is for 语句分别。 以下语句显示可能的名称: statement/sql/xxx xxx drop_table select DROP TABLE SELECT

    SELECT REPLACE(EVENT_NAME,'statement / sql /','')AS名称
    FROM performance_schema.events_statements_summary_global_by_event_name
    在哪里EVENT_NAME LIKE'statement / sql /%'
    按名称订购;
    
  • <CONNECTION_ID>

    表示客户端连接标识符的无符号整数。 CONNECTION_ID() 与会话中函数 返回的值相同

    例:

    <CONNECTION_ID> 127 </ CONNECTION_ID>
    
  • <CONNECTION_TYPE>

    与服务器连接的安全状态。 允许的值是 TCP/IP (未加密建立TCP / IP连接), SSL/TLS (通过加密建立TCP / IP连接), Socket (Unix套接字文件连接), Named Pipe (Windows命名管道连接)和 Shared Memory (Windows共享内存连接)。

    例:

    <CONNECTION_TYPE> SSL / TLS </ CONNECTION_TYPE>
    
  • <DB>

    表示默认数据库名称的字符串。

    例:

    <DB>测试</ DB>
    
  • <HOST>

    表示客户端主机名的字符串。

    例:

    <HOST>本地主机</ HOST>
    
  • <IP>

    表示客户端IP地址的字符串。

    例:

    <IP> 127.0.0.1 </ IP>
    
  • <MYSQL_VERSION>

    表示MySQL服务器版本的字符串。 这与 VERSION() 函数或 version 系统变量 的值相同

    例:

    <MYSQL_VERSION> 21年5月7日日志</ MYSQL_VERSION>
    
  • <OS_LOGIN>

    一个字符串,表示在身份验证过程中使用的外部用户名,由用于验证客户端的插件设置。 使用本机(内置)MySQL身份验证,或者如果插件未设置该值,则此元素为空。 该值与 external_user 系统变量 的值相同 (请参见 第6.2.18节“代理用户” )。

    例:

    <OS_LOGIN>杰弗里</ OS_LOGIN>
    
  • <OS_VERSION>

    一个字符串,表示构建或正在运行服务器的操作系统。

    例:

    <OS_VERSION> x86_64的Linux的</ OS_VERSION>
    
  • <PRIV_USER>

    表示服务器对客户端进行身份验证的用户的字符串。 这是服务器用于权限检查的用户名,可能与 <USER> 不同

    例:

    <PRIV_USER>杰弗里</ PRIV_USER>
    
  • <PROXY_USER>

    表示代理用户的字符串(请参见 第6.2.18节“代理用户” )。 如果用户代理无效,则该值为空。

    例:

    <PROXY_USER>显影剂</ PROXY_USER>
    
  • <SERVER_ID>

    表示服务器ID的无符号整数。 这与 server_id 系统变量 的值相同

    例:

    <SERVER_ID> 1 </ SERVER_ID>
    
  • <SQLTEXT>

    表示SQL语句文本的字符串。 该值可以为空。 长值可能会被截断。 与审计日志文件本身一样,字符串使用UTF-8(每个字符最多4个字节)写入,因此该值可能是转换的结果。 例如,原始语句可能已作为SJIS字符串从客户端收到。

    例:

    <SQLTEXT> DELETE FROM t1 </ SQLTEXT>
    
  • <STARTUP_OPTIONS>

    一个字符串,表示MySQL服务器启动时在命令行或选项文件中给出的选项。 第一个选项是服务器可执行文件的路径。

    例:

    <STARTUP_OPTIONS>的/ usr /本地/ MySQL的/斌/ mysqld的
      --port = 3306 --log_output = FILE </ STARTUP_OPTIONS>
    
  • <STATUS>

    表示命令状态的无符号整数:0表示成功,非零表示发生错误。 这与 mysql_errno() C API函数 的值相同 有关 <STATUS_CODE> 它的不同之处, 请参阅说明 <STATUS>

    审核日志不包含SQLSTATE值或错误消息。 要查看错误代码,SQLSTATE值和消息之间的关联,请参见 第B.3.1节“服务器错误消息参考”

    不记录警告。

    例:

    <STATUS> 1051 </ STATUS>
    
  • <STATUS_CODE>

    表示命令状态的无符号整数:0表示成功,1表示发生错误。

    STATUS_CODE 值与值不同 STATUS STATUS_CODE 成功为0,错误为1,与Audit Vault的EZ_collector使用者兼容。 STATUS mysql_errno() C API函数 的值 成功时为0,错误为非零,因此错误不一定为1。

    例:

    <STATUS_CODE> 0 </ STATUS_CODE>
    
  • <USER>

    表示客户端发送的用户名的字符串。 这可能与 <PRIV_USER> 价值 不同

    例:

    <USER> root [root] @ localhost [127.0.0.1] </ USER>
    
  • <VERSION>

    无符号整数,表示审计日志文件格式的版本。

    例:

    <VERSION> 1 </ VERSION>
    
旧式XML审核日志文件格式

以下是旧式XML格式( audit_log_format=OLD 的示例日志文件, 为了便于阅读,略微重新格式化:

<?xml version =“1.0”encoding =“utf-8”?>
<AUDIT>
  <AUDIT_RECORD
    TIMESTAMP =“2017-10-16T14:25:00 UTC”
    RECORD_ID = “1_2017-10-16T14:25:00”
    NAME = “审计”
    SERVER_ID = “1”
    VERSION = “1”
    STARTUP_OPTIONS = “ - 端口= 3306”
    OS_VERSION = “i686的Linux的”
    MYSQL_VERSION = “21年5月7日日志”/>
  <AUDIT_RECORD
    TIMESTAMP =“2017-10-16T14:25:24 UTC”
    RECORD_ID = “2_2017-10-16T14:25:00”
    NAME = “连接”
    CONNECTION_ID = “4”
    STATUS = “0”
    STATUS_CODE = “0”
    USER = “根”
    OS_LOGIN = “”
    HOST = “本地主机”
    IP = “127.0.0.1”
    COMMAND_CLASS = “连接”
    CONNECTION_TYPE = “SSL / TLS”
    PRIV_USER = “根”
    PROXY_USER = “”
    DB = “测试”/>

...

  <AUDIT_RECORD
    TIMESTAMP =“2017-10-16T14:25:24 UTC”
    RECORD_ID = “6_2017-10-16T14:25:00”
    NAME = “查询”
    CONNECTION_ID = “4”
    STATUS = “0”
    STATUS_CODE = “0”
    USER =“root [root] @ localhost [127.0.0.1]”
    OS_LOGIN = “”
    HOST = “本地主机”
    IP = “127.0.0.1”
    COMMAND_CLASS = “drop_table”
    SQLTEXT =“DROP TABLE IF EXISTS t”/>

...

  <AUDIT_RECORD
    TIMESTAMP =“2017-10-16T14:25:24 UTC”
    RECORD_ID = “8_2017-10-16T14:25:00”
    NAME = “退出”
    CONNECTION_ID = “4”
    STATUS = “0”
    STATUS_CODE = “0”
    USER = “根”
    OS_LOGIN = “”
    HOST = “本地主机”
    IP = “127.0.0.1”
    COMMAND_CLASS = “连接”
    CONNECTION_TYPE = “SSL / TLS”/>
  <AUDIT_RECORD
    TIMESTAMP =“2017-10-16T14:25:32 UTC”
    RECORD_ID = “12_2017-10-16T14:25:00”
    NAME = “NOAUDIT”
    SERVER_ID = “1”/>
</ AUDIT>

审计日志文件使用UTF-8(每个字符最多4个字节)写为XML。 根元素是 <AUDIT> 根元素包含 <AUDIT_RECORD> 元素,每个元素都提供有关审计事件的信息。 当审计日志插件开始编写新的日志文件时,它会写入XML声明并打开 <AUDIT> 根元素标记。 当插件关闭日志文件时,它会写入关闭的 </AUDIT> 根元素标记。 文件打开时,结束标记不存在。

<AUDIT_RECORD> 元素的 属性 具有以下特征:

  • 某些属性出现在每个 <AUDIT_RECORD> 元素中。 其他是可选的,可能会出现,具体取决于审计记录类型。

  • <AUDIT_RECORD> 不保证元素 内的属性顺序

  • 属性值不是固定长度。 如稍后给出的属性描述中所示,可以截断长值。

  • < > " ,和 & 字符被编码为 &lt; &gt; &quot; ,和 &amp; ,分别。 NUL字节(U + 00)被编码为 ? 字符。

  • 无效为XML字符的字符使用数字字符引用进行编码。 有效的XML字符是:

    #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
    

以下属性在每个 <AUDIT_RECORD> 元素中 都是必需的

  • NAME

    一个字符串,表示生成审计事件的指令类型,例如服务器从客户端收到的命令。

    例: NAME="Query"

    一些共同的 NAME 价值:

    审计启动审计时,可能是服务器启动时间
    连接当客户端连接时,也称为登录
    查询SQL语句(直接执行)
    准备SQL语句的准备; 通常后跟Execute
    执行SQL语句的执行; 通常遵循准备
    关机服务器关机
    退出当客户端断开连接时
    NoAudit审计已被关闭
    

    可能的值是 Audit Binlog Dump Change user Close stmt Connect Out Connect Create DB Daemon Debug Delayed insert Drop DB Execute Fetch Field List Init DB Kill Long Data NoAudit Ping Prepare Processlist Query Quit Refresh Register Slave Reset stmt Set option Shutdown Sleep Statistics Table Dump Time

    除了 "Audit" 和之外 "NoAudit" ,这些值对应 头文件中 列出 命令值 例如, 对应于 分别。 COM_xxx my_command.h "Create DB" "Change user" COM_CREATE_DB COM_CHANGE_USER

  • RECORD_ID

    审计记录的唯一标识符。 该值由格式中的序列号和时间戳组成 SEQ_TIMESTAMP 当审核日志插件打开审核日志文件时,它会将序列号初始化为审核日志文件的大小,然后为记录的每个记录将序列递增1。 时间戳是UTC值, 格式表示审核日志插件打开文件的日期和时间。 YYYY-MM-DDThh:mm:ss

    例: RECORD_ID="12_2017-10-16T14:25:00"

  • TIMESTAMP

    一个字符串,表示 格式 的UTC值, 表示生成审计事件的日期和时间。 例如,与从客户端接收的SQL语句的执行相对应的事件具有 在语句结束之后而不是在语句结束时发生 值。 YYYY-MM-DDThh:mm:ss UTC TIMESTAMP

    例: TIMESTAMP="2017-10-16T14:25:32 UTC"

以下属性在 <AUDIT_RECORD> 元素中 是可选的 其中许多只出现在具有特定 NAME 属性 值的元素中

  • COMMAND_CLASS

    一个字符串,指示执行的操作类型。

    例: COMMAND_CLASS="drop_table"

    值对应于 命令计数器。 例如, is for 语句分别。 以下语句显示可能的名称: statement/sql/xxx xxx drop_table select DROP TABLE SELECT

    SELECT REPLACE(EVENT_NAME,'statement / sql /','')AS名称
    FROM performance_schema.events_statements_summary_global_by_event_name
    在哪里EVENT_NAME LIKE'statement / sql /%'
    按名称订购;
    
  • CONNECTION_ID

    表示客户端连接标识符的无符号整数。 CONNECTION_ID() 与会话中函数 返回的值相同

    例: CONNECTION_ID="127"

  • CONNECTION_TYPE

    与服务器连接的安全状态。 允许的值是 TCP/IP (未加密建立TCP / IP连接), SSL/TLS (通过加密建立TCP / IP连接), Socket (Unix套接字文件连接), Named Pipe (Windows命名管道连接)和 Shared Memory (Windows共享内存连接)。

    例: CONNECTION_TYPE="SSL/TLS"

  • DB

    表示默认数据库名称的字符串。

    例: DB="test"

  • HOST

    表示客户端主机名的字符串。

    例: HOST="localhost"

  • IP

    表示客户端IP地址的字符串。

    例: IP="127.0.0.1"

  • MYSQL_VERSION

    表示MySQL服务器版本的字符串。 这与 VERSION() 函数或 version 系统变量 的值相同

    例: MYSQL_VERSION="5.7.21-log"

  • OS_LOGIN

    一个字符串,表示在身份验证过程中使用的外部用户名,由用于验证客户端的插件设置。 使用本机(内置)MySQL身份验证,或者如果插件未设置该值,则此属性为空。 该值与 external_user 系统变量 的值相同 (请参见 第6.2.18节“代理用户” )。

    例: OS_LOGIN="jeffrey"

  • OS_VERSION

    一个字符串,表示构建或正在运行服务器的操作系统。

    例: OS_VERSION="x86_64-Linux"

  • PRIV_USER

    表示服务器对客户端进行身份验证的用户的字符串。 这是服务器用于权限检查的用户名,它可能与 USER 不同

    例: PRIV_USER="jeffrey"

  • PROXY_USER

    表示代理用户的字符串(请参见 第6.2.18节“代理用户” )。 如果用户代理无效,则该值为空。

    例: PROXY_USER="developer"

  • SERVER_ID

    表示服务器ID的无符号整数。 这与 server_id 系统变量 的值相同

    例: SERVER_ID="1"

  • SQLTEXT

    表示SQL语句文本的字符串。 该值可以为空。 长值可能会被截断。 与审计日志文件本身一样,字符串使用UTF-8(每个字符最多4个字节)写入,因此该值可能是转换的结果。 例如,原始语句可能已作为SJIS字符串从客户端收到。

    例: SQLTEXT="DELETE FROM t1"

  • STARTUP_OPTIONS

    一个字符串,表示MySQL服务器启动时在命令行或选项文件中给出的选项。

    例: STARTUP_OPTIONS="--port=3306 --log_output=FILE"

  • STATUS

    表示命令状态的无符号整数:0表示成功,非零表示发生错误。 这与 mysql_errno() C API函数 的值相同 有关 STATUS_CODE 它的不同之处, 请参阅说明 STATUS

    审核日志不包含SQLSTATE值或错误消息。 要查看错误代码,SQLSTATE值和消息之间的关联,请参见 第B.3.1节“服务器错误消息参考”

    不记录警告。

    例: STATUS="1051"

  • STATUS_CODE

    表示命令状态的无符号整数:0表示成功,1表示发生错误。

    STATUS_CODE 值与值不同 STATUS STATUS_CODE 成功为0,错误为1,与Audit Vault的EZ_collector使用者兼容。 STATUS mysql_errno() C API函数 的值 成功时为0,错误为非零,因此错误不一定为1。

    例: STATUS_CODE="0"

  • USER

    表示客户端发送的用户名的字符串。 这可能与 PRIV_USER 价值 不同

  • VERSION

    无符号整数,表示审计日志文件格式的版本。

    例: VERSION="1"

JSON审核日志文件格式

对于JSON格式的审计日志记录( audit_log_format=JSON ),日志文件内容形成一个 JSON 数组,每个数组元素将一个审计事件表示 JSON 为键值对 哈希。 完整事件记录的示例将在本节后面部分显示。 以下是部分事件的摘录:

[
  {
    “timestamp”:“2018-01-15 13:50:01”,
    “id”:0,
    “阶级”:“审计”,
    “事件”:“启动”,
    ...
  },
  {
    “timestamp”:“2018-01-15 15:02:32”,
    “id”:0,
    “阶级”:“连接”,
    “事件”:“连接”,
    ...
  },
  ...
  {
    “timestamp”:“2018-01-15 17:37:26”,
    “id”:0,
    “class”:“table_access”,
    “事件”:“插入”,
      ...
  }
  ...
]

审计日志文件使用UTF-8编写(每个字符最多4个字节)。 当审核日志插件开始编写新的日志文件时,它会写入打开的 [ 数组标记。 当插件关闭日志文件时,它会写入结束 ] 数组标记。 文件打开时,关闭标记不存在。

审计记录中的项目具有以下特征:

  • 每个审核记录中都会显示一些项目。 其他是可选的,可能会出现,具体取决于审计记录类型。

  • 审计记录中的项目顺序无法保证。

  • 项目值不是固定长度。 如稍后给出的项目描述中所示,可以截断长值。

  • " \ 字符被编码为 \" \\ 分别。

以下示例显示了不同事件类型的JSON对象格式(由 class event 表示 ),为了便于阅读,略微重新格式化:

审核启动事件:

{“timestamp”:“2018-01-15 14:21:56”,
  “id”:0,
  “阶级”:“审计”,
  “事件”:“启动”,
  “connection_id”:0,
  “startup_data”:{“server_id”:1,
                    “os_version”:“i686-Linux”,
                    “mysql_version”:“5.7.21-log”,
                    “args”:[“/ usr / local / mysql / bin / mysqld”,
                             “--loose审计日志格式= JSON”,
                             “--log误差= LOG.ERR”,
                             “--pid文件= mysqld.pid”,
                             “--port = 3306”]}}

当审计日志插件开始作为服务器启动的结果(而不是在运行时被启用), connection_id 被设置为0,并且 account login 不存在。

审核关闭事件:

{“timestamp”:“2018-01-15 14:28:20”,
  “id”:3,
  “阶级”:“审计”,
  “事件”:“关机”,
  “connection_id”:0,
  “shutdown_data”:{“server_id”:1}}

当审计日志插件被卸载为服务器关闭的结果(而不是在运行时被禁用), connection_id 被设置为0,并且 account login 不存在。

连接或更改用户事件:

{“timestamp”:“2018-01-15 14:23:18”,
  “id”:1,
  “阶级”:“连接”,
  “事件”:“连接”,
  “connection_id”:5,
  “account”:{“user”:“root”,“host”:“localhost”},
  “login”:{“user”:“root”,“os”:“”,“ip”:“:: 1”,“proxy”:“”},
  “connection_data”:{“connection_type”:“ssl”,
                       “状态”:0,
                       “db”:“test”}}

断开事件:

{“timestamp”:“2018-01-15 14:24:45”,
  “id”:3,
  “阶级”:“连接”,
  “事件”:“断开”,
  “connection_id”:5,
  “account”:{“user”:“root”,“host”:“localhost”},
  “login”:{“user”:“root”,“os”:“”,“ip”:“:: 1”,“proxy”:“”},
  “connection_data”:{“connection_type”:“ssl”}}

查询事件:

{“timestamp”:“2018-01-15 14:23:35”,
  “id”:2,
  “阶级”:“一般”,
  “事件”:“状态”,
  “connection_id”:5,
  “account”:{“user”:“root”,“host”:“localhost”},
  “login”:{“user”:“root”,“os”:“”,“ip”:“:: 1”,“proxy”:“”},
  “general_data”:{“command”:“查询”,
                    “sql_command”:“show_variables”,
                    “查询”:“显示变量”,
                    “状态”:0}}

表访问事件(读取,删除,插入,更新):

{“timestamp”:“2018-01-15 14:23:41”,
  “id”:0,
  “class”:“table_access”,
  “事件”:“插入”,
  “connection_id”:5,
  “account”:{“user”:“root”,“host”:“localhost”},
  “login”:{“user”:“root”,“os”:“”,“ip”:“127.0.0.1”,“proxy”:“”},
  “table_access_data”:{“db”:“test”,
                         “table”:“t1”,
                         “query”:“INSERT INTO t1(i)VALUES(1),(2),(3)”,
                         “sql_command”:“insert”}}

以下列表中的项目显示在JSON格式审核记录的顶级:每个项目值都是标量或 JSON 散列。 对于具有哈希值的项目,描述仅列出该哈希中的项目名称。 有关二级哈希项的更完整描述,请参阅本节后面的内容。

  • account

    与事件关联的MySQL帐户。 的值是包含这些项目相当于值的散列 CURRENT_USER() 的段内的功能: user host

    例:

    “account”:{“user”:“root”,“host”:“localhost”}
    
  • class

    表示事件类的字符串。 该类与 event 指定事件子类 一起定义事件的类型

    例:

    “阶级”:“连接”
    

    下表显示了允许的组合 class event 值。

    表6.27审计日志类和事件组合

    类价值 允许的事件值
    audit startup shutdown
    connection connect change_user disconnect
    general status
    table_access_data read delete insert update

  • connection_data

    有关客户端连接的信息。 的值是包含这些项目的哈希: connection_type status db 此项仅适用于 class 值为的 审计记录 connection

    例:

    “connection_data”:{“connection_type”:“ssl”,
                         “状态”:0,
                         “db”:“test”}
    
  • connection_id

    表示客户端连接标识符的无符号整数。 CONNECTION_ID() 与会话中函数 返回的值相同

    例:

    “connection_id”:5
    
  • event

    表示事件类的子类的字符串。 子类与 class 指定事件类 一起定义 事件的类型。 有关更多信息,请参阅 class 项目说明。

    例:

    “事件”:“连接”
    
  • general_data

    有关已执行语句或命令的信息。 的值是包含这些项目的哈希: command sql_command query status 此项仅适用于 class 值为的 审计记录 general

    例:

    “general_data”:{“command”:“查询”,
                      “sql_command”:“show_variables”,
                      “查询”:“显示变量”,
                      “状态”:0}
    
  • id

    表示事件ID的无符号整数。

    例:

    “id”:2
    

    对于具有相同 timestamp 值的 审计记录 ,它们的 id 值区分它们并形成序列。 在审计日志中, timestamp / id 对是唯一的。 这些对是用于标识日志中的事件位置的书签。

  • login

    指示客户端如何连接到服务器的信息。 的值是包含这些项目的哈希: user os ip proxy

    例:

    “login”:{“user”:“root”,“os”:“”,“ip”:“:: 1”,“proxy”:“”}
    
  • shutdown_data

    有关审计日志插件终止的信息。 该值是包含这些项的哈希值: server_id 此项仅适用于具有 class event audit 和的 审计记录 shutdown

    例:

    “shutdown_data”:{“server_id”:1}
    
  • startup_data

    有关审计日志插件初始化的信息。 的值是包含这些项目的哈希: server_id os_version mysql_version args 此项仅适用于具有 class event audit 和的 审计记录 startup

    例:

    “startup_data”:{“server_id”:1,
                      “os_version”:“i686-Linux”,
                      “mysql_version”:“5.7.21-log”,
                      “args”:[“/ usr / local / mysql / bin / mysqld”,
                               “--loose审计日志格式= JSON”,
                               “--log误差= LOG.ERR”,
                               “--pid文件= mysqld.pid”,
                               “--port = 3306”]}
    
  • table_access_data

    有关访问表的信息。 该值是包含这些项目的哈希: db table query sql_command ,此产品仅适用于一个审计记录发生 class 的价值 table_access

    例:

    “table_access_data”:{“db”:“test”,
                           “table”:“t1”,
                           “query”:“INSERT INTO t1(i)VALUES(1),(2),(3)”,
                           “sql_command”:“insert”}
    
  • timestamp

    一个字符串,表示 YYYY-MM-DD hh:mm:ss 格式 的UTC值, 表示生成审计事件的日期和时间。 例如,与从客户端接收的SQL语句的执行相对应的事件具有 timestamp 在语句结束之后而不是在语句结束时发生 值。

    例:

    “timestamp”:“2018-01-15 13:50:01”
    

    对于具有相同 timestamp 值的 审计记录 ,它们的 id 值区分它们并形成序列。 在审计日志中, timestamp / id 对是唯一的。 这些对是用于标识日志中的事件位置的书签。

这些项目显示在与JSON格式审核记录的顶级项目关联的哈希值中:

  • args

    启动MySQL服务器时在命令行或选项文件中给出的一组选项。 第一个选项是服务器可执行文件的路径。

    例:

    “args”:[“/ usr / local / mysql / bin / mysqld”,
             “--loose审计日志格式= JSON”,
             “--log误差= LOG.ERR”,
             “--pid文件= mysqld.pid”,
             “--port = 3306”]
    
  • command

    一个字符串,表示生成审计事件的指令类型,例如服务器从客户端收到的命令。

    例:

    “命令”:“查询”
    
  • connection_type

    与服务器连接的安全状态。 允许的值是 tcp/ip (未加密建立TCP / IP连接), ssl (通过加密建立TCP / IP连接), socket (Unix套接字文件连接), named_pipe (Windows命名管道连接)和 shared_memory (Windows共享内存连接)。

    例:

    “connection_type”:“tcp / tcp”
    
  • db

    表示数据库名称的字符串。 对于 connection_data ,它是默认数据库。 因为 table_access_data ,它是表数据库。

    例:

    “db”:“测试”
    
  • host

    表示客户端主机名的字符串。

    例:

    “host”:“localhost”
    
  • ip

    表示客户端IP地址的字符串。

    例:

    “ip”:“:: 1”
    
  • mysql_version

    表示MySQL服务器版本的字符串。 这与 VERSION() 函数或 version 系统变量 的值相同

    例:

    “mysql_version”:“5.7.21-log”
    
  • os

    一个字符串,表示在身份验证过程中使用的外部用户名,由用于验证客户端的插件设置。 使用本机(内置)MySQL身份验证,或者如果插件未设置该值,则此属性为空。 该值与 external_user 系统变量 的值相同 请参见 第6.2.18节“代理用户”

    例:

    “os”:“jeffrey”
    
  • os_version

    一个字符串,表示构建或正在运行服务器的操作系统。

    例:

    “os_version”:“i686-Linux”
    
  • proxy

    表示代理用户的字符串(请参见 第6.2.18节“代理用户” )。 如果用户代理无效,则该值为空。

    例:

    “代理”:“开发者”
    
  • query

    表示SQL语句文本的字符串。 该值可以为空。 长值可能会被截断。 与审计日志文件本身一样,字符串使用UTF-8(每个字符最多4个字节)写入,因此该值可能是转换的结果。 例如,原始语句可能已作为SJIS字符串从客户端收到。

    例:

    “query”:“DELETE FROM t1”
    
  • server_id

    表示服务器ID的无符号整数。 这与 server_id 系统变量 的值相同

    例:

    “server_id”:1
    
  • sql_command

    一个表示SQL语句类型的字符串。

    例:

    “sql_command”:“插入”
    

    值对应于 命令计数器。 例如, is for 语句分别。 以下语句显示可能的名称: statement/sql/xxx xxx drop_table select DROP TABLE SELECT

    SELECT REPLACE(EVENT_NAME,'statement / sql /','')AS名称
    FROM performance_schema.events_statements_summary_global_by_event_name
    在哪里EVENT_NAME LIKE'statement / sql /%'
    按名称订购;
    
  • status

    表示命令状态的无符号整数:0表示成功,非零表示发生错误。 这与 mysql_errno() C API函数 的值相同

    审核日志不包含SQLSTATE值或错误消息。 要查看错误代码,SQLSTATE值和消息之间的关联,请参见 第B.3.1节“服务器错误消息参考”

    不记录警告。

    例:

    “身份”:1051
    
  • table

    表示表名的字符串。

    例:

    “表”:“t1”
    
  • user

    表示用户名的字符串。 含义因 user 发生 的项目而异

    • account items中, user 是一个字符串,表示服务器对客户端进行身份验证的用户。 这是服务器用于权限检查的用户名。

    • login items中, user 是一个表示客户端发送的用户名的字符串。

    例:

    “用户”:“root”
    

6.4.5.5审核日志记录配置

本节介绍如何配置审核日志记录特征,例如审核日志插件写入事件的文件,写入事件的格式以及是否启用日志文件压缩和加密。

有关影响审计日志记录的用户定义函数和系统变量的其他信息,请参见 第6.4.5.8.2节“审计日志函数” 第6.4.5.8.4节“审计日志选项和变量”

审计日志插件还可以根据事件内容或事件发起的帐户控制将审计事件写入审计日志文件。 请参见 第6.4.5.6节“审核日志过滤”

审核日志文件名

要配置审核日志文件名,请 audit_log_file 在服务器启动时 设置 系统变量。 默认情况下,该名称 audit.log 位于服务器数据目录中。 出于安全原因,请将审核日志文件写入仅可供MySQL服务器访问的目录以及具有查看日志的合法理由的用户。

该插件将该 audit_log_file 解释 为由基本名称和可选后缀组成。 如果启用了压缩或加密,则有效文件名(实际用于创建日志文件的名称)与配置的文件名不同,因为它具有其他后缀:

  • 如果启用了压缩,则插件会添加后缀 .gz

  • 如果启用了加密,则插件会添加后缀 .enc

有效的审核日志文件名是为配置的文件名添加适用的压缩和加密后缀而生成的名称。 例如,如果配置的 audit_log_file 值为 audit.log ,则有效文件名是下表中显示的值之一。

启用功能 有效的文件名
没有压缩或加密 audit.log
压缩 audit.log.gz
加密 audit.log.enc
压缩,加密 audit.log.gz.enc

审计日志插件根据有效的审计日志文件名在初始化和终止期间执行某些操作:

  • 在初始化期间,插件会检查具有审核日志文件名的文件是否已存在,如果是,则重命名。 (在这种情况下,插件假定先前的服务器调用在审计日志插件运行时意外退出。)然后插件将写入新的空审计日志文件。

  • 在终止期间,插件会重命名审核日志文件。

  • 根据自动日志文件轮换的通常规则进行文件重命名(无论是在插件初始化期间还是终止期间); 请参阅 自动审核日志文件轮换

审核日志文件格式

要配置审核日志文件格式,请 audit_log_format 在服务器启动时 设置 系统变量。 默认情况下,格式为 NEW (新式XML格式)。 有关每种格式的详细信息,请参见 第6.4.5.4节“审核日志文件格式”

如果更改 audit_log_format ,建议您也进行更改 audit_log_file 否则,将有两组具有相同基本名称但格式不同的日志文件。

审核日志文件压缩

可以为任何日志记录格式启用审核日志文件压缩。

要配置审核日志文件压缩,请 audit_log_compression 在服务器启动时 设置 系统变量。 允许的值是 NONE (无压缩;默认值)和 GZIP (GNU Zip压缩)。

如果同时启用了压缩和加密,则会在加密之前进行压缩。 要手动恢复原始文件,请先解密,然后解压缩。 请参阅 审核日志文件手动解压缩和解密

审核日志文件加密

可以为任何日志记录格式启用审核日志文件加密。 加密基于用户定义的密码(审计日志插件生成的初始密码除外)。 要使用此功能,必须启用MySQL密钥环,因为审计日志记录将其用于密码存储。 可以使用任何密钥环插件; 有关说明,请参见 第6.4.4节“MySQL密钥环”

要配置审核日志文件加密,请 audit_log_encryption 在服务器启动时 设置 系统变量。 允许的值是 NONE (无加密;默认值)和 AES (AES-256-CBC密码加密)。

要设置或获取加密密码,请使用以下用户定义的函数(UDF):

  • 要设置当前加密密码,请调用 audit_log_encryption_password_set() 此功能将新密码存储在密钥环中。 如果启用了加密,它还会执行重命名当前日志文件的日志文件循环操作,并开始使用密码加密的新日志文件。 根据自动日志文件轮换的通常规则进行文件重命名; 请参阅 自动审核日志文件轮换

    以前编写的审核日志文件不会使用新密码重新加密。 如果需要手动解密这些文件,请保留以前密码的记录。

  • 要获取当前加密密码,请调用 audit_log_encryption_password_get() ,从密钥环中检索密码。

有关审核日志加密功能的其他信息,请参见 第6.4.5.8.2节“审核日志功能”

审计日志插件初始化时,如果发现启用了日志文件加密,则会检查密钥环是否包含审计日志加密密码。 如果没有,插件会自动生成随机初始加密密码并将其存储在密钥环中。 要发现此密码,请调用 audit_log_encryption_password_get()

如果同时启用了压缩和加密,则会在加密之前进行压缩。 要手动恢复原始文件,请先解密,然后解压缩。 请参阅 审核日志文件手动解压缩和解密

审核日志文件手动解压缩和解密

可以使用标准工具对审核日志文件进行解压缩和解密。 这应仅针对已关闭(已存档)且不再使用的日志文件执行,而不应针对审计日志插件当前正在编写的日志文件执行此操作。 您可以识别归档日志文件,因为它们已由审核日志插件重命名,以在基本名称后面的文件名中包含时间戳。

对于此讨论,假设 audit_log_file 设置为 audit.log 在这种情况下,归档的审核日志文件具有下表中显示的名称之一。

启用功能 存档文件名
没有压缩或加密 audit.timestamp.log
压缩 audit.timestamp.log.gz
加密 audit.timestamp.log.enc
压缩,加密 audit.timestamp.log.gz.enc

要手动解压缩压缩日志文件,请使用 gunzip gzip -d 或等效命令。 例如:

gunzip -c审计。timestamp.log.gz>审计。timestamp.LOG

要手动解密加密的日志文件,请使用 openssl 命令。 例如:

openssl enc -d -aes-256-cbc -pass pass:password -pass -md sha256
    - 审计。timestamp.log.enc
    - 审计。timestamp.LOG

如果为审核日志记录启用了压缩和加密,则会在加密之前进行压缩。 在这种情况下,文件名具有 .gz.enc 添加 后缀,对应于这些操作发生的顺序。 要手动恢复原始文件,请反向执行操作。 也就是说,首先解密文件,然后解压缩它:

openssl enc -d -aes-256-cbc -pass pass:password -pass -md sha256
    - 审计。timestamp.log.gz.enc
    - 审计。timestamp.log.gz
gunzip -c审计。timestamp.log.gz>审计。timestamp.LOG
审核日志文件空间管理和名称轮换

审计日志文件可能会变得非常大并占用大量磁盘空间。 为了管理其日志文件使用的空间,审计日志插件可以手动或自动提供日志文件轮换。 旋转功能使用 audit_log_flush audit_log_rotate_on_size 系统变量:

  • 默认情况下, audit_log_rotate_on_size=0 除非手动执行,否则不会发生日志轮换。 在这种情况下,用于 audit_log_flush 在手动重命名后关闭并重新打开当前日志文件。

  • 如果 audit_log_rotate_on_size 大于0,则在写入当前日志文件导致其大小超过此值时会发生自动旋转。 审核日志插件关闭文件,重命名文件并打开新的日志文件。 启用自动旋转后, audit_log_flush 无效。

  • 在后面描述的几个其他条件下也会发生自动旋转。

注意

重命名的日志文件不会自动删除。 例如,对于基于大小的日志文件轮换,重命名的日志文件不会在名称序列的末尾旋转。 相反,它们具有独特的名称并无限期地积累。 为避免过多使用空间,请定期删除旧文件,必要时先备份它们。

以下讨论更详细地描述了日志文件轮换方法。

手动审核日志文件轮换

如果 audit_log_rotate_on_size=0 (默认值),除非手动执行,否则不会发生日志轮换。 在这种情况下,当 audit_log_flush 值从禁用更改为启用 时,审核日志插件将关闭并重新打开日志文件 日志文件重命名必须在服务器外部完成。 假设日志文件名 audit.log ,并要保持三个最近的日志文件,通过名称循环 audit.log.1 通过 audit.log.3 在Unix上,手动执行旋转,如下所示:

  1. 从命令行重命名当前日志文件:

    mv audit.log.2 audit.log.3
    mv audit.log.1 audit.log.2
    mv audit.log audit.log.1
    

    此策略将覆盖当前 audit.log.3 内容,对已归档日志文件的数量及其使用的空间进行限制。

  2. 此时,插件仍在写入已重命名为的当前日志文件 audit.log.1 连接到服务器并刷新日志文件,以便插件关闭它并重新打开一个新 audit.log 文件:

    SET GLOBAL audit_log_flush = ON;
    

    audit_log_flush 特别之处在于它的值仍然存在, OFF 因此您无需在再次启用它以执行另一次刷新之前显式禁用它。

注意

对于JSON格式的日志记录,手动重命名审核日志文件使它们对日志读取功能不可用,因为审核日志插件不再能够确定它们是日志文件序列的一部分(请参阅 审核日志文件读取 )。 考虑设置 audit_log_rotate_on_size 大于0以使用基于大小的旋转。

自动审核日志文件轮换

如果 audit_log_rotate_on_size 大于0,则设置 audit_log_flush 无效。 相反,只要对当前日志文件的写入导致其大小超过该 audit_log_rotate_on_size 值,审计日志插件就会关闭该文件,重命名该文件并打开新的日志文件。

在这些条件下也会发生自动旋转:

该插件通过在其基本名称之后插入时间戳来重命名原始文件。 例如,如果文件名是 audit.log ,则插件将其重命名为诸如的值 audit.20180115T140633.log 时间戳是 格式 的UTC值 时间戳表示XML日志记录的轮换时间,以及写入JSON日志记录文件的最后一个事件的时间戳。 YYYYMMDDThhmmss

审计记录写策略

审计日志插件可以使用几种策略中的任何一种进行日志写入。 无论策略如何,日志记录都是在尽力而为的基础上进行的,并不能保证一致性。

要指定写策略,请 audit_log_strategy 在服务器启动时 设置 系统变量。 默认情况下,策略值是 ASYNCHRONOUS ,并且插件异步记录到缓冲区,等待缓冲区已满。 可以告诉插件不要等待( PERFORMANCE )或同步记录,使用文件系统缓存( SEMISYNCHRONOUS )或 sync() 在每次写入请求后 强制输出 调用( SYNCHRONOUS

对于异步写策略, audit_log_buffer_size 系统变量是以字节为单位的缓冲区大小。 在服务器启动时设置此变量以更改缓冲区大小。 该插件使用单个缓冲区,它在初始化时分配,并在终止时删除。 插件不为非同步写策略分配此缓冲区。

异步日志记录策略具有以下特征:

  • 对服务器性能和可伸缩性的影响最小。

  • 阻止在尽可能短的时间内生成审计事件的线程; 也就是说,分配缓冲区的时间加上将事件复制到缓冲区的时间。

  • 输出进入缓冲区。 一个单独的线程处理从缓冲区到日志文件的写入。

使用异步日志记录时,如果在写入文件期间出现问题或者插件没有干净地关闭(例如,在服务器主机意外退出的情况下),则日志文件的完整性可能会受到影响。 要降低此风险,请设置 audit_log_strategy 为使用同步日志记录。

PERFORMANCE 策略的 一个缺点 是它在缓冲区已满时丢弃事件。 对于负载很重的服务器,审计日志可能缺少事件。

审核日志文件读取

审计日志插件支持书签和读取JSON格式的审计日志文件。 (这些功能不适用于以其他日志格式编写的文件。)

当审计日志插件初始化并配置为JSON日志记录时,它使用包含审计日志文件的目录(根据 audit_log_file 确定 )作为搜索可读审计日志文件的位置。 为此,它使用值 audit_log_file 来确定文件基本名称和后缀值,然后查找名称与以下模式匹配的 [...] 文件 ,其中 表示可选的文件名部分:

basename[ timestamp]。suffix[。广州] [ENC]

该插件打开每个匹配的文件,检查它是否真的包含JSON审计记录,并使用每个文件的第一个记录中的时间戳对它们进行排序,以构建一个日志文件列表,这些日志文件可以与日志读取功能一起使用。

该插件不能包含在手动重命名的序列文件中,并且与前面的模式不匹配,或者使用密钥环中不再可用的密码加密。

要从审核日志中读取事件,请使用以下用户定义的函数(UDF):

  • audit_log_read_bookmark() 返回 JSON 表示最近编写的审核日志事件的书签 字符串。 此书签适合传递以 audit_log_read() 指示该功能从何处开始阅读。 书签示例:

    {“timestamp”:“2018-01-15 21:03:44”,“id”:0}
    
  • audit_log_read() 从审计日志中读取事件并返回 JSON 包含审计事件数组的字符串。

audit_log_read() 使用当前书签调用 示例

MySQL的> SELECT audit_log_read(audit_log_read_bookmark());
+ ------------------------------------------------- ---------------------- +
| audit_log_read(audit_log_read_bookmark())|
+ ------------------------------------------------- ---------------------- +
| [{“timestamp”:“2018-01-15 22:41:24”,“id”:0,“class”:“connection”,... |
+ ------------------------------------------------- ---------------------- +

audit_log_read() 返回值 中的每个事件 都是一个 JSON 哈希值,但最后一个数组元素可能是一个 值,表示没有后续事件可供读取。 例如: JSON null

[
  {“timestamp”:“2018-01-15 22:08:08”,“id”:10,
    “阶级”:“一般”,“事件”:“状态”,
    ...
  },
  {
    “timestamp”:“2018-01-15 22:08:08”,“id”:11,
    “class”:“connection”,“event”:“disconnect”,
    ...
  },
  {
    “timestamp”:“2018-01-15 13:39:33”,“id”:0,
    “class”:“连接”,“事件”:“连接”,
    ...
  },
  {
    “timestamp”:“2018-01-15 13:39:33”,“id”:1,
    “阶级”:“一般”,“事件”:“状态”,
    ...
  },
  {
    “timestamp”:“2018-01-15 13:39:33”,“id”:2,
    “class”:“connection”,“event”:“disconnect”,
    ...
  },
  空值
]

使用 audit_log_read() 这样:

  • 对于 audit_log_read() 在会话中 的第一次调用 ,传递指示从哪里开始阅读的书签。

  • 如果返回的数组的最终值不是 值,则在刚读取的数据之后会有更多事件,并且 可以在没有或带有书签参数的情况下调用。 如果没有参数,则继续阅读下一个未读事件。 使用书签参数,从书签继续读取。 JSON null audit_log_read()

  • 如果返回的数组的最终值是一个 值,则不再有剩余的事件需要读取,下一次调用 必须包含书签参数。 JSON null audit_log_read()

书签是 JSON 指示读取位置和 数量的 散列。 以下项目在书签值中很重要(其他项目将被忽略):

  • timestamp id :要读取的第一个事件的审核日志中的位置。 必须存在两个项目才能完全指定位置。

  • max_array_length :从日志中读取的最大事件数。 如果省略,则默认为读取日志结尾或读取缓冲区已满,以先到者为准。

从任一日志读取函数返回的结果是二进制字符串。 要将字符串与需要非二进制字符串的函数(例如操作 JSON 的函数 )一起使用,请将其转换为 utf8mb4 假设书签具有此值:

MySQL的> SELECT @mark := audit_log_read_bookmark() AS mark;
+ ------------------------------------------------- +
| 标记|
+ ------------------------------------------------- +
| {“timestamp”:“2018-01-15 16:10:28”,“id”:2} |
+ ------------------------------------------------- +

audit_log_read() 使用该书签 调用 可以返回多个事件。 要设置读取事件数量的限制 audit_log_read() ,将书签转换为 utf8mb4 ,然后添加 max_array_length 值为1 项目。例如,使用前面的书签,转换并修改如下:


mysql> SET @mark = CONVERT(@mark USING utf8mb4);
mysql> SET @mark := JSON_SET(@mark, '$.max_array_length', 1);
mysql>SELECT @mark;
+ ------------------------------------------------- --------------------- +
| @mark |
+ ------------------------------------------------- --------------------- +
| {“id”:2,“timestamp”:“2018-01-15 16:10:28”,“max_array_length”:1} |
+ ------------------------------------------------- --------------------- +

修改后的书签在传递给 audit_log_read() 时会产生单个审核记录的结果。

要设置 audit_log_read() 读取 的字节数限制 ,请设置 audit_log_read_buffer_size 系统变量。 从MySQL 8.0.12开始,此变量的默认值为32KB,可以在运行时设置。 每个客户端应该 audit_log_read_buffer_size 为其使用适当地 设置其会话值 audit_log_read() 在MySQL 8.0.12之前, audit_log_read_buffer_size 默认值为1MB,影响所有客户端,并且只能在服务器启动时更改。

每次调用都 audit_log_read() 返回适合缓冲区大小的可用项目,跳过不符合缓冲区大小的项目。 鉴于此行为,在评估应用程序的适当缓冲区大小时请考虑以下因素:

  • audit_log_read() 每个呼叫的呼叫 次数 和返回的项目 之间存在权衡 使用较小的缓冲区大小,调用返回的项目较少,因此需要更多的调用。 缓冲区大小越大,调用返回的项越多,因此需要的调用次数越少。

  • 使用较小的缓冲区大小(例如默认大小为32KB),项目超出缓冲区大小的可能性更大,并且 audit_log_read() 会跳过它们。 跳过的项目会生成警告。

有关审计日志读取功能的其他信息,请参见 第6.4.5.8.2节“审计日志功能”

6.4.5.6审核日志过滤

注意

本节介绍如果安装了审核日志插件以及随附的审核表和UDF,审核日志筛选的工作原理。 如果安装了插件但没有附带的审计表和UDF,则插件以传统过滤模式运行,如 第6.4.5.7节“传统模式审计日志过滤”中所述 传统模式是MySQL 5.7.13之前的过滤行为; 也就是说,在引入基于规则的过滤之前。

审计日志插件可以通过过滤来控制审计事件的日志记录:

  • 可以使用以下特征过滤审核事件:

    • 用户帐号

    • 审核事件类

    • 审计事件子类

    • 事件字段的值,例如指示操作状态或执行的SQL语句的事件字段

  • 审核筛选基于规则:

    • 过滤器定义创建一组审核规则。 可以将定义配置为基于刚刚描述的特征包括或排除用于记录的事件。

    • 除了用于事件记录的现有功能之外,过滤规则还具有阻止(中止)合格事件执行的能力。

    • 可以定义多个过滤器,并且可以将任何给定过滤器分配给任意数量的用户帐户。

    • 可以定义默认过滤器以用于未明确指定过滤器的任何用户帐户。

  • 可以使用基于用户定义函数(UDF)的SQL接口定义,显示和修改审计过滤器。

  • 审计筛选器定义存储在 mysql 系统数据库 的表中

  • 在给定会话中,只读 audit_log_filter_id 系统变量的值指示是否已将过滤器分配给会话。

注意

默认情况下,基于规则的审核日志筛选不会为任何用户记录可审核事件。 要记录所有用户的所有可审计事件,请使用以下语句,这些语句创建一个简单的过滤器以启用日志记录并将其分配给默认帐户:

SELECT audit_log_filter_set_filter('log_all','{“filter”:{“log”:true}}');
SELECT audit_log_filter_set_user('%','log_all');

分配给的过滤器 % 用于来自任何未明确分配过滤器的帐户的连接(最初对所有帐户都是如此)。

以下列表简要总结了为审计过滤控制实现SQL接口的UDF:

有关过滤功能的用法示例和完整详细信息,请参见 第6.4.5.6.1节“使用审计日志过滤功能” 第6.4.5.8.2节“审计日志功能”

审核日志过滤功能受以下限制:

  • 要使用任何过滤功能, audit_log 必须启用插件或发生错误。 此外,审计表必须存在或发生错误。 要安装 audit_log 插件及其随附的UDF和表,请参见 第6.4.5.2节“安装或卸载MySQL Enterprise Audit”

  • 要使用任何过滤功能,用户必须拥有该 SUPER 权限或发生错误。 要将 SUPER 权限 授予 用户帐户,请使用以下语句:

    授予超级*。* TO user;
    

    或者,如果您 SUPER 仍然 希望 在允许用户访问特定过滤功能的同时 避免授予 权限, 则可以定义 包装器 存储的程序。 第6.4.4.8.2节“使用通用密钥环函数” 中,密钥环UDF的上下文中描述了这种技术 ; 它可以适用于过滤UDF。

  • audit_log 如果已安装,但附带的审计表和功能都没有建立在传统模式下运行的插件。 插件在服务器启动时将这些消息写入错误日志:

    [警告]插件audit_log报告:'无法打开审核日志过滤器表。'
    [警告]插件audit_log报告:'审核日志插件支持过滤,
    还没有安装。审核日志插件将在旧版中运行
    模式,将在下一个版本中禁用。
    

    在传统模式下,只能根据事件帐户或状态进行过滤。 有关详细信息,请参见 第6.4.5.7节“传统模式审核日志过滤”

6.4.5.6.1使用审计日志过滤功能

在使用审计日志用户定义函数(UDF)之前,请按照 第6.4.5.2节“安装或卸载MySQL Enterprise Audit”中 提供的说明进行 安装 SUPER 使用任何这些功能都需要 权限。

审计日志过滤功能通过提供用于创建,修改和删除过滤器定义以及为用户帐户分配过滤器的界面来启用过滤控制。

过滤器定义是 JSON 值。 有关 JSON 在MySQL中 使用 数据的 信息 ,请参见 第11.6节“JSON数据类型” 本节显示了一些简单的过滤器定义。 有关过滤器定义的更多信息,请参见 第6.4.5.6.2节“编写审核日志过滤器定义”

当连接到达时,审核日志插件通过在当前筛选器分配中搜索用户帐户名来确定要用于新会话的筛选器:

  • 如果为用户分配了筛选器,则审核日志将使用该筛选器。

  • 否则,如果不存在特定于用户的筛选器分配,但是为默认帐户( % 分配了筛选器 ,则审核日志将使用默认筛选器。

  • 否则,审核日志不会从会话中选择任何审核事件进行处理。

如果在会话期间发生更改用户操作(请参见 第28.7.7.3节“mysql_change_user()” ),则会针对新用户使用相同的规则更新会话的筛选器分配。

默认情况下,没有帐户分配过滤器,因此任何帐户都不会处理可审核事件。

假设您希望默认情况下仅记录与连接相关的活动(例如,查看connect,change-user和disconnect事件,而不是用户在连接时执行的SQL语句)。 要实现此目的,请定义一个过滤器(此处显示为名称 log_conn_events ), 该过滤器 仅允许记录 connection 类中 的事件 ,并将该过滤器分配给默认帐户,由 % 帐户名称 表示

SET @f ='{“filter”:{“class”:{“name”:“connection”}}}';
SELECT audit_log_filter_set_filter('log_conn_events',@ f);
SELECT audit_log_filter_set_user('%','log_conn_events');

现在,审核日志使用此默认帐户筛选器来处理来自任何未明确定义筛选器的帐户的连接。

要明确地将过滤器分配给特定用户帐户,请定义过滤器,然后将其分配给相关帐户:

SELECT audit_log_filter_set_filter('log_all','{“filter”:{“log”:true}}');
SELECT audit_log_filter_set_user('user1 @ localhost','log_all');
SELECT audit_log_filter_set_user('user2 @ localhost','log_all');

现在为 user1@localhost 启用了完整日志记录 user2@localhost 使用默认帐户过滤器继续过滤来自其他帐户的连接。

要取消关联用户帐户与当前过滤器的关联,请取消分配过滤器或指定其他过滤器:

  • 要从用户帐户取消分配过滤器:

    SELECT audit_log_filter_remove_user('user1 @ localhost');
    

    过滤帐户的当前会话不受影响。 如果存在,则使用默认帐户过滤器过滤来自帐户的后续连接,否则不会记录。

  • 要为用户帐户分配不同的过滤器:

    SELECT audit_log_filter_set_filter('log_nothing','{“filter”:{“log”:false}}');
    SELECT audit_log_filter_set_user('user1 @ localhost','log_nothing');
    

    过滤帐户的当前会话不受影响。 使用新过滤器过滤来自帐户的后续连接。 对于此处显示的过滤器,这意味着不会记录新连接 user1@localhost

对于审核日志筛选,用户名和主机名比较区分大小写。 这与特权检查的比较不同,对于这些比较,主机名比较不区分大小写。

要删除过滤器,请执行以下操作:

SELECT audit_log_filter_remove_filter('log_nothing');

删除过滤器也会从已分配过滤器的任何用户取消分配,包括这些用户的所有当前会话。

刚刚描述的过滤UDF立即影响审计过滤,并更新 mysql 存储过滤器和用户帐户 系统数据库中 的审计日志表 (请参见 第6.4.5.8.1节“审计日志表” )。 也可以直接使用语句,如修改审计日志表 INSERT UPDATE DELETE ,但这样的变化不影响立即过滤。 要刷新更改并使其可操作,请致电 audit_log_filter_flush()

SELECT audit_log_filter_flush();
警告

audit_log_filter_flush() 只有在直接修改审计表后才能使用,强制重新加载所有过滤器。 否则,应避免使用此功能。 它实际上是,卸载的简化版本并重新加载 audit_log 与插件 UNINSTALL PLUGIN INSTALL PLUGIN

audit_log_filter_flush() 影响所有当前会话并将它们与之前的过滤器分离。 除非断开连接并重新连接或执行更改用户操作,否则不再记录当前会话。

要确定是否已将过滤器分配给当前会话,请检查只读 audit_log_filter_id 系统变量 的会话值 如果值为0,则不分配过滤器。 非零值表示已分配过滤器的内部维护ID:

MySQL的> SELECT @@audit_log_filter_id;
+ ----------------------- +
| @@ audit_log_filter_id |
+ ----------------------- +
| 2 |
+ ----------------------- +
6.4.5.6.2编写审计日志过滤器定义

过滤器定义是 JSON 值。 有关 JSON 在MySQL中 使用 数据的 信息 ,请参见 第11.6节“JSON数据类型”

过滤器定义具有此形式,其中 actions 指示过滤如何发生:

{“过滤器”:actions}

以下讨论描述了过滤器定义中允许的构造。

记录所有事件

要显式启用或禁用所有事件的日志记录,请使用 log 过滤器中 元素:

{
  “过滤器”:{“log”:true}
}

log 值可以是 true false

上述过滤器可以记录所有事件。 它相当于:

{
  “过滤器”:{}
}

登录行为取决于 log 价值,以及是否 class event 指定项目:

  • 使用 log 指定时,将使用其给定值。

  • 如果没有 log 指定,则记录是否指定 true no class event item, false 否则(在这种情况下, class 或者 event 可以包括它们自己的 log 项目)。

记录特定事件类

要记录特定类的事件,请使用 class 过滤器中 元素,其 name 字段表示要记录的类的名称:

{
  “过滤器”:{
    “class”:{“name”:“connection”}
  }
}

name 值可以是 connection general 或分别 table_access 用于记录连接,常规或表访问事件。

前面的过滤器可以记录 connection 类中 的事件 它相当于以下过滤器,其中 log 明确的项目:

{
  “过滤器”:{
    “log”:false,
    “class”:{“log”:true,
               “名称”:“连接”}
  }
}

要启用多个类的日志记录,请将 class 定义 JSON 命名类 数组元素:

{
  “过滤器”:{
    “班级”:[
      {“name”:“connection”},
      {“name”:“general”},
      {“name”:“table_access”}
    ]
  }
}
注意

当给定项的多个实例出现在过滤器定义中的同一级别时,可以将项值组合到数组值中该项的单个实例中。 前面的定义可以这样写:

{
  “过滤器”:{
    “班级”:[
      {“name”:[“connection”,“general”,“table_access”]}
    ]
  }
}
记录特定事件子类

要选择特定事件子类,请使用 event 包含 name 命名子类 项的 项。 项目选择的事件的默认操作 event 是记录它们。 例如,此筛选器启用对命名事件子类的日志记录:

{
  “过滤器”:{
    “班级”:[
      {
        “名称”:“连接”,
        “事件”:[
          {“name”:“connect”},
          {“name”:“disconnect”}
        ]
      },
      {“name”:“general”},
      {
        “name”:“table_access”,
        “事件”:[
          {“name”:“insert”},
          {“name”:“删除”},
          {“name”:“update”}
        ]
      }
    ]
  }
}

该项 event 还可以包含显式 log 项,以指示是否记录限定事件。 此项 event 选择多个事件并明确指示它们的日志记录行为:

“事件”:[
  {“name”:“read”,“log”:false},
  {“name”:“insert”,“log”:true},
  {“name”:“delete”,“log”:true},
  {“name”:“update”,“log”:true}
]

event 项目还可以指示是否阻止符合条件的事件(如果它包含 abort 项目)。 有关详细信息,请参阅 阻止特定事件的执行

表6.28“事件类和子类组合” 描述了每个事件类的允许子类值。

表6.28事件类和子类组合

活动类 事件子类 描述
connection connect 连接启动(成功或不成功)
connection change_user 用户在会话期间使用不同的用户/密码重新验证
connection disconnect 连接终止
general status 一般操作信息
message internal 内部生成的消息
message user 消息生成 audit_api_message_emit_udf()
table_access read 表读语句,例如 SELECT INSERT INTO ... SELECT
table_access delete 表删除语句,例如 DELETE TRUNCATE TABLE
table_access insert 表插入语句,例如 INSERT REPLACE
table_access update 表更新语句,例如 UPDATE

表6.29“每个事件类和子类组合的日志和中止特征” 描述了每个事件子类是否可以记录或中止。

表6.29每个事件类和子类组合的日志和中止特征

活动类 事件子类 可以记录 可以中止
connection connect 没有
connection change_user 没有
connection disconnect 没有
general status 没有
message internal
message user
table_access read
table_access delete
table_access insert
table_access update

包容性和独家记录

过滤器可以以包含或独占模式定义:

  • 包含模式仅记录明确指定的项目。

  • 独占模式记录除明确指定的项目之外

要执行包含日志记录,请全局禁用日志记录并启用特定类的日志记录 这种过滤日志 connect disconnect 事件中的 connection 类,并且在事件 general 类:

{
  “过滤器”:{
    “log”:false,
    “班级”:[
      {
        “名称”:“连接”,
        “事件”:[
          {“name”:“connect”,“log”:true},
          {“name”:“disconnect”,“log”:true}
        ]
      },
      {“name”:“general”,“log”:true}
    ]
  }
}

要执行独占日志记录,请全局启用日志记录并禁用特定类的日志记录 此过滤器记录除 general 类中 事件之外的所有内容

{
  “过滤器”:{
    “log”:是的,
    “类”:
      {“name”:“general”,“log”:false}
  }
}

该过滤器记录 change_user 的事件 connection 类, message 事件和 table_access 事件:

{
  “过滤器”:{
    “log”:是的,
    “班级”:[
      {
        “名称”:“连接”,
        “事件”:[
          {“name”:“connect”,“log”:false},
          {“name”:“disconnect”,“log”:false}
        ]
      },
      {“name”:“general”,“log”:false}
    ]
  }
}
测试事件字段值

要根据特定事件字段值启用日志记录,请在 field 项目中 指定一个 项目,该 log 项目指示字段名称及其预期值:

{
  “过滤器”:{
    “class”:{
    “名字”:“一般”,
      “event”:{
        “名称”:“状态”,
        “log”:{
          “field”:{“name”:“general_command.str”,“value”:“查询”}
        }
      }
    }
  }
}

每个事件都包含特定于事件类的字段,可以从过滤器中访问这些字段以执行自定义过滤。

连接事件指示在会话期间何时发生与连接相关的活动,例如用户连接到服务器或从服务器断开连接。 表6.30,“连接事件字段” 表示 连接事件 的允许字段。

表6.30连接事件字段

字段名称 字段类型 描述
status 整数

活动状态:

0:好的

否则:失败

connection_id 无符号整数 连接ID
user.str 验证期间指定的用户名
user.length 无符号整数 用户名长度
priv_user.str 经过身份验证的用户名(帐户用户名)
priv_user.length 无符号整数 经过身份验证的用户名长度
external_user.str 外部用户名(由第三方认证插件提供)
external_user.length 无符号整数 外部用户名长度
proxy_user.str 代理用户名
proxy_user.length 无符号整数 代理用户名长度
host.str 已连接的用户主机
host.length 无符号整数 连接的用户主机长度
ip.str 连接的用户IP地址
ip.length 无符号整数 连接的用户IP地址长度
database.str 连接时指定的数据库名称
database.length 无符号整数 数据库名称长度
connection_type 整数

连接类型:

"::undefined" :未定义

"::tcp/ip" :TCP / IP

"::socket" :插座

"::named_pipe" :命名管道

"::ssl" :带加密的TCP / IP

"::shared_memory" :共享内存


值是符号伪常量可以给出的,而不是字面数值。 它们必须作为字符串引用并且区分大小写。 "::xxx"

一般事件表示操作的状态代码及其详细信息。 表6.31,“常规事件字段” 表示一般事件的允许字段。

表6.31常规事件字段

字段名称 字段类型 描述
general_error_code 整数

活动状态:

0:好的

否则:失败

general_thread_id 无符号整数 连接/线程ID
general_user.str 验证期间指定的用户名
general_user.length 无符号整数 用户名长度
general_command.str 命令名称
general_command.length 无符号整数 命令名称长度
general_query.str SQL语句文本
general_query.length 无符号整数 SQL语句文本长度
general_host.str 主机名
general_host.length 无符号整数 主机名长度
general_sql_command.str SQL命令类型名称
general_sql_command.length 无符号整数 SQL命令类型名称长度
general_external_user.str 外部用户名(由第三方认证插件提供)
general_external_user.length 无符号整数 外部用户名长度
general_ip.str 连接的用户IP地址
general_ip.length 无符号整数 连接用户IP地址长度

general_command.str 表示命令名: Query Execute Quit ,或 Change user

与一般的事件 general_command.str 字段设置为 Query Execute 包含 general_sql_command.str 设置为指定SQL命令的类型的值: alter_db alter_db_upgrade admin_commands ,等等。 这些值可以看作此语句显示的性能模式工具的最后组件:

MySQL的> SELECT NAME FROM performance_schema.setup_instruments
       WHERE NAME LIKE 'statement/sql/%' ORDER BY NAME;
+ --------------------------------------- +
| NAME |
+ --------------------------------------- +
| statement / sql / alter_db |
| statement / sql / alter_db_upgrade |
| statement / sql / alter_event |
| statement / sql / alter_function |
| statement / sql / alter_instance |
| statement / sql / alter_procedure |
| statement / sql / alter_server |
...

表访问事件提供有关特定表访问的信息。 表6.32“表访问事件字段” 表示 表访问事件 的允许字段。

表6.32表访问事件字段

字段名称 字段类型 描述
connection_id 无符号整数 事件连接ID
sql_command_id 整数 SQL命令ID
query.str SQL语句文本
query.length 无符号整数 SQL语句文本长度
table_database.str 与事件关联的数据库名称
table_database.length 无符号整数 数据库名称长度
table_name.str 与事件关联的表名称
table_name.length 无符号整数 表名长度

以下列表显示哪些语句产生哪些表访问事件:

  • read 事件:

    • SELECT

    • INSERT ... SELECT (对于 SELECT 子句中 引用的表

    • REPLACE ... SELECT (对于 SELECT 子句中 引用的表

    • UPDATE ... WHERE (对于 WHERE 子句中 引用的表

    • HANDLER ... READ

  • delete 事件:

    • DELETE

    • TRUNCATE TABLE

  • insert 事件:

    • INSERT

    • INSERT ... SELECT (对于 INSERT 子句 中引用的表

    • REPLACE

    • REPLACE ... SELECT (对于 REPLACE 条款 中引用的表)

    • LOAD DATA

    • LOAD XML

  • update 事件:

    • UPDATE

    • UPDATE ... WHERE (对于 UPDATE 子句中 引用的表

阻止特定事件的执行

event 项目可以包括 abort 指示是否阻止合格事件执行的项目。 例如, abort 启用阻止特定SQL语句执行的规则。

abort 项目必须出现在 event 项目中。 例如:

“event”:{
  “名称”:qualifying event subclass names
  “中止”:condition
}

对于 name 项目 选择的事件子类 abort 操作为true或false,具体取决于 condition 评估。 如果条件的计算结果为true,则会阻止该事件。 否则,事件继续执行。

所述 condition 规范可以是一样简单 true false ,或者它可以是更复杂的,使得评价取决于事件特性。

该过滤块 INSERT UPDATE DELETE 语句:

{
  “过滤器”:{
    “class”:{
      “name”:“table_access”,
      “event”:{
        “name”:[“insert”,“update”,“delete”],
        “abort”:是的
      }
    }
  }
}

这个更复杂的过滤器会阻止相同的语句,但仅限于特定的表( finances.bank_account ):

{
  “过滤器”:{
    “class”:{
      “name”:“table_access”,
      “event”:{
        “name”:[“insert”,“update”,“delete”],
        “abort”:{
          “和”:[
            {“field”:{“name”:“table_database.str”,“value”:“finances”}},
            {“field”:{“name”:“table_name.str”,“value”:“bank_account”}}
          ]
        }
      }
    }
  }
}

过滤器匹配和阻止的语句会向客户端返回错误:

错误1045(28000):语句被审核日志过滤器中止

并非所有事件都可以被阻止(请参阅 表6.29“每个事件类和子类组合的日志和中止特征” )。 对于不能执行的事件,审计日志会将警告写入错误日志而不是阻止它。

对于尝试定义 abort 项目出现在 event 项目 之外 的过滤器的尝试, 会发生错误。

逻辑运算符

逻辑运算符( and or not )可被用 log 物品。 这允许构建更高级的过滤配置:

{
  “过滤器”:{
    “class”:{
      “名字”:“一般”,
      “event”:{
        “名称”:“状态”,
        “log”:{
          “要么”: [
            {
              “和”:[
                {“field”:{“name”:“general_command.str”,“value”:“查询”}},
                {“field”:{“name”:“general_command.length”,“value”:5}}
              ]
            },
            {
              “和”:[
                {“field”:{“name”:“general_command.str”,“value”:“执行”}},
                {“field”:{“name”:“general_command.length”,“value”:7}}
              ]
            }
          ]
        }
      }
    }
  }
}
引用预定义变量

要在 log 条件中 引用预定义变量 ,请使用 variable 项目,该项目测试与给定值的相等性:

{
  “过滤器”:{
    “class”:{
      “名字”:“一般”,
      “event”:{
        “名称”:“状态”,
        “log”:{
          “变量”:{
            “name”:“audit_log_connection_policy_value”,“value”:“:: none”
          }
        }
      }
    }
  }
}

每个预定义变量对应于系统变量。 通过编写测试预定义变量的过滤器,您可以通过设置相应的系统变量来修改过滤器操作,而无需重新定义过滤器。 例如,通过编写测试 audit_log_connection_policy_value 预定义变量 值的过滤器, 可以通过更改 audit_log_connection_policy 系统变量 的值来修改过滤器操作

系统变量用于遗留模式审计日志(见 第6.4.5.7,“传统模式下的审计日志过滤” )。 使用基于规则的审计日志过滤,这些变量仍然可见(例如,使用 ),但是对它们的更改不起作用,除非您编写包含引用它们的构造的过滤器。 audit_log_xxx_policy SHOW VARIABLES

以下列表描述了 variable 项目 允许的预定义变量

  • audit_log_connection_policy_value

    此变量对应于 audit_log_connection_policy 系统变量 的值 该值是无符号整数。 表6.33“audit_log_connection_policy_value值” 显示允许值和相应的 audit_log_connection_policy 值。

    表6.33 audit_log_connection_policy_value值

    对应的audit_log_connection_policy值
    0 要么 "::none" NONE
    1 要么 "::errors" ERRORS
    2 要么 "::all" ALL

    值是符号伪常量可以给出的,而不是字面数值。 它们必须作为字符串引用并且区分大小写。 "::xxx"

  • audit_log_policy_value

    此变量对应于 audit_log_policy 系统变量 的值 该值是无符号整数。 表6.34“audit_log_policy_value值” 显示允许值和相应的 audit_log_policy 值。

    表6.34 audit_log_policy_value值

    对应的audit_log_policy值
    0 要么 "::none" NONE
    1 要么 "::logins" LOGINS
    2 要么 "::all" ALL
    3 要么 "::queries" QUERIES

    值是符号伪常量可以给出的,而不是字面数值。 它们必须作为字符串引用并且区分大小写。 "::xxx"

  • audit_log_statement_policy_value

    此变量对应于 audit_log_statement_policy 系统变量 的值 该值是无符号整数。 表6.35“audit_log_statement_policy_value值” 显示允许值和相应的 audit_log_statement_policy 值。

    表6.35 audit_log_statement_policy_value值

    对应的audit_log_statement_policy值
    0 要么 "::none" NONE
    1 要么 "::errors" ERRORS
    2 要么 "::all" ALL

    值是符号伪常量可以给出的,而不是字面数值。 它们必须作为字符串引用并且区分大小写。 "::xxx"

引用预定义函数

要引用条件中的预定义函数 log ,请使用 function 项目,其中取值 name args 值分别指定函数名称及其参数:

{
  “过滤器”:{
    “class”:{
      “名字”:“一般”,
      “event”:{
        “名称”:“状态”,
        “log”:{
          “功能”:{
            “name”:“find_in_include_list”,
            “args”:[{“string”:[{“field”:“user.str”},
                                    {“string”:“@”},
                                    {“field”:“host.str”}]}]
          }
        }
      }
    }
  }
}

name 项目中 指定 的函数应该只是函数名称,没有括号或参数列表。 args 必须按照函数说明中列出的顺序给出项目中的 参数 (如果有)。 参数可以指预定义变量,事件字段或字符串或数字常量。

前面的过滤器根据是否 系统变量中 找到当前用户 来确定是否记录 general status 事件 audit_log_include_accounts 该用户是使用事件中的字段构建的。

以下列表描述了 function 项目 的允许预定义功能

  • audit_log_exclude_accounts_is_null()

    检查 audit_log_exclude_accounts 系统变量 是否 NULL 定义与旧审计日志实现相对应的过滤器时,此功能非常有用。

    参数:

    没有。

  • audit_log_include_accounts_is_null()

    检查 audit_log_include_accounts 系统变量 是否 NULL 定义与旧审计日志实现相对应的过滤器时,此功能非常有用。

    参数:

    没有。

  • debug_sleep(millisec)

    睡眠时间为给定的毫秒数。 在性能测量期间使用此功能。

    debug_sleep() 仅适用于调试版本。

    参数:

    • millisec :无符号整数,指定要休眠的毫秒数。

  • find_in_exclude_list(account)

    检查审核日志排除列表中是否存在帐户字符串( audit_log_exclude_accounts 系统变量 的值 )。

    参数:

    • account :一个指定用户帐户名称的字符串。

  • find_in_include_list(account)

    检查审计日志包含列表中是否存在帐户字符串( audit_log_include_accounts 系统变量 的值 )。

    参数:

    • account :一个指定用户帐户名称的字符串。

  • string_find(text, substr)

    检查 substr 值是否包含在 text 值中。 此搜索区分大小写。

    参数:

    • text :要搜索的文本字符串。

    • substr :要搜索的子字符串 text

替换用户过滤器

在某些情况下,可以动态更改过滤器定义。 为此,请 filter 在现有内部 定义 配置 filter 例如:

{
  “过滤器”:{
    “id”:“主”,
    “class”:{
      “name”:“table_access”,
      “event”:{
        “名称”:[“更新”,“删除”],
        “log”:false,
        “过滤器”:{
          “class”:{
            “名字”:“一般”,
            “event”:{“name”:“status”,
                        “过滤器”:{“ref”:“main”}}
          },
          “启用”: {
            “要么”: [
              {“field”:{“name”:“table_name.str”,“value”:“temp_1”}},
              {“field”:{“name”:“table_name.str”,“value”:“temp_2”}}
            ]
          }
        }
      }
    }
  }
}

当子过滤器中的 activate 元素求值 时,将激活新过滤器 true 不允许 activate 在顶级 使用 filter

通过使用子 ref 过滤器内的项目来引用原始过滤 器,可以用原始过滤器替换新过滤 id

显示的过滤器操作如下:

  • main 过滤器等待 table_access 的事件,无论是 update delete

  • 如果 update or或 delete table_access 事件发生在 temp_1 temp_2 表上,则过滤器将替换为内部过滤器(没有 id ,因为不需要明确引用它)。

  • 如果命令结束命令( general / status event),则会将一个条目写入审核日志文件,并将过滤器替换为 main 过滤器。

该过滤器是有用的日志陈述,更新或从删除任何东西 temp_1 temp_2 表,像这样的:

UPDATE temp_1,temp_3 SET temp_1.a = 21,temp_3.a = 23;

该语句生成多个 table_access 事件,但审核日志文件仅包含 general / status entries。

注意

id 定义中使用的 任何 值仅针对该定义进行评估。 它们与 audit_log_filter_id 系统变量 的值无关

6.4.5.7传统模式审核日志过滤

注意

本节介绍旧版审核日志过滤,该过滤适用于 audit_log 安装 插件但不适用于基于规则的过滤所需的随附审核表和UDF。

审核日志插件可以过滤审核事件。 这使您可以根据事件发起的帐户或事件状态来控制是否将审计事件写入审计日志文件。 状态筛选分别针对连接事件和语句事件进行。

按帐户过滤事件

要根据原始帐户筛选审计事件,请在服务器启动或运行时设置其中一个系统变量:

  • audit_log_include_accounts :要包含在审核日志记录中的帐户。 如果设置了此变量,则仅审核这些帐户。

  • audit_log_exclude_accounts :要从审核日志记录中排除的帐户。 如果设置了此变量,则会审核除这些帐户之外的所有帐户。

任一变量的值都可以是 NULL 包含一个或多个逗号分隔帐户名的字符串,每个帐户名都有 格式。 默认情况下, 在这种情况 下,两个变量都 不会进行帐户过滤,并且会对所有帐户进行审核。 user_name@host_name NULL

修改 audit_log_include_accounts audit_log_exclude_accounts 影响 修改后 创建的连接,而不是现有连接。

示例:要启用审核日志记录只为 user1 user2 本地主机帐户帐户,设置 audit_log_include_accounts 这样的系统变量:

SET GLOBAL audit_log_include_accounts ='user1 @ localhost,user2 @ localhost';

一次只能一个 audit_log_include_accounts audit_log_exclude_accounts 不一个非 NULL

- 这将audit_log_exclude_accounts设置为NULL
SET GLOBAL audit_log_include_accounts = value;

- 由于audit_log_include_accounts不为NULL,因此失败
SET GLOBAL audit_log_exclude_accounts = value;

- 要设置audit_log_exclude_accounts,请先设置
-  audit_log_include_accounts为NULL
SET GLOBAL audit_log_include_accounts = NULL;
SET GLOBAL audit_log_exclude_accounts = value;

如果检查任一变量的值,请注意 SHOW VARIABLES 显示 NULL 为空字符串。 为避免这种情况,请 SELECT 改用:

MySQL的> SHOW VARIABLES LIKE 'audit_log_include_accounts';
+ ---------------------------- + ------- +
| Variable_name | 价值|
+ ---------------------------- + ------- +
| audit_log_include_accounts | |
+ ---------------------------- + ------- +
MySQL的> SELECT @@audit_log_include_accounts;
+ ------------------------------ +
| @@ audit_log_include_accounts |
+ ------------------------------ +
| NULL |
+ ------------------------------ +

如果用户名或主机名需要引用,因为它包含逗号,空格或其他特殊字符,请使用单引号引用它。 如果变量值本身用单引号引用,则将每个内部单引号加倍或使用反斜杠对其进行转义。 以下语句均为本地 root 帐户 启用审核日志记录, 并且等效,即使引用样式不同:

SET GLOBAL audit_log_include_accounts ='root @ localhost';
SET GLOBAL audit_log_include_accounts ='''root''@''localhost''';
SET GLOBAL audit_log_include_accounts ='\'root \'@ \'localhost \'';
SET GLOBAL audit_log_include_accounts =“'root'@'localhost'”;

如果 ANSI_QUOTES 启用 SQL模式,则 最后一个语句将不起作用, 因为在该模式下双引号表示标识符引用,而不是字符串引用。

按状态筛选事件

要根据状态筛选审计事件,请在服务器启动或运行时设置以下系统变量。 这些变量仅适用于旧版审核日志筛选。 对于JSON审核日志筛选,应用不同的状态变量; 请参见 第6.4.5.8.4节“审核日志选项和变量”

每个变量的值为 ALL (记录所有关联事件;这是默认值), ERRORS (仅记录失败事件)或 NONE (不记录事件)。 例如,要记录所有语句事件但仅记录失败的连接事件,请使用以下设置:

SET GLOBAL audit_log_statement_policy = ALL;
SET GLOBAL audit_log_connection_policy =错误;

另一项政策系统变量, audit_log_policy 是可用的,但不提供尽可能多的控制, audit_log_connection_policy audit_log_statement_policy 它只能在服务器启动时设置。 在运行时,它是一个只读变量。 它取值 ALL (记录所有事件;这是默认值), LOGINS (日志连接事件), QUERIES (日志语句事件)或 NONE (不记录事件)。 对于任何这些值,审计日志插件会记录所有选定事件,而不会区分成功或失败。 audit_log_policy 启动时的 使用 如下:

6.4.5.8审核日志参考

以下讨论作为MySQL Enterprise Audit组件的参考:

要安装审核日志表和函数,请使用 第6.4.5.2节“安装或卸载MySQL Enterprise Audit”中提供的说明 除非安装了这些组件,否则 audit_log 插件将以传统模式运行。 请参见 第6.4.5.7节“传统模式审核日志过滤”

6.4.5.8.1审核日志表

MySQL Enterprise Audit使用 mysql 系统数据库中的 来持久存储过滤器和用户帐户数据。 只有具有该数据库权限的用户才能访问这些表。 表使用 InnoDB 存储引擎。

如果缺少这些表,则 audit_log 插件将以传统模式运行。 请参见 第6.4.5.7节“传统模式审核日志过滤”

audit_log_filter 表存储过滤器定义。 该表包含以下列:

  • NAME

    过滤器名称。

  • FILTER

    与筛选器名称关联的筛选器定义。 定义存储为 JSON 值。

audit_log_user 表存储用户帐户信息。 该表包含以下列:

  • USER

    帐户的用户名部分。 对于一个帐户 user1@localhost ,该 USER 部分是 user1

  • HOST

    帐户的主机名部分。 对于一个帐户 user1@localhost ,该 HOST 部分是 localhost

  • FILTERNAME

    分配给帐户的过滤器的名称。 过滤器名称将帐户与 audit_log_filter 表中 定义的过滤器相关联

6.4.5.8.2审核日志功能

本节描述了每个审计日志用户定义函数(UDF),其用途,调用顺序和返回值。 有关可以调用这些UDF的条件的信息,请参见 第6.4.5.6节“审核日志过滤”

每个审核日志UDF都返回一个字符串,指示操作是否成功。 OK 表示成功。 表示失败。 ERROR: message

这些审核日志UDF可用:

  • audit_log_encryption_password_get()

    以二进制字符串形式检索当前审核日志加密密码。 密码是从MySQL密钥环中获取的,必须启用该密钥环或发生错误。 可以使用任何密钥环插件; 有关说明,请参见 第6.4.4节“MySQL密钥环”

    有关审核日志加密的其他信息,请参阅 审核日志文件加密

    参数:

    没有。

    返回值:

    成功的密码字符串(最多766个字节),或 NULL 失败的错误。

    例:

    MySQL的> SELECT audit_log_encryption_password_get();
    + ------------------------------- +
    | audit_log_encryption_password_get()|
    + ------------------------------- +
    | 秘密|
    + ------------------------------- +
    
  • audit_log_encryption_password_set(password)

    将审核日志加密密码设置为参数,将密码存储在MySQL密钥环中。 如果启用了加密,则该函数将执行日志文件循环操作,该操作将重命名当前日志文件,并开始使用密码加密的新日志文件。 必须启用密钥环或发生错误。 可以使用任何密钥环插件; 有关说明,请参见 第6.4.4节“MySQL密钥环”

    有关审核日志加密的其他信息,请参阅 审核日志文件加密

    参数:

    password :密码字符串。 允许的最大长度为766字节。

    返回值:

    1表示成功,0表示失败。

    例:

    MySQL的> SELECT audit_log_encryption_password_set(password);
    + --------------------------------------------- +
    | audit_log_encryption_password_set(password)|
    + --------------------------------------------- +
    | 1 |
    + --------------------------------------------- +
    
  • audit_log_filter_flush()

    调用任何其他过滤UDF会立即影响操作审核日志筛选并更新审核日志表。 相反,如果你修改这些表的内容,直接使用语句,例如 INSERT UPDATE DELETE ,所做的更改不会影响立即过滤。 要刷新更改并使其可操作,请致电 audit_log_filter_flush()

    警告

    audit_log_filter_flush() 只有在直接修改审计表后才能使用,强制重新加载所有过滤器。 否则,应避免使用此功能。 它实际上是,卸载的简化版本并重新加载 audit_log 与插件 UNINSTALL PLUGIN INSTALL PLUGIN

    audit_log_filter_flush() 影响所有当前会话并将它们与之前的过滤器分离。 除非断开连接并重新连接或执行更改用户操作,否则不再记录当前会话。

    如果此函数失败,则会返回错误消息,并且在下次成功调用之前将禁用审核日志 audit_log_filter_flush()

    参数:

    没有。

    返回值:

    一个字符串,指示操作是否成功。 OK 表示成功。 表示失败。 ERROR: message

    例:

    MySQL的> SELECT audit_log_filter_flush();
    + -------------------------- +
    | audit_log_filter_flush()|
    + -------------------------- +
    | 好的
    + -------------------------- +
    
  • audit_log_filter_remove_filter(filter_name)

    给定过滤器名称,从当前过滤器集中删除过滤器。 过滤器不存在不是错误。

    如果为任何用户帐户分配了已删除的筛选器,则会停止筛选这些用户(将从 audit_log_user 中删除这些筛选器 )。 终止过滤包括这些用户的任何当前会话:它们与过滤器分离,不再记录。

    参数:

    • filter_name :一个指定过滤器名称的字符串。

    返回值:

    一个字符串,指示操作是否成功。 OK 表示成功。 表示失败。 ERROR: message

    例:

    MySQL的> SELECT audit_log_filter_remove_filter('SomeFilter');
    + ---------------------------------------------- +
    | audit_log_filter_remove_filter('SomeFilter')|
    + ---------------------------------------------- +
    | 好的
    + ---------------------------------------------- +
    
  • audit_log_filter_remove_user(user_name)

    给定用户帐户名称,导致用户不再被分配到过滤器。 如果用户未分配过滤器,则不会出错。 为用户过滤当前会话不受影响。 如果存在,则使用默认帐户过滤器过滤用户的新连接,否则不会记录。

    如果名称为 % ,则该函数将删除用于未明确分配过滤器的任何用户帐户的默认帐户过滤器。

    参数:

    • user_name :用户帐户名称 格式 为字符串 ,或 表示默认帐户。 user_name@host_name %

    返回值:

    一个字符串,指示操作是否成功。 OK 表示成功。 表示失败。 ERROR: message

    例:

    MySQL的> SELECT audit_log_filter_remove_user('user1@localhost');
    + ------------------------------------------------- +
    | audit_log_filter_remove_user('user1 @ localhost')|
    + ------------------------------------------------- +
    | 好的
    + ------------------------------------------------- +
    
  • audit_log_filter_set_filter(filter_name, definition)

    给定过滤器名称和定义,将过滤器添加到当前过滤器集。 如果过滤器已存在且由任何当前会话使用,则这些会话将从过滤器中分离,并且不再记录。 发生这种情况是因为新过滤器定义具有与其先前ID不同的新过滤器ID。

    参数:

    • filter_name :一个指定过滤器名称的字符串。

    • definition :一个 JSON 指定过滤器定义的值。

    返回值:

    一个字符串,指示操作是否成功。 OK 表示成功。 表示失败。 ERROR: message

    例:

    mysql> SET @f = '{ "filter": { "log": false } }';
    mysql>SELECT audit_log_filter_set_filter('SomeFilter', @f);
    + ----------------------------------------------- +
    | audit_log_filter_set_filter('SomeFilter',@ f)|
    + ----------------------------------------------- +
    | 好的
    + ----------------------------------------------- +
    
  • audit_log_filter_set_user(user_name, filter_name)

    给定用户帐户名称和过滤器名称,将过滤器分配给用户。 用户只能分配一个过滤器,因此如果已为用户分配过滤器,则替换分配。 为用户过滤当前会话不受影响。 使用新过滤器过滤新连接。

    作为特殊情况,名称 % 表示默认帐户。 过滤器用于来自未明确指定过滤器的任何用户帐户的连接。

    参数:

    • user_name :用户帐户名称 格式 为字符串 ,或 表示默认帐户。 user_name@host_name %

    • filter_name :一个指定过滤器名称的字符串。

    返回值:

    一个字符串,指示操作是否成功。 OK 表示成功。 表示失败。 ERROR: message

    例:

    MySQL的> SELECT audit_log_filter_set_user('user1@localhost', 'SomeFilter');
    + ------------------------------------------------- ----------- +
    | audit_log_filter_set_user('user1 @ localhost','SomeFilter')|
    + ------------------------------------------------- ----------- +
    | 好的
    + ------------------------------------------------- ----------- +
    
  • audit_log_read([arg])

    从审计日志中读取事件并返回 JSON 包含审计事件数组的 二进制 字符串。 如果不是审核日志格式 JSON ,则会发生错误。

    返回值中的每个事件都是一个 JSON 哈希值,但最后一个数组元素可能是一个 值,表示没有后续事件可供读取。 JSON null

    对于 audit_log_read() 在会话中 的第一次调用 ,传递指示从哪里开始阅读的书签。 如果返回的数组的最终值不是 值,则在刚读取的数据之后会有更多事件,并且 可以在没有或带有书签参数的情况下调用。 如果没有参数,则继续阅读下一个未读事件。 使用书签参数,从书签继续读取。 JSON null audit_log_read()

    如果返回的数组的最终值是一个 值,则不再有剩余的事件需要读取,下一次调用 必须包含书签参数。 JSON null audit_log_read()

    要获取最近编写的事件的书签,请致电 audit_log_read_bookmark()

    有关审核日志读取功能的其他信息,请参阅 审核日志文件读取

    参数:

    arg :可选书签,表示为包含 JSON 指示读取位置和内容 散列 的字符串 以下项目的 arg 很重要 (其他项目被忽略):

    • timestamp id :要读取的第一个事件的审核日志中的位置。 必须存在两个项目才能完全指定位置。

    • max_array_length :从日志中读取的最大事件数。 如果省略,则默认为读取日志结尾或读取缓冲区已满,以先到者为准。

    返回值:

    二进制 JSON 字符串,包含成功的审计事件数组,或 NULL 失败错误。

    例:

    MySQL的> SELECT audit_log_read(audit_log_read_bookmark());
    + ------------------------------------------------- ---------------------- +
    | audit_log_read(audit_log_read_bookmark())|
    + ------------------------------------------------- ---------------------- +
    | [{“timestamp”:“2018-01-15 22:41:24”,“id”:0,“class”:“connection”,... |
    + ------------------------------------------------- ---------------------- +
    
  • audit_log_read_bookmark()

    返回 JSON 表示最近编写的审核日志事件的书签 的二进制 字符串。 如果不是审核日志格式 JSON ,则会发生错误。

    书签是 JSON 哈希, timestamp 其中的 id 项目表示审计日志中的事件位置。 它适用于传递以 audit_log_read() 指示该功能从何处开始阅读。

    有关审核日志读取功能的其他信息,请参阅 审核日志文件读取

    参数:

    没有。

    返回值:

    JSON 包含成功书签的 二进制 字符串,或 NULL 失败错误。

    例:

    MySQL的> SELECT audit_log_read_bookmark();
    + ------------------------------------------------- +
    | audit_log_read_bookmark()|
    + ------------------------------------------------- +
    | {“timestamp”:“2018-01-15 21:03:44”,“id”:0} |
    + ------------------------------------------------- +
    
6.4.5.8.3审核日志选项和变量引用

表6.36审核日志选项和变量引用

名称 CMD线 选项文件 系统变量 状态变量 Var范围 动态
审计日志
audit_log_buffer_size 全球 没有
audit_log_compression 全球 没有
audit_log_connection_policy 全球
audit_log_current_session 没有
Audit_log_current_size 全球 没有
audit_log_encryption 全球 没有
Audit_log_event_max_drop_size 全球 没有
Audit_log_events 全球 没有
Audit_log_events_filtered 全球 没有
Audit_log_events_lost 全球 没有
Audit_log_events_written 全球 没有
audit_log_exclude_accounts 全球
audit_log_file 全球 没有
audit_log_filter_id 没有
audit_log_flush 全球
audit_log_format 全球 没有
audit_log_include_accounts 全球
audit_log_policy 全球 没有
audit_log_read_buffer_size 不定 不定
audit_log_rotate_on_size 全球
audit_log_statement_policy 全球
audit_log_strategy 全球 没有
Audit_log_total_size 全球 没有
Audit_log_write_waits 全球 没有

6.4.5.8.4审核日志选项和变量

本节介绍配置MySQL Enterprise Audit操作的命令选项和系统变量。 如果在启动时指定的值不正确,则 audit_log 插件可能无法正确初始化,并且服务器无法加载它。 在这种情况下,服务器还可能会为其他审核日志设置生成错误消息,因为它无法识别它们。

要配置审核日志插件的激活,请使用此选项:

如果启用了审计日志插件,它会公开几个允许控制日志记录的系统变量:

MySQL的> SHOW VARIABLES LIKE 'audit_log%';
+ ----------------------------- + -------------- +
| Variable_name | 价值|
+ ----------------------------- + -------------- +
| audit_log_buffer_size | 1048576 |
| audit_log_connection_policy | 所有|
| audit_log_current_session | 关闭|
| audit_log_exclude_accounts | |
| audit_log_file | audit.log |
| audit_log_filter_id | 0 |
| audit_log_flush | 关闭|
| audit_log_format | 新|
| audit_log_include_accounts | |
| audit_log_policy | 所有|
| audit_log_rotate_on_size | 0 |
| audit_log_statement_policy | 所有|
| audit_log_strategy | 异步|
+ ----------------------------- + -------------- +

您可以在服务器启动时设置任何这些变量,并在运行时设置其中一些变量。 仅注意那些仅适用于传统模式审核日志过滤的那些。

  • audit_log_buffer_size

    属性
    命令行格式 --audit-log-buffer-size=#
    介绍 8.0.11
    系统变量 audit_log_buffer_size
    范围 全球
    动态 没有
    SET_VAR 提示适用 没有
    类型 整数
    默认值 1048576
    最低价值 4096
    最大值 (64位平台) 18446744073709547520
    最大值 (32位平台) 4294967295

    当审计日志插件异步地将事件写入日志时,它会在写入事件内容之前使用缓冲区来存储事件内容。 此变量控制该缓冲区的大小(以字节为单位)。 服务器将值调整为4096的倍数。插件使用单个缓冲区,它在初始化时分配,在终止时删除。 仅当日志记录是异步时,插件才会分配此缓冲区。

  • audit_log_compression

    属性
    命令行格式 --audit-log-compression=value
    介绍 8.0.11
    系统变量 audit_log_compression
    范围 全球
    动态 没有
    SET_VAR 提示适用 没有
    类型 列举
    默认值 NONE
    有效值

    NONE

    GZIP

    审核日志文件的压缩类型。 允许的值是 NONE (无压缩;默认值)和 GZIP (GNU Zip压缩)。 有关更多信息,请参阅 审核日志文件压缩

  • audit_log_connection_policy

    属性
    命令行格式 --audit-log-connection-policy=value
    介绍 8.0.11
    系统变量 audit_log_connection_policy
    范围 全球
    动态
    SET_VAR 提示适用 没有
    类型 列举
    默认值 ALL
    有效值

    ALL

    ERRORS

    NONE

    注意

    此变量仅适用于传统模式审核日志筛选(请参见 第6.4.5.7节“传统模式审核日志筛选” )。

    控制审核日志插件如何将连接事件写入其日志文件的策略。 下表显示了允许的值。

    描述
    ALL 记录所有连接事件
    ERRORS 仅记录失败的连接事件
    NONE 不记录连接事件
    注意

    在服务器启动时, audit_log_connection_policy 如果 audit_log_policy 还指定了 任何给定的显式值, 则可以覆盖 它,如 第6.4.5.5节“审计日志记录配置”中所述

  • audit_log_current_session

    属性
    介绍 8.0.11
    系统变量 audit_log_current_session
    范围 全球,会议
    动态 没有
    SET_VAR 提示适用 没有
    类型 布尔
    默认值 depends on filtering policy

    是否为当前会话启用了审核日志记录。 此变量的会话值是只读的。 它是在会话开始时根据 audit_log_include_accounts audit_log_exclude_accounts 系统变量 的值设置的 审核日志插件使用会话值来确定是否审核会话的事件。 (有一个全局值,但插件不使用它。)

  • audit_log_encryption

    属性
    命令行格式 --audit-log-encryption=value
    介绍 8.0.11
    系统变量 audit_log_encryption
    范围 全球
    动态 没有
    SET_VAR 提示适用 没有
    类型 列举
    默认值 NONE
    有效值

    NONE

    AES

    审核日志文件的加密类型。 允许的值是 NONE (无加密;默认值)和 AES (AES-256-CBC密码加密)。 有关更多信息,请参阅 审核日志文件加密

  • audit_log_exclude_accounts

    属性
    命令行格式 --audit-log-exclude-accounts=value
    介绍 8.0.11
    系统变量 audit_log_exclude_accounts
    范围 全球
    动态
    SET_VAR 提示适用 没有
    类型
    默认值 NULL
    注意

    此变量仅适用于传统模式审核日志筛选(请参见 第6.4.5.7节“传统模式审核日志筛选” )。

    不应记录事件的帐户。 该值应为 NULL 或包含一个或多个逗号分隔帐户名列表的字符串。 有关更多信息,请参见 第6.4.5.6节“审核日志过滤”

    修改 audit_log_exclude_accounts 仅影响 修改后 创建的连接,而不影响现有连接。

  • audit_log_file

    属性
    命令行格式 --audit-log-file=file_name
    介绍 8.0.11
    系统变量 audit_log_file
    范围 全球
    动态 没有
    SET_VAR 提示适用 没有
    类型 文件名
    默认值 audit.log

    审计日志插件将事件写入的文件的基本名称和后缀。 audit.log 无论日志记录格式如何, 默认值均为 要使名称后缀与格式相对应,请明确设置名称,选择不同的后缀(例如, audit.xml 对于XML格式, audit.json 对于JSON格式)。

    如果值 audit_log_file 是相对路径名,则插件会相对于数据目录解释它。 如果值是完整路径名,则插件将按原样使用该值。 如果需要在单独的文件系统或目录上查找审计文件,则完整路径名可能很有用。 出于安全原因,请将审核日志文件写入仅可供MySQL服务器访问的目录以及具有查看日志的合法理由的用户。

    有关审核日志插件如何解释 audit_log_file 插件初始化和终止时发生的文件重命名 值和规则的 详细信息 ,请参阅 审核日志文件名

    审核日志插件使用包含审核日志文件的目录(根据 audit_log_file 确定 )作为搜索可读审核日志文件的位置。 从这些日志文件和当前文件中,插件构造了一个列表,列出了与审计日志书签和阅读功能一起使用的列表。 请参阅 审核日志文件读取

  • audit_log_filter_id

    属性
    介绍 8.0.11
    系统变量 audit_log_filter_id
    范围 全球,会议
    动态 没有
    SET_VAR 提示适用 没有
    类型 整数

    此变量的会话值指示当前会话的审计筛选器的内部维护ID。 值为0表示会话未分配过滤器。

  • audit_log_flush

    属性
    介绍 8.0.11
    系统变量 audit_log_flush
    范围 全球
    动态
    SET_VAR 提示适用 没有
    类型 布尔
    默认值 OFF

    当此变量设置为enabled(1或 ON )时,审计日志插件将关闭并重新打开其日志文件以对其进行刷新。 (该值保持不变, OFF 因此您无需在再次启用它之前显式禁用它以执行另一次刷新。)启用此变量无效,除非 audit_log_rotate_on_size 为0.有关更多信息,请参见 第6.4.5.5节“审核日志记录配置”

  • audit_log_format

    属性
    命令行格式 --audit-log-format=value
    介绍 8.0.11
    系统变量 audit_log_format
    范围 全球
    动态 没有
    SET_VAR 提示适用 没有
    类型 列举
    默认值 NEW
    有效值

    OLD

    NEW

    JSON

    审核日志文件格式。 允许的值是 OLD (旧式XML), NEW (新式XML;默认值)和 JSON 有关每种格式的详细信息,请参见 第6.4.5.4节“审核日志文件格式”

    注意

    有关更改日志格式时要考虑的问题的信息,请参阅 审核日志文件格式

  • audit_log_include_accounts

    属性
    命令行格式 --audit-log-include-accounts=value
    介绍 8.0.11
    系统变量 audit_log_include_accounts
    范围 全球
    动态
    SET_VAR 提示适用 没有
    类型
    默认值 NULL
    注意

    此变量仅适用于传统模式审核日志筛选(请参见 第6.4.5.7节“传统模式审核日志筛选” )。

    应记录事件的帐户。 该值应为 NULL 或包含一个或多个逗号分隔帐户名列表的字符串。 有关更多信息,请参见 第6.4.5.6节“审核日志过滤”

    修改 audit_log_include_accounts 仅影响 修改后 创建的连接,而不影响现有连接。

  • audit_log_policy

    属性
    命令行格式 --audit-log-policy=value
    介绍 8.0.11
    系统变量 audit_log_policy
    范围 全球
    动态 没有
    SET_VAR 提示适用 没有
    类型 列举
    默认值 ALL
    有效值

    ALL

    LOGINS

    QUERIES

    NONE

    注意

    此变量仅适用于传统模式审核日志筛选(请参见 第6.4.5.7节“传统模式审核日志筛选” )。

    控制审核日志插件如何将事件写入其日志文件的策略。 下表显示了允许的值。

    描述
    ALL 记录所有事件
    LOGINS 仅记录登录事件
    QUERIES 仅记录查询事件
    NONE 什么都不记录(禁用审计流)

    audit_log_policy 只能在服务器启动时设置。 在运行时,它是一个只读变量。 另外两个系统变量, audit_log_connection_policy audit_log_statement_policy 提供了日志记录策略更精细的控制,并可以在启动或运行时设置。 如果 audit_log_policy 在启动时 使用 而不是其他两个变量,则服务器使用其值来设置这些变量。 有关策略变量及其交互的更多信息,请参见 第6.4.5.5节“审核日志记录配置”

  • audit_log_read_buffer_size

    属性
    命令行格式 --audit-log-read-buffer-size=#
    介绍 8.0.11
    系统变量 (> = 8.0.11) audit_log_read_buffer_size
    范围 (> = 8.0.12) 全球,会议
    范围 (8.0.11) 全球
    动态 (> = 8.0.12)
    动态 (8.0.11) 没有
    SET_VAR 提示适用 (> = 8.0.11) 没有
    类型 整数
    默认值 (> = 8.0.12) 32768
    默认值 (8.0.11) 1048576
    最小值 (> = 8.0.12) 32768
    最低价值 (8.0.11) 1024
    最大价值 4194304

    从审计日志文件中读取的缓冲区大小(以字节为单位)。 audit_log_read() 函数读取的字节数不超过这个字节。 仅支持JSON日志格式的日志文件读取。 有关更多信息,请参阅 审核日志文件读取

    从MySQL 8.0.12开始,此变量的默认值为32KB,可以在运行时设置。 每个客户端应该 audit_log_read_buffer_size 为其使用适当地 设置其会话值 audit_log_read() 在MySQL 8.0.12之前, audit_log_read_buffer_size 默认值为1MB,影响所有客户端,并且只能在服务器启动时更改。

  • audit_log_rotate_on_size

    属性
    命令行格式 --audit-log-rotate-on-size=#
    介绍 8.0.11
    系统变量 audit_log_rotate_on_size
    范围 全球
    动态
    SET_VAR 提示适用 没有
    类型 整数
    默认值 0

    如果 audit_log_rotate_on_size 值为0,则审核日志插件不会执行自动日志文件轮换。 而是 audit_log_flush 用于关闭并重新打开按需记录。 在这种情况下,请在刷新之前手动将文件重命名为服务器。

    如果该 audit_log_rotate_on_size 值大于0,则会发生基于自动大小的日志文件轮换。 每当写入日志文件导致其大小超过 audit_log_rotate_on_size 值,审计日志插件就会关闭当前日志文件,重命名该日志文件并打开新的日志文件。

    有关审核日志文件轮换的详细信息,请参阅 审核日志文件空间管理和名称轮换

    如果将此变量设置为不是4096的倍数的值,则会将其截断为最接近的倍数。 (因此,将其设置为小于4096的值会将其设置为0并且不会发生旋转,除非手动。)

  • audit_log_statement_policy

    属性
    命令行格式 --audit-log-statement-policy=value
    介绍 8.0.11
    系统变量 audit_log_statement_policy
    范围 全球
    动态
    SET_VAR 提示适用 没有
    类型 列举
    默认值 ALL
    有效值

    ALL

    ERRORS

    NONE

    注意

    此变量仅适用于传统模式审核日志筛选(请参见 第6.4.5.7节“传统模式审核日志筛选” )。

    控制审计日志插件如何将语句事件写入其日志文件的策略。 下表显示了允许的值。

    描述
    ALL 记录所有语句事件
    ERRORS 仅记录失败的语句事件
    NONE 不记录语句事件
    注意

    在服务器启动时, audit_log_statement_policy 如果 audit_log_policy 还指定了 任何给定的显式值, 则可以覆盖 它,如 第6.4.5.5节“审计日志记录配置”中所述

  • audit_log_strategy

    属性
    命令行格式 --audit-log-strategy=value
    介绍 8.0.11
    系统变量 audit_log_strategy
    范围 全球
    动态 没有
    SET_VAR 提示适用 没有
    类型 列举
    默认值 ASYNCHRONOUS
    有效值

    ASYNCHRONOUS

    PERFORMANCE

    SEMISYNCHRONOUS

    SYNCHRONOUS

    审计日志插件使用的日志记录方法。 允许使用以下策略值:

    • ASYNCHRONOUS :异步记录。 等待输出缓冲区中的空间。

    • PERFORMANCE :异步记录。 删除输出缓冲区中空间不足的请求。

    • SEMISYNCHRONOUS :同步记录。 允许操作系统进行缓存。

    • SYNCHRONOUS :同步记录。 sync() 每次请求后 致电

6.4.5.8.5审核日志状态变量

如果启用了审核日志插件,则会公开几个提供操作信息的状态变量。 这些变量可用于传统模式审核筛选和JSON模式审核筛选。

6.4.5.9审核日志限制

MySQL Enterprise Audit受这些一般限制的约束:

  • 仅记录SQL语句。 不记录no-SQL API(例如memcached,Node.JS和NDB API)所做的更改。

  • 仅记录顶级语句,而不记录存储程序(如触发器或存储过程)中的语句。

  • 语句引用的文件内容( LOAD DATA 如未记录)。

NDB集群。  根据以下条件,可以将MySQL Enterprise Audit与MySQL NDB Cluster一起使用:

  • 必须使用SQL接口完成要记录的所有更改。 不记录使用无SQL接口的更改,例如NDB API,memcached或ClusterJ提供的更改。

  • 必须在用于在群集上执行SQL的每个MySQL服务器上安装该插件。

  • 必须在与群集一起使用的所有MySQL服务器之间聚合审核插件数据。 此聚合是应用程序或用户的责任。

6.4.6审计消息组件

从MySQL 8.0.14开始,该 audit_api_message_emit 组件使应用程序能够使用 audit_api_message_emit_udf() 用户定义的函数 将自己的消息事件添加到审计日志中

audit_api_message_emit 组件与审计类型的所有插件协作。 具体而言,示例使用 第6.4.5节“MySQL Enterprise Audit”中 audit_log 描述 插件

安装或卸载审核消息组件

要使服务器可以使用,组件库文件必须位于MySQL插件目录( plugin_dir 系统变量 指定的目录 )中。 如有必要,通过设置 plugin_dir 服务器启动时 的值来配置插件目录位置

要安装 audit_api_message_emit 组件,请使用以下语句:

INSTALL COMPONENT“file:// component_audit_api_message_emit”;

组件安装是一次性操作,无需在每个服务器启动时完成。 INSTALL COMPONENT 加载组件,并将其注册到 mysql.component 系统表中,以便在后续服务器启动期间加载它。

要卸载 audit_api_message_emit 组件,请使用以下语句:

UNINSTALL COMPONENT“file:// component_audit_api_message_emit”;

UNINSTALL COMPONENT 卸载组件,并从中取消注册 mysql.component 系统表中 以使其在后续服务器启动期间不被加载。

安装或卸载 audit_api_message_emit 组件会安装或卸载 audit_api_message_emit_udf() 组件实现 功能。 没有必要使用 CREATE FUNCTION DROP FUNCTION 这样做。

审核消息功能

本节介绍 组件 audit_api_message_emit_udf() 实现 用户定义函数(UDF) audit_api_message_emit

在使用审核消息功能之前,请根据 安装或卸载审核消息组件中 提供的说明 安装审核消息组件

  • audit_api_message_emit_udf(component, producer, message[, key, value] ...)

    将消息事件添加到审核日志中。 消息事件包括调用者选择的组件,生成器和消息字符串,以及可选的一组键值对。

    此UDF发布的事件将发送到所有已启用的审计类型插件,每个插件都根据自己的规则处理事件。 如果未启用审核类型的插件,则发布该事件无效。

    参数:

    • component :一个指定组件名称的字符串。

    • producer :一个指定生产者名称的字符串。

    • message :一个指定事件消息的字符串。

    • key value :事件可能包含0个或更多键值对,这些键值对指定任意应用程序提供的数据映射。 每个 key 参数都是一个字符串,它指定紧随其后的 value 参数 的名称 每个 value 参数指定紧随其后的 key 参数 的值 每个 value 都可以是字符串或数值,或 NULL

    返回值:

    字符串 OK 表示成功 如果函数失败,则会发生错误。

    例:

    MySQL的> SELECT audit_api_message_emit_udf('component_text',
                                             'producer_text',
                                             'message_text',
                                             'key1', 'value1',
                                             'key2', 123,
                                             'key3', NULL) AS 'Message';
    + --------- +
    | 消息|
    + --------- +
    | 好的
    + --------- +
    

    附加信息:

    接收发布事件的每个审计插件都以 audit_api_message_emit_udf() 特定于插件的格式记录事件。 例如, audit_log 插件(参见 第6.4.5节“MySQL Enterprise Audit” )按如下方式记录消息值,具体取决于 audit_log_format 系统变量 配置的日志格式

    • JSON格式( audit_log_format=JSON ):

      {
        ...
        “阶级”:“消息”,
        “事件”:“用户”,
        ...
        “message_data”:{
          “component”:“component_text”,
          “producer”:“producer_text”,
          “message”:“message_text”,
          “map”:{
            “key1”:“value1”,
            “key2”:123,
            “key3”:null
          }
        }
      }
      
    • 新式XML格式( audit_log_format=NEW ):

      <AUDIT_RECORD>
       ...
       <名称>消息</ NAME>
       ...
       <COMMAND_CLASS>用户</ COMMAND_CLASS>
       <组件> component_text </ COMPONENT>
       <PRODUCER> producer_text </ PRODUCER>
       <MESSAGE> MESSAGE_TEXT </ MESSAGE>
       <MAP>
         <ELEMENT>
           <KEY> KEY1 </ KEY>
           <值>值1 </ VALUE>
         </ ELEMENT>
         <ELEMENT>
           <KEY> KEY2 </ KEY>
           <值> 123 </ VALUE>
         </ ELEMENT>
         <ELEMENT>
           <KEY> KEY3 </ KEY>
           <VALUE />
         </ ELEMENT>
       </ MAP>
      </ AUDIT_RECORD>
      
    • 旧式XML格式( audit_log_format=OLD ):

      <AUDIT_RECORD
        ...
        NAME = “消息”
        ...
        COMMAND_CLASS = “用户”
        COMPONENT = “component_text”
        生产者= “producer_text”
        MESSAGE = “MESSAGE_TEXT”/>
      
      注意

      由于此格式强加的表示性约束,以旧式XML格式记录的消息事件不包括键值映射。

    发布的消息 audit_api_message_emit_udf() 具有事件类 MYSQL_AUDIT_MESSAGE_CLASS 和子类 MYSQL_AUDIT_MESSAGE_USER (内部生成的审计消息具有相同的类和子类 MYSQL_AUDIT_MESSAGE_INTERNAL ;此子类当前未使用。)要在 audit_log 过滤规则中 引用此类事件 ,请使用 值为的 class 元素 例如: name message

    {
      “过滤器”:{
        “class”:{
          “名字”:“消息”
        }
      }
    }
    

    如果有必要区分用户生成的消息事件和内部生成的消息事件,请使用 测试 subclass user internal

    不支持基于键值映射的内容进行过滤。

    有关编写过滤规则的信息,请参见 第6.4.5.6节“审核日志过滤”

6.4.7 MySQL企业防火墙

注意

MySQL企业防火墙是商业产品MySQL企业版中的扩展。 要了解有关商业产品的更多信息,请访问 https://www.mysql.com/products/

MySQL企业版包括MySQL企业防火墙,这是一个应用程序级防火墙,使数据库管理员能够根据与已接受语句模式的白名单进行匹配来允许或拒绝SQL语句执行。 这有助于强化MySQL服务器免受SQL注入等攻击或尝试通过在合法查询工作负载特征之外使用应用程序来利用应用程序。

在防火墙中注册的每个MySQL帐户都有自己的语句白名单,可以为每个帐户定制保护。 对于给定的帐户,防火墙可以在记录,保护或检测模式下操作,用于接受可接受的语句模式的训练,针对不可接受的语句的主动保护,或对不可接受的语句的被动检测。 该图说明了防火墙如何处理每种模式下的传入语句。

图6.1 MySQL企业防火墙操作

Flow chart showing how MySQL Enterprise Firewall processes incoming SQL statements in recording, protecting, and detecting modes.

以下部分描述了MySQL Enterprise Firewall的组件,讨论了如何安装和使用它,并提供了其组件的参考信息。

6.4.7.1 MySQL企业防火墙组件

MySQL Enterprise Firewall基于实现这些组件的插件库:

  • 名为服务器端的插件 MYSQL_FIREWALL 在执行之前检查SQL语句,并根据其内存缓存,决定是执行还是拒绝每个语句。

  • 服务器端插件命名 MYSQL_FIREWALL_USERS MYSQL_FIREWALL_WHITELIST 实现 INFORMATION_SCHEMA 了提供防火墙数据缓存视图的表。

  • 名为 firewall_users firewall_whitelist mysql 数据库 中的 系统表 提供防火墙数据的持久存储。

  • 存储过程命名 sp_set_firewall_mode() sp_reload_firewall_rules() 执行诸如向防火墙注册MySQL帐户,建立其操作模式以及管理缓存与底层系统表之间的防火墙数据传输等任务。

  • 一组用户定义的函数为较低级别的任务提供SQL级API,例如将缓存与底层系统表同步。

  • 系统变量启用防火墙配置,状态变量提供运行时操作信息。

  • FIREWALL_ADMIN FIREWALL_USER 权限使用户可以分别管理任何用户的防火墙规则和他们自己的防火墙规则。

6.4.7.2安装或卸载MySQL Enterprise Firewall

MySQL Enterprise Firewall安装是一次性操作,用于安装 第6.4.7.1节“MySQL Enterprise Firewall Components”中 描述的 组件 可以使用图形界面或手动执行安装:

  • 在Windows上,MySQL Installer包含一个为您启用MySQL Enterprise Firewall的选项。

  • MySQL Workbench 6.3.4或更高版本可以安装MySQL Enterprise Firewall,启用或禁用已安装的防火墙,或卸载防火墙。

  • 手动MySQL Enterprise Firewall安装涉及运行位于 share MySQL安装目录中 的脚本

重要

按照说明阅读完整部分。 部分程序因环境而异。

注意

如果安装,MySQL Enterprise Firewall即使在禁用时也会涉及一些最小的开销。 为避免此开销,请不要安装防火墙,除非您打算使用它。

注意

MySQL Enterprise Firewall不与查询缓存一起使用。 如果启用了查询缓存,请在安装防火墙之前将其禁用(请参阅 查询缓存配置 )。

有关使用说明,请参见 第6.4.7.3节“使用MySQL Enterprise Firewall” 有关参考信息,请参见 第6.4.7.4节“MySQL Enterprise Firewall Reference”

安装MySQL企业防火墙

如果已从旧版本的MySQL安装了MySQL Enterprise Firewall,请使用本节后面给出的说明将其卸载,然后在安装当前版本之前重新启动服务器。 在这种情况下,还需要再次注册您的配置。

在Windows上,您可以使用MySQL Installer来安装MySQL Enterprise Firewall, 如图6.2“Windows上的MySQL Enterprise Firewall安装”所示 选中 Enable Enterprise Firewall 复选框。 用于网络访问的开放式防火墙端口 具有不同的用途。它指的是Windows防火墙并控制Windows是否阻止MySQL服务器侦听客户端连接的TCP / IP端口。)

图6.2 Windows上的MySQL Enterprise Firewall安装

Content is described in the surrounding text.

要使用MySQL Workbench 6.3.4或更高版本安装MySQL Enterprise Firewall,请参阅 MySQL Enterprise Firewall Interface

要手动安装MySQL Enterprise Firewall,请查看 share MySQL安装目录并选择适合您平台的脚本。 可用脚本的不同之处在于用于引用插件库文件的后缀:

  • win_install_firewall.sql :为 .dll 用作文件名后缀的 Windows系统选择此脚本

  • linux_install_firewall.sql :为Linux和类似系统选择此脚本, .so 用作文件名后缀。

安装脚本在默认数据库中创建存储过程,因此请选择要使用的数据库。 然后按如下所示运行脚本,在命令行上命名所选的数据库。 这里的例子使用了 mysql 数据库和Linux安装脚本。 为您的系统进行适当的替换。

shell> mysql -u root -p mysql < linux_install_firewall.sql
输入密码:(enter root password here)
注意

要在主/从复制,组复制或InnoDB群集的上下文中使用MySQL Enterprise Firewall,必须在主节点或主节点上运行安装脚本之前准备从节点或辅助节点。 这是必要的,因为 INSTALL PLUGIN 脚本中 语句不会被复制。

  1. 在每个从属节点或辅助节点上, INSTALL PLUGIN 从安装脚本中 提取 语句并手动执行它们。

  2. 在主节点或主节点上,按前面所述运行安装脚本。

使用图形界面或手动安装MySQL Enterprise Firewall应启用防火墙。 要验证这一点,请连接到服务器并执行以下语句:

MySQL的> SHOW GLOBAL VARIABLES LIKE 'mysql_firewall_mode';
+ --------------------- + ------- +
| Variable_name | 价值|
+ --------------------- + ------- +
| mysql_firewall_mode | ON |
+ --------------------- + ------- +

如果插件无法初始化,请检查服务器错误日志以获取诊断消息。

卸载MySQL Enterprise Firewall

可以使用MySQL Workbench或手动卸载MySQL Enterprise Firewall。

要使用MySQL Workbench 6.3.4或更高版本卸载MySQL Enterprise Firewall,请参阅 MySQL Enterprise Firewall Interface

要手动卸载MySQL Enterprise Firewall,请执行以下语句。 假设存储过程是在 mysql 数据库 中创建的 DROP PROCEDURE 如果在其他数据库中创建过程,请相应地 调整 语句。

DROP TABLE mysql.firewall_whitelist;
DROP TABLE mysql.firewall_users;
UNINSTALL PLUGIN mysql_firewall;
UNINSTALL PLUGIN mysql_firewall_whitelist;
UNINSTALL PLUGIN mysql_firewall_users;
DROP FUNCTION set_firewall_mode;
DROP FUNCTION normalize_statement;
DROP FUNCTION read_firewall_whitelist;
DROP FUNCTION read_firewall_users;
DROP FUNCTION mysql_firewall_flush_status;
DROP PROCEDURE mysql.sp_set_firewall_mode;
DROP PROCEDURE mysql.sp_reload_firewall_rules;

6.4.7.3使用MySQL企业防火墙

在使用MySQL Enterprise Firewall之前,请按照 第6.4.7.2节“安装或卸载MySQL Enterprise Firewall”中 提供的说明进行 安装 此外,MySQL Enterprise Firewall不能与查询缓存一起使用; 如果启用了查询缓存,请禁用它(请参阅 查询缓存配置 )。

本节介绍如何使用SQL语句配置MySQL Enterprise Firewall。 或者,MySQL Workbench 6.3.4或更高版本提供了防火墙控制的图形界面。 请参阅 MySQL企业防火墙接口

要启用或禁用防火墙,请设置 mysql_firewall_mode 系统变量。 默认情况下,安装防火墙时会启用此变量。 要显式控制初始防火墙状态,可以在服务器启动时设置变量。 例如,要在选项文件中启用防火墙,请使用以下行:

的[mysqld]
mysql_firewall_mode = ON

也可以在运行时禁用或启用防火墙:

mysql> SET GLOBAL mysql_firewall_mode = OFF;
mysql>SET GLOBAL mysql_firewall_mode = ON;

除了全局开/关防火墙模式之外,在防火墙中注册的每个帐户都有自己的操作模式。 对于处于录制模式的帐户,防火墙会学习应用程序的 指纹 ”。 ,即可接受的语句模式,它们组合在一起形成白名单。 训练之后,将防火墙切换到保护模式,以强化MySQL,使其不会被偏离指纹的语句访问。 要进行其他培训,请根据需要将防火墙切换回录制模式,以使用新的语句模式更新白名单。 可以使用入侵检测模式将可疑语句写入错误日志但不拒绝访问。

防火墙基于每个帐户维护白名单规则,从而实现以下保护策略:

  • 对于具有唯一保护要求的应用程序,请将其配置为使用不用于任何其他目的的帐户。

  • 对于相关和共享保护要求的应用程序,请将它们配置为一个组以使用同一帐户。

防火墙操作基于将SQL语句转换为规范化摘要形式。 防火墙摘要类似于性能模式使用的语句摘要(请参见 第26.10节“性能模式语句摘要和采样” )。 但是,与性能模式不同,相关的摘要相关系统变量是 max_digest_length

对于来自已注册帐户的连接,防火墙会将每个传入语句转换为规范化形式,并根据帐户模式对其进行处理:

  • 在记录模式下,防火墙会将规范化语句添加到帐户白名单规则中。

  • 在保护模式下,防火墙将规范化语句与帐户白名单规则进行比较。 如果匹配,则语句通过,服务器继续处理它。 否则,服务器拒绝该语句并向客户端返回错误。 如果 mysql_firewall_trace 启用 系统变量 ,防火墙还会将拒绝的语句写入错误日志

  • 在检测模式下,防火墙将语句与保护模式匹配,但将不匹配语句写入错误日志而不拒绝访问。

具有 OFF 防火墙 模式 或未在防火墙中注册的 帐户将 被忽略。

要使用MySQL Enterprise Firewall保护帐户,请按照下列步骤操作:

  1. 注册帐户并将其置于录制模式。

  2. 使用已注册的帐户连接到MySQL服务器并执行要学习的语句。 这将建立帐户的已接受语句的白名单。

  3. 将注册的帐户切换到保护模式。

以下示例说明如何向防火墙注册帐户,使用防火墙了解该帐户的可接受语句,并保护帐户不被执行不可接受的语句。 示例帐户 'fwuser'@'localhost' 供供访问 sakila 数据库中的 表的应用程序使用 (该数据库可在 https://dev.mysql.com/doc/index-other.html获得 。)

注意

帐户名的用户和主机部分分别为诸如 CREATE USER 和之类的 语句引用 GRANT ,而要指定用于防火墙组件的帐户,请将其命名为单引号字符串 'fwuser@localhost'

将帐户命名为防火墙组件的单引号字符串的约定意味着您不能使用 @ 在用户名 中包含嵌入 字符的 帐户

使用管理MySQL帐户执行以下过程中的步骤,但指定由防火墙注册的帐户执行的帐户除外。 默认数据库应该是 sakila 使用注册帐户执行的语句。

  1. 如有必要,创建要保护的帐户(选择适当的密码)并为其授予 sakila 数据库 权限

    
    mysql> CREATE USER 'fwuser'@'localhost' IDENTIFIED BY 'fWp@3sw0rd';
    mysql>GRANT ALL ON sakila.* TO 'fwuser'@'localhost';
    
  2. 使用 sp_set_firewall_mode() 存储过程向防火墙注册帐户并将其置于记录模式(如果过程位于数据库以外 mysql ,请相应地调整语句):

    MySQL的> CALL mysql.sp_set_firewall_mode('fwuser@localhost', 'RECORDING');
    

    在执行过程中,存储过程调用防火墙用户定义的函数,这些函数可能产生自己的输出。

  3. 使用已注册的帐户,连接到服务器,然后执行一些合法的语句:

    mysql> SELECT first_name, last_name FROM customer WHERE customer_id = 1;
    mysql> UPDATE rental SET return_date = NOW() WHERE rental_id = 1;
    mysql>SELECT get_customer_balance(1, NOW());
    

    防火墙将语句转换为摘要形式,并将其记录在帐户白名单中。

    注意

    在帐户以记录模式执行语句之前,其白名单为空,这相当于 拒绝全部。 如果切换到保护模式,将有效禁止该帐户执行语句。

  4. 此时,用户和白名单信息被缓存并可在防火墙中看到 INFORMATION_SCHEMA 表中

    MySQL的> SELECT MODE FROM INFORMATION_SCHEMA.MYSQL_FIREWALL_USERS
           WHERE USERHOST = 'fwuser@localhost';
    + ----------- +
    | MODE |
    + ----------- +
    | 记录|
    + ----------- +
    MySQL的> SELECT RULE FROM INFORMATION_SCHEMA.MYSQL_FIREWALL_WHITELIST
           WHERE USERHOST = 'fwuser@localhost';
    + ------------------------------------------------- --------------------------- +
    | 规则|
    + ------------------------------------------------- --------------------------- +
    | SELECT`first_name`,`last_name` FROM`customer` WHERE`customer_id` =?|
    | SELECT`get_customer_balance`(?,NOW())|
    | 更新`rental` SET`report_date` = NOW()WHERE` rental_id` =?|
    | SELECT @@`version_comment` LIMIT?|
    + ------------------------------------------------- --------------------------- +
    
    注意

    @@version_comment 规则来自 mysql 自动发送的语句 客户端作为注册用户连接到服务器时

    在与应用程序使用匹配的条件下训练防火墙非常重要。 例如,给定的MySQL连接器可能会在连接开始时向服务器发送语句,以确定服务器特性和功能。 如果通常通过该连接器使用应用程序,那么也要以这种方式训练防火墙。 这使得这些初始语句成为与应用程序关联的帐户的白名单的一部分。

  5. 使用存储过程将注册用户切换到保护模式:

    MySQL的> CALL mysql.sp_set_firewall_mode('fwuser@localhost', 'PROTECTING');
    
    重要

    将帐户切换出 RECORDING 模式会将其防火墙缓存数据同步到底层 mysql 系统数据库表以进行持久存储。 如果不为正在记录的用户切换模式,则缓存的白名单数据不会写入系统表,并且在重新启动服务器时将丢失。

  6. 使用已注册的帐户,执行一些可接受和不可接受的声明。 防火墙将每个防火墙与帐户白名单进行匹配,并接受或拒绝它。

    此语句与训练语句不同,但会产生与其中一个相同的规范化语句,因此防火墙接受它:

    MySQL的> SELECT first_name, last_name FROM customer WHERE customer_id = '48';
    + ------------ + ----------- +
    | first_name | last_name |
    + ------------ + ----------- +
    | ANN | EVANS |
    + ------------ + ----------- +
    

    这些语句与白名单中的任何内容都不匹配,每个语句都会导致错误:

    MySQL的> SELECT first_name, last_name FROM customer WHERE customer_id = 1 OR TRUE;
    错误1045(28000):语句被防火墙阻止
    MySQL的> SHOW TABLES LIKE 'customer%';
    错误1045(28000):语句被防火墙阻止
    MySQL的> TRUNCATE TABLE mysql.slow_log;
    错误1045(28000):语句被防火墙阻止
    

    如果 mysql_firewall_trace 启用 系统变量 ,防火墙还会将拒绝的语句写入错误日志 例如:

    [注意]插件MYSQL_FIREWALL报告:
    '为fwuser @ localhost拒绝访问。原因:白名单中没有匹配项。
    声明:TRUNCATE TABLE`mysql`。`slow_log`'
    

    您可以在努力中使用这些日志消息来识别攻击源。

  7. 您可以将不匹配的语句记录为可疑语句而不拒绝访问。 为此,请将帐户置于入侵检测模式:

    MySQL的> CALL mysql.sp_set_firewall_mode('fwuser@localhost', 'DETECTING');
    
  8. 使用已注册的帐户连接到服务器,然后执行与白名单不匹配的语句:

    MySQL的> SHOW TABLES LIKE 'customer%';
    + ------------------------------ +
    | Tables_in_sakila(客户%)|
    + ------------------------------ +
    | 客户|
    | customer_list |
    + ------------------------------ +
    

    在检测模式下,防火墙允许执行非匹配语句,但会将消息写入错误日志:

    [注意]插件MYSQL_FIREWALL报告:
    '来自'fwuser @ localhost'的可疑声明。原因:白名单中没有匹配项。
    声明:显示表格如何?
    
    注意

    检测模式将消息写为Notes,这是信息消息。 要确保此类消息出现在错误日志中并且不被丢弃,请确保将 log_error_verbosity 系统变量设置为值3。

  9. 要评估防火墙活动,请检查其状态变量:

    MySQL的> SHOW GLOBAL STATUS LIKE 'Firewall%';
    + ---------------------------- + ------- +
    | Variable_name | 价值|
    + ---------------------------- + ------- +
    | Firewall_access_denied | 3 |
    | Firewall_access_granted | 4 |
    | Firewall_access_suspicious | 1 |
    | Firewall_cached_entries | 4 |
    + ---------------------------- + ------- +
    

    这些变量分别表示拒绝,接受,记录为可疑的语句数,并分别添加到缓存中。 Firewall_access_granted 数是4,因为中 @@version_comment 通过发送声明 的mysql 你们每个人都用它来连接为注册用户三个时间客户端,再加上 SHOW TABLES 这是不会被阻止在声明 DETECTING 模式。

如果需要对帐户进行额外培训,请再次将其切换到记录模式,然后在执行要添加到白名单的语句后返回保护模式。

6.4.7.4 MySQL企业防火墙参考

以下讨论作为MySQL Enterprise Firewall组件的参考:

6.4.7.4.1 MySQL企业防火墙表

MySQL Enterprise Firewall维护帐户和白名单信息。 它使用 INFORMATION_SCHEMA 表来提供缓存数据和表中的表 mysql 系统数据库中的 以持久的形式存储这些数据。 启用后,防火墙将其操作决策基于缓存数据。

INFORMATION_SCHEMA 任何人都可以访问 这些 表格。 mysql 只有具有该数据库权限的用户才能访问 表。

INFORMATION_SCHEMA.MYSQL_FIREWALL_USERS mysql.firewall_users 表列表中注册的防火墙账户和他们的操作模式。 表格包含以下列:

  • USERHOST

    在防火墙中注册的帐户。 每个帐户都具有格式, 并表示服务器验证的实际用户名和主机名。 注册用户时不应使用模式和网络掩码。 user_name@host_name

  • MODE

    帐户的当前防火墙操作模式。 允许的模式值 OFF DETECTING PROTECTING RECORDING ,和 RESET 有关其含义的详细信息,请参阅的描述 sp_set_firewall_mode() 第6.4.7.4.2,“MySQL企业防火墙程序和功能”

INFORMATION_SCHEMA.MYSQL_FIREWALL_WHITELIST mysql.firewall_whitelist 表列表中注册的防火墙账户和他们的白名单。 表格包含以下列:

  • USERHOST

    在防火墙中注册的帐户。 格式与用户帐户表的格式相同。

  • RULE

    标准化语句,指示帐户可接受的语句模式。 帐户白名单是其规则的结合。

  • ID

    一个整数列,它是表的主键。 此列已添加到MySQL 8.0.12中。

6.4.7.4.2 MySQL企业防火墙程序和功能

MySQL Enterprise Firewall具有执行任务的存储过程,例如向防火墙注册MySQL帐户,建立其操作模式,以及管理缓存和底层系统表之间的防火墙数据传输。 它还有一组用户定义的函数(UDF),为较低级别的任务提供SQL级API,例如将缓存与底层系统表同步。

在正常操作下,存储过程实现用户界面。 UDF由存储过程调用,而不是由用户直接调用。

要在默认数据库不是包含该过程的数据库时调用存储过程,请使用数据库名称限定过程名称。 例如:

CALL mysql.sp_set_firewall_mode(usermode);

以下列表描述了每个防火墙存储过程和UDF:

  • sp_reload_firewall_rules(user)

    此存储过程使用防火墙UDF重置已注册的帐户,并从存储在 mysql.firewall_whitelist 表中 的规则重新加载内存中的规则 此过程可控制各个帐户的防火墙操作。

    user 参数名受影响的帐户,作为一个字符串 格式。 user_name@host_name

    例:

    CALL mysql.sp_reload_firewall_rules('fwuser @ localhost');
    
    警告

    此过程将帐户模式设置为 RESET ,清除帐户白名单并将其模式设置为 OFF 如果帐户模式不在 呼叫 OFF 之前, sp_reload_firewall_rules() sp_set_firewall_mode() 在重新加载规则后用于恢复其先前的模式。 例如,如果帐户处于 PROTECTING 模式,则在调用后不再为真 sp_reload_firewall_rules() ,您必须 PROTECTING 再次 将其设置为 显式。

  • sp_set_firewall_mode(user, mode)

    此存储过程向防火墙注册MySQL帐户并建立其操作模式。 该过程还根据需要调用防火墙UDF,以在缓存和底层系统表之间传输防火墙数据。 即使 mysql_firewall_mode 系统变量是 OFF 也可以调用此过程 ,尽管在禁用防火墙时设置帐户模式没有操作效果。

    user 参数名受影响的帐户,作为一个字符串 格式。 user_name@host_name

    mode 是用户的操作模式,作为字符串。 允许使用这些模式值:

    • OFF :禁用该帐户的防火墙。

    • DETECTING :入侵检测模式:将可疑(不匹配)语句写入错误日志但不拒绝访问。

    • PROTECTING :通过将传入的语句与帐户白名单进行匹配来保护帐户。

    • RECORDING :培训模式:记录帐户可接受的报表。 记录不会立即失败并出现语法错误的传入语句将成为帐户白名单规则的一部分。

    • RESET :清除帐户白名单并将帐户模式设置为 OFF

    将帐户模式切换到任何模式,但 RECORDING 将防火墙缓存数据同步到底层 mysql 系统数据库表以进行持久存储。 切换模式 OFF RECORDING 将白名单从 mysql.firewall_whitelist 重新加载 到缓存中。

    如果帐户具有空白名单, PROTECTING 请将 其模式设置为 生成在结果集中返回的错误消息,但不会出现SQL错误:

    MySQL的> CALL mysql.sp_set_firewall_mode('a@b','PROTECTING');
    + ------------------------------------------------- --------------------- +
    | set_firewall_mode(arg_userhost,arg_mode)|
    + ------------------------------------------------- --------------------- +
    | 错误:@ b请求的保护模式,但白名单为空。|
    + ------------------------------------------------- --------------------- +
    1排(0.02秒)
    
    查询OK,0行受影响(0.02秒)
    
  • mysql_firewall_flush_status()

    此UDF将多个防火墙状态变量重置为0:

    Firewall_access_denied
    Firewall_access_granted
    Firewall_access_suspicious
    

    例:

    SELECT mysql_firewall_flush_status();
    
  • normalize_statement(stmt)

    此UDF将SQL语句规范化为用于白名单规则的摘要形式。

    例:

    SELECT normalize_statement('SELECT * FROM t1 WHERE c1> 2');
    
  • read_firewall_users(user, mode)

    此聚合UDF通过 SELECT 表上的语句 更新防火墙用户缓存 mysql.firewall_users

    例:

    SELECT read_firewall_users('fwuser @ localhost','RECORDING')
    来自mysql.firewall_users;
    
  • read_firewall_whitelist(user, rule)

    此聚合UDF通过 SELECT 表上的 语句更新记录的语句高速缓存 mysql.firewall_whitelist

    例:

    SELECT read_firewall_whitelist('fwuser @ localhost','RECORDING')
    来自mysql.firewall_whitelist;
    
  • set_firewall_mode(user, mode)

    此UDF管理用户缓存并建立用户操作模式。

    例:

    SELECT set_firewall_mode('fwuser @ localhost','RECORDING');
    
6.4.7.4.3 MySQL企业防火墙系统变量

MySQL Enterprise Firewall支持以下系统变量。 使用它们配置防火墙操作。 除非安装了防火墙,否则这些变量不可用(请参见 第6.4.7.2节“安装或卸载MySQL Enterprise Firewall” )。

  • mysql_firewall_mode

    属性
    命令行格式 --mysql-firewall-mode[={OFF|ON}]
    介绍 8.0.11
    系统变量 mysql_firewall_mode
    范围 全球
    动态
    SET_VAR 提示适用 没有
    类型 布尔
    默认值 ON

    是启用MySQL企业防火墙(默认)还是禁用。

  • mysql_firewall_trace

    属性
    命令行格式 --mysql-firewall-trace[={OFF|ON}]
    介绍 8.0.11
    系统变量 mysql_firewall_trace
    范围 全球
    动态
    SET_VAR 提示适用 没有
    类型 布尔
    默认值 OFF

    是启用还是禁用MySQL Enterprise Firewall跟踪(默认设置)。 mysql_firewall_trace 启用时,为 PROTECTING 模式,防火墙写入拒绝语句错误日志。

6.4.7.4.4 MySQL企业防火墙状态变量

MySQL Enterprise Firewall支持以下状态变量。 使用它们获取有关防火墙操作状态的信息。 除非安装了防火墙,否则这些变量不可用(请参见 第6.4.7.2节“安装或卸载MySQL Enterprise Firewall” )。 每当 MYSQL_FIREWALL 安装插件或启动服务器 时,防火墙状态变量都将设置为0 其中许多由 mysql_firewall_flush_status() UDF 重置为零 (请参见 第6.4.7.4.2节“MySQL企业防火墙过程和函数” )。

6.4.8 MySQL企业数据屏蔽和去标识

注意

MySQL企业数据屏蔽和去标识是MySQL企业版(一种商业产品)中包含的扩展。 要了解有关商业产品的更多信息, 请访问https://www.mysql.com/products/

从MySQL 8.0.13开始,MySQL Enterprise Edition提供数据屏蔽和去识别功能:

  • 转换现有数据以屏蔽它并删除识别特征,例如更改信用卡号码的所有数字,但最后四个更改为 'X' 字符 字符。

  • 生成随机数据,例如电子邮件地址和支付卡号。

应用程序使用这些功能的方式取决于数据的使用目的以及访问数据的人员:

  • 使用敏感数据的应用程序可以通过执行数据屏蔽并允许使用部分屏蔽数据进行客户端识别来保护它。 示例:呼叫中心可能会要求客户提供其最后四个社会安全号码。

  • 需要格式正确的数据但不一定是原始数据的应用程序可以合成样本数据。 示例:正在测试数据验证程序但无法访问原始数据的应用程序开发人员可能会使用相同的格式合成随机数据。

例1:

医学研究机构可以保存包含个人和医疗数据混合的患者数据。 这可能包括遗传序列(长串),以JSON格式存储的测试结果以及其他数据类型。 虽然数据可能主要由自动分析软件使用,但仍然可以访问基因组数据或特定患者的测试结果。 在这种情况下,应使用数据屏蔽来提供此信息,而不是个人身份信息。

例2:

信用卡处理器公司使用敏感数据提供一组服务,例如:

  • 每秒处理大量金融交易。

  • 存储大量与交易相关的数据。

  • 保护与交易相关的数据,严格要​​求个人数据。

  • 使用可逆或部分屏蔽数据处理客户对交易的投诉。

典型的交易可能包括许多类型的敏感信息,包括:

  • 信用卡号。

  • 交易类型和金额。

  • 商家类型。

  • 交易密码(确认交易合法性)。

  • 配备GPS的终端的地理位置(用于欺诈检测)。

然后,这些类型的信息可以在银行或其他发卡金融机构内与客户个人数据相结合,例如:

  • 完整的客户名称(个人或公司)。

  • 地址。

  • 出生日期。

  • 社会安全号码。

  • 电子邮件地址。

  • 电话号码。

卡处理公司和金融机构内的各种员工角色需要访问该数据。 其中一些角色可能只需要访问屏蔽数据。 其他角色可能需要根据具体情况访问原始数据,该数据记录在审计日志中。

屏蔽和去识别是法规遵从的核心,因此MySQL Enterprise Data Masking和De-Identification可以帮助应用程序开发人员满足隐私要求:

  • PCI - DSS:支付卡数据。

  • HIPAA:健康数据隐私,健康信息技术促进经济和临床健康法案(HITECH法案)。

  • 欧盟通用数据保护指令(GDPR):保护个人数据。

  • 数据保护法(英国):保护个人数据。

  • Sarbanes Oxley,GLBA,美国爱国者法案,1998年身份盗窃和假设威慑法案。

  • FERPA - 学生数据,NASD,CA SB1386和AB 1950,国家数据保护法,巴塞尔协议II。

以下部分描述了MySQL Enterprise Data Masking和De-Identification的组件,讨论了如何安装和使用它,并提供了其组件的参考信息。

6.4.8.1 MySQL企业数据屏蔽和去识别组件

MySQL Enterprise Data Masking和De-Identification基于一个实现这些组件的插件库:

  • 一个名为的服务器端插件 data_masking

  • 一组用户定义函数(UDF)提供用于执行屏蔽和去标识操作的SQL级API。 其中一些功能需要 SUPER 特权。

6.4.8.2安装或卸载MySQL Enterprise Data Masking和De-Identification

本节介绍如何安装或卸载MySQL Enterprise Data Masking和De-Identification,它是作为包含插件和用户定义函数(UDF)的插件库文件实现的。 有关安装或卸载插件和UDF的一般信息,请参见 第5.6.1节“安装和卸载插件” 第5.7.1节“安装和卸载用户定义的函数”

要使服务器可以使用,插件库文件必须位于MySQL插件目录( plugin_dir 系统变量 指定的目录 )中。 如有必要,通过设置 plugin_dir 服务器启动时 的值来配置插件目录位置

插件库文件基本名称是 data_masking 文件名后缀因平台 .so 而异 (例如, 对于Unix和类Unix系统, .dll 对于Windows)。

要安装MySQL Enterprise Data Masking和De-Identification插件和UDF,请使用 INSTALL PLUGIN CREATE FUNCTION 语句(调整 .so 根据需要 平台 后缀):

INSTALL PLUGIN data_masking SONAME'data_masking.so';
创建功能gen_blacklist返回字符串
  SONAME'data_masking.so';
CREATE FUNCTION gen_dictionary返回STRING
  SONAME'data_masking.so';
创建功能gen_dictionary_drop返回STRING
  SONAME'data_masking.so';
CREATE FUNCTION gen_dictionary_load RETURNS STRING
  SONAME'data_masking.so';
创建功能gen_range返回INTEGER
  SONAME'data_masking.so';
创建功能gen_rnd_email返回STRING
  SONAME'data_masking.so';
创建功能gen_rnd_pan返回字符串
  SONAME'data_masking.so';
创建功能gen_rnd_ssn返回字符串
  SONAME'data_masking.so';
创建功能gen_rnd_us_phone返回字符串
  SONAME'data_masking.so';
CREATE FUNCTION mask_inner RETURNS STRING
  SONAME'data_masking.so';
CREATE FUNCTION mask_outer RETURNS STRING
  SONAME'data_masking.so';
CREATE FUNCTION mask_pan RETURNS STRING
  SONAME'data_masking.so';
创建功能mask_pan_relaxed RETURNS STRING
  SONAME'data_masking.so';
创建功能mask_ssn RETURNS STRING
  SONAME'data_masking.so';

如果在主复制服务器上使用插件和UDF,请将它们安装在所有从属服务器上,以避免复制问题。

如上所述安装后,插件和UDF将保持安装状态,直到卸载为止。 要删除它们,请使用 UNINSTALL PLUGIN DROP FUNCTION 语句:

UNINSTALL PLUGIN data_masking;
DROP FUNCTION gen_blacklist;
DROP FUNCTION gen_dictionary;
DROP FUNCTION gen_dictionary_drop;
DROP FUNCTION gen_dictionary_load;
DROP FUNCTION gen_range;
DROP FUNCTION gen_rnd_email;
DROP FUNCTION gen_rnd_pan;
DROP FUNCTION gen_rnd_ssn;
DROP FUNCTION gen_rnd_us_phone;
DROP FUNCTION mask_inner;
DROP FUNCTION mask_outer;
DROP FUNCTION mask_pan;
DROP FUNCTION mask_pan_relaxed;
DROP FUNCTION mask_ssn;

6.4.8.3使用MySQL企业数据屏蔽和去标识

在使用MySQL Enterprise Data Masking和De-Identification之前,请按照 第6.4.8.2节“安装或卸载MySQL Enterprise Data Masking and De-Identification”中 提供的说明进行 安装

要在应用程序中使用MySQL Enterprise Data Masking和De-Identification,请调用适合您要执行的操作的函数。 有关详细的功能说明,请参见 第6.4.8.4节“MySQL企业数据屏蔽和取消标识用户定义的函数参考” 本节演示如何使用这些功能执行一些代表性任务。 它首先概述了可用的功能,然后是一些如何在现实环境中使用这些功能的示例:

屏蔽数据以删除识别特征

MySQL提供掩盖任意字符串的通用掩码函数,以及掩盖特定类型值的特殊用途掩码函数。

通用掩蔽功能

mask_inner() 并且 mask_outer() 是通用函数,它根据字符串中的位置屏蔽任意字符串的部分:

  • mask_inner() 屏蔽其字符串参数的内部,使末端不被屏蔽。 其他参数指定未屏蔽结束的大小。

    MySQL的> SELECT mask_inner('This is a string', 5, 1);
    + -------------------------------------- +
    | mask_inner('这是一个字符串',5,1)|
    + -------------------------------------- +
    | 这个XXXXXXXXXXg |
    + -------------------------------------- +
    MySQL的> SELECT mask_inner('This is a string', 1, 5);
    + -------------------------------------- +
    | mask_inner('这是一个字符串',1,5)|
    + -------------------------------------- +
    | TXXXXXXXXXXtring |
    + -------------------------------------- +
    
  • mask_outer() 反过来,屏蔽其字符串参数的末尾,使内部屏蔽。 其他参数指定蒙版末端的大小。

    MySQL的> SELECT mask_outer('This is a string', 5, 1);
    + -------------------------------------- +
    | mask_outer('这是一个字符串',5,1)|
    + -------------------------------------- +
    | XXXXX是一个strinX |
    + -------------------------------------- +
    MySQL的> SELECT mask_outer('This is a string', 1, 5);
    + -------------------------------------- +
    | mask_outer('这是一个字符串',1,5)|
    + -------------------------------------- +
    | Xhis是一个sXXXXX |
    + -------------------------------------- +
    

默认情况下, mask_inner() mask_outer() 使用 'X' 作为掩蔽的性格,但允许一个可选的屏蔽字符参数:

MySQL的> SELECT mask_inner('This is a string', 5, 1, '*');
+ ------------------------------------------- +
| mask_inner('这是一个字符串',5,1,'*')|
+ ------------------------------------------- +
| 这个********** g |
+ ------------------------------------------- +
MySQL的> SELECT mask_outer('This is a string', 5, 1, '#');
+ ------------------------------------------- +
| mask_outer('这是一个字符串',5,1,'#')|
+ ------------------------------------------- +
| #####是一个strin#|
+ ------------------------------------------- +
专用掩蔽功能

其他掩码函数需要一个表示特定类型值的字符串参数,并将其屏蔽以删除识别特征。

注意

这里的示例使用返回适当类型值的随机值生成函数来提供函数参数。 有关生成函数的更多信息,请参阅 生成具有特定特征的随机数据

支付卡主帐号掩盖。  屏蔽功能提供严格和轻松的主帐号屏蔽。

  • mask_pan() 除了数字的最后四位数字外,其他所有数字:

    MySQL的> SELECT mask_pan(gen_rnd_pan());
    + ------------------------- +
    | mask_pan(gen_rnd_pan())|
    + ------------------------- +
    | XXXXXXXXXXXX2461 |
    + ------------------------- +
    
  • mask_pan_relaxed() 类似但不掩盖表示支付卡发行人未屏蔽的前六位数字:

    MySQL的> SELECT mask_pan_relaxed(gen_rnd_pan());
    + --------------------------------- +
    | mask_pan_relaxed(gen_rnd_pan())|
    + --------------------------------- +
    | 770630XXXXXX0807 |
    + --------------------------------- +
    

美国社会安全号码掩盖。  mask_ssn() 除了数字的最后四位数字外,其他所有数字:

MySQL的> SELECT mask_ssn(gen_rnd_ssn());
+ ------------------------- +
| mask_ssn(gen_rnd_ssn())|
+ ------------------------- +
| XXX-XX-1723 |
+ ------------------------- +
生成具有特定特征的随机数据

几个函数生成随机值。 这些值可用于测试,模拟等。

gen_range() 返回从给定范围中选择的随机整数:

MySQL的> SELECT gen_range(1, 10);
+ ------------------ +
| gen_range(1,10)|
+ ------------------ +
| 6 |
+ ------------------ +

gen_rnd_email() 返回 example.com 域中 的随机电子邮件地址

MySQL的> SELECT gen_rnd_email();
+ --------------------------- +
| gen_rnd_email()|
+ --------------------------- +
| ayxnq.xmkpvvy@example.com |
+ --------------------------- +

gen_rnd_pan() 返回随机支付卡主帐号:

MySQL的> SELECT gen_rnd_pan();

gen_rnd_pan() 函数结果未显示,因为其返回值应仅用于测试目的,而不是用于发布。不能保证该数字不会分配给合法的支付帐户。)

gen_rnd_ssn() 返回一个随机的美国社会安全号码,其第一和第二部分各自从不用于合法数字的范围中选择:

MySQL的> SELECT gen_rnd_ssn();
+ --------------- +
| gen_rnd_ssn()|
+ --------------- +
| 912-45-1615 |
+ --------------- +

gen_rnd_us_phone() 返回555区号中的随机美国电话号码,不用于合法号码:

MySQL的> SELECT gen_rnd_us_phone();
+ -------------------- +
| gen_rnd_us_phone()|
+ -------------------- +
| 1-555-747-5627 |
+ -------------------- +
使用字典生成随机数据

MySQL Enterprise Data Masking和De-Identification使字典可用作随机值的来源。 要使用字典,必须首先从文件加载并给出名称。 每个加载的字典都成为字典注册表的一部分。 然后可以从已注册的词典中选择项目,并将其用作随机值或替换其他值。

有效的字典文件具有以下特征:

  • 文件内容为纯文本,每行一个术语。

  • 空行被忽略。

  • 该文件必须至少包含一个术语。

假设一个名为的文件 de_cities.txt 在德国包含这些城市名称:

柏林
慕尼黑
不来梅

还假设一个名为的文件 us_cities.txt 在美国包含这些城市名称:

芝加哥
休斯顿
凤凰
埃尔帕索
底特律

假设 secure_file_priv 系统变量设置为 /usr/local/mysql/mysql-files 在这种情况下,将字典文件复制到该目录,以便MySQL服务器可以访问它们。 然后使用 gen_dictionary_load() 将字典加载到字典注册表中并为其指定名称:

MySQL的> SELECT gen_dictionary_load('/usr/local/mysql/mysql-files/de_cities.txt', 'DE_Cities');
+ ------------------------------------------------- ------------------------------- +
| gen_dictionary_load('/ usr / local / mysql / mysql-files / de_cities.txt','DE_Cities')|
+ ------------------------------------------------- ------------------------------- +
| 字典加载成功|
+ ------------------------------------------------- ------------------------------- +
MySQL的> SELECT gen_dictionary_load('/usr/local/mysql/mysql-files/us_cities.txt', 'US_Cities');
+ ------------------------------------------------- ------------------------------- +
| gen_dictionary_load('/ usr / local / mysql / mysql-files / us_cities.txt','US_Cities')|
+ ------------------------------------------------- ------------------------------- +
| 字典加载成功|
+ ------------------------------------------------- ------------------------------- +

要从字典中选择随机项,请使用 gen_dictionary()

MySQL的> SELECT gen_dictionary('DE_Cities');
+ ----------------------------- +
| gen_dictionary('DE_Cities')|
+ ----------------------------- +
| 柏林|
+ ----------------------------- +
MySQL的> SELECT gen_dictionary('US_Cities');
+ ----------------------------- +
| gen_dictionary('US_Cities')|
+ ----------------------------- +
| 凤凰城|
+ ----------------------------- +

要从多个词典中选择一个随机词,请随机选择其中一个词典,然后从中选择一个词:

MySQL的> SELECT gen_dictionary(ELT(gen_range(1,2), 'DE_Cities', 'US_Cities'));
+ ------------------------------------------------- -------------- +
| gen_dictionary(ELT(gen_range(1,2),'DE_Cities','US_Cities'))|
+ ------------------------------------------------- -------------- +
| 底特律|
+ ------------------------------------------------- -------------- +
MySQL的> SELECT gen_dictionary(ELT(gen_range(1,2), 'DE_Cities', 'US_Cities'));
+ ------------------------------------------------- -------------- +
| gen_dictionary(ELT(gen_range(1,2),'DE_Cities','US_Cities'))|
+ ------------------------------------------------- -------------- +
| 不来梅|
+ ------------------------------------------------- -------------- +

gen_blacklist() 函数使得来自一个字典的术语可以被来自另一个字典的术语替换,该术语通过替换来实现掩蔽。 它的参数是要替换的术语,术语出现的字典,以及从中选择替换的字典。 例如,要将美国城市替换为德国城市,反之亦然,请使用 gen_blacklist() 如下:

MySQL的> SELECT gen_blacklist('Munich', 'DE_Cities', 'US_Cities');
+ ------------------------------------------------- -  +
| gen_blacklist('慕尼黑','DE_Cities','US_Cities')|
+ ------------------------------------------------- -  +
| 休斯顿|
+ ------------------------------------------------- -  +
MySQL的> SELECT gen_blacklist('El Paso', 'US_Cities', 'DE_Cities');
+ ------------------------------------------------- --- +
| gen_blacklist('El Paso','US_Cities','DE_Cities')|
+ ------------------------------------------------- --- +
| 不来梅|
+ ------------------------------------------------- --- +

如果要替换的术语不在第一个字典中, gen_blacklist() 则将其保持不变:

MySQL的> SELECT gen_blacklist('Moscow', 'DE_Cities', 'US_Cities');
+ ------------------------------------------------- -  +
| gen_blacklist('莫斯科','DE_Cities','US_Cities')|
+ ------------------------------------------------- -  +
| 莫斯科|
+ ------------------------------------------------- -  +
使用蒙面数据进行客户识别

在客户服务呼叫中心,一种常见的身份验证技术是要求客户提供他们的最后四个社会安全号码(SSN)数字。 例如,客户可能会说她的名字是乔安娜邦德,而她的最后四个SSN数字是 0007

假设 customer 包含客户记录 表具有以下列:

  • id :客户ID号。

  • first_name :客户名。

  • last_name :客户姓氏。

  • ssn :客户社会安全号码。

客户服务代表用于检查客户SSN的应用程序可能会执行如下查询:

mysql> SELECT id, ssn
mysql> FROM customer
mysql>WHERE first_name = 'Joanna' AND last_name = 'Bond';
+ ----- + ------------- +
| id | ssn |
+ ----- + ------------- +
| 786 | 906-39-0007 |
+ ----- + ------------- +

但是,这会将SSN暴露给客户服务代表,客户服务代表除了最后四位数外无需查看任何内容。 相反,应用程序可以使用此查询仅显示屏蔽的SSN:

mysql> SELECT id, mask_ssn(CONVERT(ssn USING binary))
mysql> FROM customer
mysql>WHERE first_name = 'Joanna' AND last_name = 'Bond';
+ ----- + ------------------------------- +
| id | mask_ssn(CONVERT(ssn使用二进制))|
+ ----- + ------------------------------- +
| 786 | XXX-XX-0007 |
+ ----- + ------------------------------- +

现在,代表只看到了必要的内容,并保留了客户隐私。

为什么 CONVERT() 函数用于参数 mask_ssn() 因为 mask_ssn() 需要长度为11的参数,并且因为UDF将字符串参数视为二进制字符串,每个字符一个字节。 因此,即使 ssn 被定义为 VARCHAR(11) ,如果 ssn 列具有多字节字符集,则在传递给UDF时它似乎长于11个字节,并且发生错误。 将值转换为二进制字符串可确保UDF看到长度为11的参数。

当字符串参数没有单字节字符集时,其他数据屏蔽函数可能需要类似的技术。

创建显示屏蔽数据的视图

如果表中的掩码数据用于多个查询,则定义生成掩码数据的视图可能很方便。 这样,应用程序可以从视图中进行选择,而无需在单个查询中执行屏蔽。

例如, customer 可以像下面这样定义上一节中表格 的掩蔽视图

创建视图masked_customer AS
SELECT id,first_name,last_name,mask_ssn(CONVERT(ssn USING binary))AS ssn
来自客户;

然后查询客户的查询变得更简单但仍返回屏蔽数据:

mysql> SELECT id, ssn
mysql> FROM masked_customer
mysql>WHERE first_name = 'Joanna' AND last_name = 'Bond';
+ ----- + ------------- +
| id | ssn |
+ ----- + ------------- +
| 786 | XXX-XX-0007 |
+ ----- + ------------- +

6.4.8.4 MySQL企业数据屏蔽和去标识用户自定义函数参考

MySQL企业数据屏蔽和去标识插件库包括几个用户定义的函数(UDF),它们可以分为以下类别:

这些UDF将字符串参数视为二进制字符串,这意味着它们隐式区分大小写。 此外,字符串UDF返回值是二进制字符串。 如果字符串返回值应该在不同的字符集中,请转换它。 以下示例显示如何将结果转换 gen_rnd_email() utf8mb4 字符集:

SET @email = CONVERT(gen_rnd_email()USING utf8mb4);

也可能需要转换字符串参数,如 使用屏蔽数据进行客户识别中所示

数据屏蔽功能

本节中的每个函数对其字符串参数执行屏蔽操作并返回屏蔽结果。

  • mask_inner(str, margin1, margin2 [, mask_char])

    掩盖字符串的内部部分,保持两端不变,并返回结果。 可以指定可选的屏蔽字符。

    参数:

    • str :要屏蔽的字符串。

    • margin1 :非负整数,指定要保持未屏蔽的字符串左端的字符数。 如果值为0,则不会取消屏蔽左端字符。

    • margin2 :非负整数,指定要保持未屏蔽的字符串右端的字符数。 如果值为0,则不会取消屏蔽右端字符。

    • mask_char :(可选)用于屏蔽的单个字符。 默认值为 'X' if mask_char 未给出。

      由于UDF字符串参数被视为二进制字符串,因此屏蔽字符必须是单字节字符。 尝试使用多字节字符会产生错误。

    返回值:

    屏蔽的字符串,或者 NULL 如果任一边距是负的。

    如果边距值的总和大于参数长度,则不会发生屏蔽,并且参数将保持不变。

    例:

    MySQL的> SELECT mask_inner('abcdef', 1, 2), mask_inner('abcdef',0, 5);
    + ---------------------------- + -------------------- ------- +
    | mask_inner('abcdef',1,2)| mask_inner('abcdef',0,5)|
    + ---------------------------- + -------------------- ------- +
    | aXXXef | Xbcdef |
    + ---------------------------- + -------------------- ------- +
    MySQL的> SELECT mask_inner('abcdef', 1, 2, '*'), mask_inner('abcdef',0, 5, '#');
    + --------------------------------- + --------------- ----------------- +
    | mask_inner('abcdef',1,2,'*')| mask_inner('abcdef',0,5,'#')|
    + --------------------------------- + --------------- ----------------- +
    | a *** ef | #bcdef |
    + --------------------------------- + --------------- ----------------- +
    
  • mask_outer(str, margin1, margin2 [, mask_char])

    掩盖字符串的左端和右端,使内部不显示,并返回结果。 可以指定可选的屏蔽字符。

    参数:

    • str :要屏蔽的字符串。

    • margin1 :非负整数,指定要屏蔽的字符串左端的字符数。 如果值为0,则不会屏蔽左端字符。

    • margin2 :非负整数,指定要屏蔽的字符串右端的字符数。 如果值为0,则不会屏蔽右端字符。

    • mask_char :(可选)用于屏蔽的单个字符。 默认值为 'X' if mask_char 未给出。

      由于UDF字符串参数被视为二进制字符串,因此屏蔽字符必须是单字节字符。 尝试使用多字节字符会产生错误。

    返回值:

    屏蔽的字符串,或者 NULL 如果任一边距是负的。

    如果边距值的总和大于参数长度,则会屏蔽整个参数。

    例:

    MySQL的> SELECT mask_outer('abcdef', 1, 2), mask_outer('abcdef',0, 5);
    + ---------------------------- + -------------------- ------- +
    | mask_outer('abcdef',1,2)| mask_outer('abcdef',0,5)|
    + ---------------------------- + -------------------- ------- +
    | XbcdXX | aXXXXX |
    + ---------------------------- + -------------------- ------- +
    MySQL的> SELECT mask_outer('abcdef', 1, 2, '*'), mask_outer('abcdef',0, 5, '#');
    + --------------------------------- + --------------- ----------------- +
    | mask_outer('abcdef',1,2,'*')| mask_outer('abcdef',0,5,'#')|
    + --------------------------------- + --------------- ----------------- +
    | * bcd ** | ##### |
    + --------------------------------- + --------------- ----------------- +
    
  • mask_pan(str)

    屏蔽支付卡主帐号并返回除最后四位数字以外的所有数字替换的数字 'X'

    参数:

    • str :要屏蔽的字符串。 字符串必须是主帐号的合适长度,但不会以其他方式检查。

    返回值:

    屏蔽的支付号码为字符串。 如果参数短于要求,则返回不变。

    例:

    MySQL的> SELECT mask_pan(gen_rnd_pan());
    + ------------------------- +
    | mask_pan(gen_rnd_pan())|
    + ------------------------- +
    | XXXXXXXXXXXX9102 |
    + ------------------------- +
    MySQL的> SELECT mask_pan(gen_rnd_pan(19));
    + --------------------------- +
    | mask_pan(gen_rnd_pan(19))|
    + --------------------------- +
    | XXXXXXXXXXXXXXX8268 |
    + --------------------------- +
    MySQL的> SELECT mask_pan('a*Z');
    + ----------------- +
    | mask_pan('a * Z')|
    + ----------------- +
    | a * Z |
    + ----------------- +
    
  • mask_pan_relaxed(str)

    屏蔽支付卡主帐号并返回除前六个和后四个数字以外的所有数字替换的数字 'X' 前六位数字表示支付卡发行者。

    参数:

    • str :要屏蔽的字符串。 字符串必须是主帐号的合适长度,但不会以其他方式检查。

    返回值:

    屏蔽的支付号码为字符串。 如果参数短于要求,则返回不变。

    例:

    MySQL的> SELECT mask_pan_relaxed(gen_rnd_pan());
    + --------------------------------- +
    | mask_pan_relaxed(gen_rnd_pan())|
    + --------------------------------- +
    | 551279XXXXXX3108 |
    + --------------------------------- +
    MySQL的> SELECT mask_pan_relaxed(gen_rnd_pan(19));
    + ----------------------------------- +
    | mask_pan_relaxed(gen_rnd_pan(19))|
    + ----------------------------------- +
    | 462634XXXXXXXXX6739 |
    + ----------------------------------- +
    MySQL的> SELECT mask_pan_relaxed('a*Z');
    + ------------------------- +
    | mask_pan_relaxed('a * Z')|
    + ------------------------- +
    | a * Z |
    + ------------------------- +
    
  • mask_ssn(str)

    屏蔽美国社会安全号码并返回除最后四位数之外的所有号码 'X'

    参数:

    • str :要屏蔽的字符串。 该字符串长度必须为11个字符,但不会以其他方式检查。

    返回值:

    被屏蔽的社会安全号码作为字符串,或者 NULL 如果参数不是正确的长度。

    例:

    MySQL的> SELECT mask_ssn('909-63-6922'), mask_ssn('abcdefghijk');
    + ------------------------- + ----------------------- -  +
    | mask_ssn('909-63-6922')| mask_ssn('abcdefghijk')|
    + ------------------------- + ----------------------- -  +
    | XXX-XX-6922 | XXX-XX-hijk |
    + ------------------------- + ----------------------- -  +
    MySQL的> SELECT mask_ssn('909');
    + ----------------- +
    | mask_ssn('909')|
    + ----------------- +
    | NULL |
    + ----------------- +
    
随机数据生成函数

本节中的函数为不同类型的数据生成随机值。 如果可能,生成的值具有为演示或测试值保留的特性,以避免将它们误认为是合法数据。 例如, gen_rnd_us_phone() 返回使用555区号的美国电话号码,该号码未分配给实际使用中的电话号码。 各个功能描述描述了该原则的任何例外。

  • gen_range(lower, upper)

    生成从指定范围中选择的随机数。

    参数:

    • lower :一个整数,指定范围的下边界。

    • upper :一个整数,指定范围的上边界,该边界不得小于下边界。

    返回值:

    一个随机整数,范围从 lower to upper ,包括,或者 NULL 如果 upper 参数小于 lower

    例:

    MySQL的> SELECT gen_range(100, 200), gen_range(-1000, -800);
    + --------------------- + ------------------------ +
    | gen_range(100,200)| gen_range(-1000,-800)|
    + --------------------- + ------------------------ +
    | 177 | -917 |
    + --------------------- + ------------------------ +
    MySQL的> SELECT gen_range(1, 0);
    + ----------------- +
    | gen_range(1,0)|
    + ----------------- +
    | NULL |
    + ----------------- +
    
  • gen_rnd_email()

    example.com 域中 生成随机电子邮件地址

    参数:

    没有。

    返回值:

    随机电子邮件地址作为字符串。

    例:

    MySQL的> SELECT gen_rnd_email();
    + --------------------------- +
    | gen_rnd_email()|
    + --------------------------- +
    | ijocv.mwvhhuf@example.com |
    + --------------------------- +
    
  • gen_rnd_pan([size])

    生成随机支付卡主帐号。 该数字通过Luhn检查(对校验位执行校验和验证的算法)。

    警告

    返回的值 gen_rnd_pan() 应仅用于测试目的,不适合发布。 无法保证给定的退货值未分配给合法的付款帐户。 如果有必要发布 gen_rnd_pan() 结果,请考虑使用 mask_pan() 屏蔽它 mask_pan_relaxed()

    参数:

    • size :(可选)一个整数,指定结果的大小。 如果 size 未给出, 则默认值为16 如果给定,则 size 必须是12到19之间的整数。

    返回值:

    随机支付号码作为字符串,或者 NULL 如果 size 给出超出允许范围 参数。

    例:

    MySQL的> SELECT mask_pan(gen_rnd_pan());
    + ------------------------- +
    | mask_pan(gen_rnd_pan())|
    + ------------------------- +
    | XXXXXXXXXXXX5805 |
    + ------------------------- +
    MySQL的> SELECT mask_pan(gen_rnd_pan(19));
    + --------------------------- +
    | mask_pan(gen_rnd_pan(19))|
    + --------------------------- +
    | XXXXXXXXXXXXXXX5067 |
    + --------------------------- +
    MySQL的> SELECT mask_pan_relaxed(gen_rnd_pan());
    + --------------------------------- +
    | mask_pan_relaxed(gen_rnd_pan())|
    + --------------------------------- +
    | 398403XXXXXX9547 |
    + --------------------------------- +
    MySQL的> SELECT mask_pan_relaxed(gen_rnd_pan(19));
    + ----------------------------------- +
    | mask_pan_relaxed(gen_rnd_pan(19))|
    + ----------------------------------- +
    | 578416XXXXXXXXX6509 |
    + ----------------------------------- +
    MySQL的> SELECT gen_rnd_pan(11), gen_rnd_pan(20);
    + ----------------- + ----------------- +
    | gen_rnd_pan(11)| gen_rnd_pan(20)|
    + ----------------- + ----------------- +
    | NULL | NULL |
    + ----------------- + ----------------- +
    
  • gen_rnd_ssn()

    格式 生成随机的美国社会安全号码 部分大于900和 AAA-BB-CCCC AAA BB 部分小于70,这些特征不用于合法的社会安全号码。

    参数:

    没有。

    返回值:

    随机社会安全号码作为字符串。

    例:

    MySQL的> SELECT gen_rnd_ssn();
    + --------------- +
    | gen_rnd_ssn()|
    + --------------- +
    | 951-26-0058 |
    + --------------- +
    
  • gen_rnd_us_phone()

    格式 生成随机的美国电话号码 555区号不用于合法的电话号码。 1-555-AAA-BBBB

    参数:

    没有。

    返回值:

    一个随机的美国电话号码作为字符串。

    例:

    MySQL的> SELECT gen_rnd_us_phone();
    + -------------------- +
    | gen_rnd_us_phone()|
    + -------------------- +
    | 1-555-682-5423 |
    + -------------------- +
    
基于随机数据字典的函数

本节中的函数处理术语的字典,并基于它们执行生成和屏蔽操作。 其中一些功能需要 SUPER 特权。

加载字典时,它将成为字典注册表的一部分,并为其他字典功能分配一个名称。 字典从纯文本文件加载,每行包含一个术语。 空行被忽略。 要有效,字典文件必须至少包含一个非空行。

  • gen_blacklist(str, dictionary_name, replacement_dictionary_name)

    用一个来自第二个字典的术语替换一个字典中存在的术语并返回替换术语。 这通过替换掩盖了原始术语。

    参数:

    • str :一个字符串,指示要替换的术语。

    • dictionary_name :一个字符串,用于命名包含要替换的术语的字典。

    • replacement_dictionary_name :一个字符串,用于命名要从中选择替换术语的字典。

    返回值:

    随机选择的字符串, replacement_dictionary_name 作为替换 字符串 str ,或者 str 如果它没有出现 dictionary_name ,或者 NULL 字典名称不在字典注册表中。

    如果要替换的术语出现在两个词典中,则返回值可能是相同的术语。

    例:

    MySQL的> SELECT gen_blacklist('Berlin', 'DE_Cities', 'US_Cities');
    + ------------------------------------------------- -  +
    | gen_blacklist('柏林','DE_Cities','US_Cities')|
    + ------------------------------------------------- -  +
    | 凤凰城|
    + ------------------------------------------------- -  +
    
  • gen_dictionary(dictionary_name)

    从字典中返回一个随机项。

    参数:

    • dictionary_name :一个字符串,用于命名从中选择术语的字典。

    返回值:

    从字典中作为字符串的随机术语,或者 NULL 字典名称不在字典注册表中。

    例:

    MySQL的> SELECT gen_dictionary('mydict');
    + -------------------------- +
    | gen_dictionary('mydict')|
    + -------------------------- +
    | 我的用语|
    + -------------------------- +
    MySQL的> SELECT gen_dictionary('no-such-dict');
    + -------------------------------- +
    | gen_dictionary('no-such-dict')|
    + -------------------------------- +
    | NULL |
    + -------------------------------- +
    
  • gen_dictionary_drop(dictionary_name)

    从字典注册表中删除字典。

    此功能需要该 SUPER 权限。

    参数:

    • dictionary_name :一个字符串,用于命名要从字典注册表中删除的字典。

    返回值:

    一个字符串,指示放置操作是否成功。 Dictionary removed 表示成功。 Dictionary removal error 表示失败。

    例:

    MySQL的> SELECT gen_dictionary_drop('mydict');
    + ------------------------------- +
    | gen_dictionary_drop('mydict')|
    + ------------------------------- +
    | 删除字典|
    + ------------------------------- +
    MySQL的> SELECT gen_dictionary_drop('no-such-dict');
    + ------------------------------- +
    | gen_dictionary_drop('no-such-dict')|
    + ------------------------------- +
    | 字典删除错误|
    + ------------------------------- +
    
  • gen_dictionary_load(dictionary_path, dictionary_name)

    将文件加载到字典注册表中,并为字典分配一个名称,以便与需要字典名称参数的其他函数一起使用。

    此功能需要该 SUPER 权限。

    重要

    字典不是持久的。 必须为每个服务器启动加载应用程序使用的任何字典。

    一旦加载到注册表中,即使基础字典文件发生更改,也会按原样使用字典。 要重新加载字典,首先将其删除 gen_dictionary_drop() ,然后再次加载 gen_dictionary_load()

    参数:

    • dictionary_path :一个字符串,指定字典文件的路径名。

    • dictionary_name :为字典提供名称的字符串。

    返回值:

    一个字符串,指示加载操作是否成功。 Dictionary load success 表示成功。 Dictionary load error 表示失败。 字典加载失败可能有多种原因,包括:

    • 已加载具有给定名称的字典。

    • 找不到字典文件。

    • 字典文件不包含任何术语。

    • secure_file_priv 系统变量设置和字典文件不位于由变量命名的目录。

    例:

    MySQL的> SELECT gen_dictionary_load('/usr/local/mysql/mysql-files/mydict','mydict');
    + ------------------------------------------------- -------------------- +
    | gen_dictionary_load('/ usr / local / mysql / mysql-files / mydict','mydict')|
    + ------------------------------------------------- -------------------- +
    | 字典加载成功|
    + ------------------------------------------------- -------------------- +
    MySQL的> SELECT gen_dictionary_load('/dev/null','null');
    + ----------------------------------------- +
    | gen_dictionary_load('/ dev / null','null')|
    + ----------------------------------------- +
    | 字典加载错误|
    + ----------------------------------------- +
    

6.5 FIPS支持

如果使用OpenSSL编译,MySQL支持FIPS模式,并且运行时可以使用OpenSSL库和FIPS对象模块。

服务器端的FIPS模式适用于服务器执行的加密操作。 这包括在服务器内运行的复制(主/从和组复制)和X插件。 FIPS模式也适用于客户端连接到服务器的尝试。

以下部分描述了FIPS模式以及如何在MySQL中利用它:

FIPS概述

联邦信息处理标准140-2(FIPS 140-2)描述了联邦(美国政府)机构可能需要的用于保护敏感或有价值信息的加密模块的安全标准。 要被视为联邦使用,加密模块必须经过FIPS 140-2认证。 如果用于保护敏感数据的系统缺少适当的FIPS 140-2证书,联邦机构则无法购买。

虽然OpenSSL库本身未针对FIPS进行验证,但OpenSSL等产品可用于FIPS模式。 相反,OpenSSL库与OpenSSL FIPS对象模块一起使用,以使基于OpenSSL的应用程序能够以FIPS模式运行。

有关FIPS及其在OpenSSL中的实现的一般信息,这些引用可能会有所帮助:

重要

FIPS模式对加密操作施加了条件,例如对可接受的加密算法的限制或对更长密钥长度的要求。 对于OpenSSL,确切的FIPS行为取决于OpenSSL版本。 有关详细信息,请参阅“OpenSSL FIPS用户指南”。

MySQL中FIPS模式的系统要求

要使MySQL支持FIPS模式,必须满足以下系统要求:

  • 在构建时,必须使用OpenSSL编译MySQL。 如果编译使用不同的SSL库,则不能在MySQL中使用FIPS模式。

  • 在运行时,OpenSSL库和OpenSSL FIPS对象模块必须可用作共享(动态链接)对象。 可以构建静态链接的OpenSSL对象,但MySQL不会使用它们。

FIPS模式已经在EL7上测试了MySQL,但可能适用于其他系统。

如果您的平台或操作系统提供OpenSSL FIPS对象模块,则可以使用它。 否则,您可以从源构建OpenSSL库和FIPS对象模块。 使用“OpenSSL FIPS用户指南”中的说明(请参阅 FIPS概述 )。

在MySQL中配置FIPS模式

MySQL可以在服务器端和客户端控制FIPS模式:

  • 所述 ssl_fips_mode 系统变量控制是否将服务器在FIPS模式操作。

  • --ssl-fips-mode 客户端选项控制一个给定的MySQL客户端是否在FIPS模式下运行。

ssl_fips_mode 系统变量和 --ssl-fips-mode 客户端选项允许这些值:

  • OFF :禁用FIPS模式。

  • ON :启用FIPS模式。

  • STRICT :启用 严格 FIPS模式。

在服务器端,数字 ssl_fips_mode 的值0,1和2是等同于 OFF ON ,和 STRICT ,respectivey。

重要

一般来说, STRICT 比限制更多的限制 ON ,但MySQL本身没有FIPS特定的代码,除了向OpenSSL指定FIPS模式值。 FIPS模式的确切行为 ON STRICT 依赖于OpenSSL的版本。 有关详细信息,请参阅OpenSSL FIPS用户指南(请参阅 FIPS概述 )。

注意

如果OpenSSL的FIPS对象模块不可用时,对于唯一的允许值 ssl_fips_mode --ssl-fips-mode OFF 尝试将FIPS模式设置为其他值时发生错误。

服务器端的FIPS模式适用于服务器执行的加密操作。 这包括在服务器内运行的复制(主/从和组复制)和X插件。

FIPS模式也适用于客户端连接到服务器的尝试。 在客户端或服务器端启用时,它会限制可以选择哪种受支持的加密密码。 但是,启用FIPS模式不要求必须使用加密连接,或者必须加密用户凭据。 例如,如果启用FIPS模式,则需要更强大的加密算法。 特别是,MD5受到限制,因此尝试使用加密密码建立加密连接,例如 RC4-MD5 不起作用。 但FIPS模式无法阻止建立未加密的连接。 (为此,您可以将该 REQUIRE 子句用于 CREATE USER ALTER USER 对于特定用户帐户,或将 require_secure_transport 系统变量 设置 为影响所有帐户。)

原文