MySQL 8|安全性详解

在前面的章节中,我们了解了 MySQL 8 的可伸缩性,以及如何解决在扩展 MySQL 8 时遇到的问题。除此之外,我们还学习了如何使 MySQL 8 高度可用。如今,安全对于任何应用程序都很重要,对吗?当我们谈到安全性时,它包括帐户管理、角色、权限等。考虑到这些方面,我们将在本章中涵盖所有这些主题。本章主要介绍 MySQL 8 数据库的安全性及其相关特性。本章涵盖以下主题:

“安全”一词不受特定主题的约束;它涵盖了与 MySQL 8 相关的广泛主题。在开始详细讨论之前,让我们先谈谈与安全性相关的一些要点:

  • 考虑数据库中的安全性,其中用户和它们与各种数据库对象相关的权限需要管理。
  • 用户的密码安全。
  • 安装过程中的安全配置,包括各种类型的文件,如日志文件、数据文件等。这些文件的读/写操作必须受到保护。
  • 要处理系统级故障场景,必须有备份和恢复计划。这包括所有必需的文件,如数据库文件、配置文件等。
  • 管理安装 MySQL 8 的系统的网络安全,该系统允许有限数量的主机进行连接。

现在,您的旅程从另一个重要且非常有趣的话题开始。我们开始吧。

在详细讨论复杂问题之前,您必须首先了解一些有助于防止误用或攻击的基本要点。

在 MySQL 8 中,用户执行的所有连接、查询和操作都基于访问控制列表ACL安全性。以下是一些与安全相关的一般准则:

  • 不允许除 root 帐户之外的任何用户访问user表。使用GRANTREVOKE语句管理用户权限。
  • 在通过 internet 进行数据传输的情况下,使用加密协议,如 SSH 或 SSL。MySQL 8 为此支持 SSL 连接。
  • 当客户端使用应用程序将数据输入 MySQL 时,请使用适当的防御编程技术。
  • 使用哈希函数将密码存储到 MySQL 8 数据库中;不要将纯文本存储为密码。与密码恢复相同的方式,将一些字符串视为盐,并使用 AutoT0-Th 值。
  • 使用正确的密码策略来保护它不被破坏。这意味着您的系统应该只接受那些遵循您的规则/约定的密码。
  • 使用防火墙可将故障概率降低 50%,并为您的系统提供更多保护。在非军事区域下或防火墙后定义 MySQL,以保护不受信任的主机。
  • 基于 Linux 的系统提供tcpdump命令,以更安全的方式执行传输任务。此命令在网络层工作以提供安全性。例如,使用以下命令,可以检查 MySQL 数据流是否加密:
        shell> tcpdump -l -i eth0 -w - src or dst port 3306 | strings

在本节中,我们将介绍保护不同用户密码的指导原则,并介绍如何在日志记录过程中管理密码。MySQL 8 提供了validate_password插件来定义可接受密码的策略。

本节介绍以最安全的方式作为最终用户定义密码的各种方法。它解释了如何使您的密码更安全。最安全的方法是在受保护的选项文件中定义密码,或在客户端程序中提示输入密码。请参阅以下定义密码的不同方法:

  • 使用带有以下选项的命令行提供密码:
 cmd>mysql -u root --password=your_pwd
 --OR
 cmd> 
  • 在前面的两个命令中,您必须在命令行本身中指定密码,这是不可取的。MySQL 8 提供了另一种安全的方式来连接命令行。执行以下命令,它将提示您输入密码。输入密码后,MySQL 会为每个密码字符显示星号(*):
 cmd>mysql -u root -p
 Enter password: *********

这是一种比前两种更安全的方法,即在命令行参数中定义密码:

  • 使用MYSQL_PWD环境变量定义密码。与其他方法相比,此方法是不安全的,因为其他用户可能可以访问环境变量。
  • 使用mysql_config_editor工具定义密码,这是一个提供的选项,用于将密码存储到名为named.mylogin.cnf的加密登录路径文件中。MySQL 8 稍后将使用此文件连接 MySQL 服务器。
  • 使用选项文件存储密码。在文件中定义凭据时,请确保任何其他用户都无法访问此文件。例如,在基于 UNIX 的系统中,您可以在客户端部分下的选项文件中定义密码,如下所示:
 [client]
 password=your_pass

要使文件安全或对其设置访问模式,请执行以下命令:

shell> chmod 600 .my.cnf

对于数据库管理员,应遵循以下准则来保护密码:

  • 使用validate_password对接受的密码应用策略
  • MySQL 8 使用mysql.user表来存储用户密码,因此在配置系统时,只有管理用户才能访问此表
  • 如果密码过期,应允许用户重置帐户密码
  • 如果日志文件包含密码,则对其应用保护
  • 管理对插件目录和my.cnf文件的访问,因为它可以修改插件提供的功能

MySQL 8 允许您在 SQL 语句中以明文形式编写密码,如CREATE USERSET PASSWORDGRANT。如果我们执行这些语句,MySQL 8 将在日志文件中以文本形式写入密码,所有访问日志文件的用户都可以看到这些密码。要解决此问题,请避免使用上述 SQL 语句直接更新 grant 表。

为了保护 MySQL 8 免受攻击者攻击,请强烈考虑以下几点:

  • 为所有 MySQL 帐户设置密码。永远不要定义没有密码的帐户,因为这允许任何用户访问您的帐户。
  • 要与 MySQL 8 建立连接,请使用安全协议/通道,如压缩协议、MySQL 8 内部 SSL 连接或 SSH 进行加密 TCP/IP 连接。
  • 对于基于 Unix 的系统,在用于运行mysqld的 Unix 帐户的数据目录上设置读/写权限。不要使用 root 用户启动 MySQL 8 服务器。
  • 使用secure_file_priv变量指定读写权限的目录。使用此变量,可以限制非管理用户访问重要目录。使用此变量设置对plugin_dir的权限;这是非常重要的。同样,不要向所有用户提供FILE权限,因为它允许用户在系统中的任何位置写入文件。
  • 使用max_user_connections变量限制每个帐户的连接数。
  • 在创建授权表项时,请正确使用通配符。最好使用 IP 而不是 DNS。
  • 在存储程序和视图创建过程中遵循安全准则。

为了安全起见,MySQL 8 提供了以下mysqld选项和变量:

| 名称 | 命令行 | 选项文件 | 系统变量 | 状态变量 | 风险值范围 | 动态 | | allow-suspicious-udfs | 对 | 对 |   |   |   |   | | automatic_sp_privileges |   |   | 对 |   | 全球的 | 对 | | chroot | 对 | 对 |   |   |   |   | | des-key-file | 对 | 对 |   |   |   |   | | local_infile |   |   | 对 |   | 全球的 | 对 | | old_passwords |   |   | 对 |   | 二者都 | 对 | | safe-user-create | 对 | 对 |   |   |   |   | | secure-auth | 对 | 对 |   |   | 全球的 | 对 | | - Variable: secure_auth |   |   | 对 |   | 全球的 | 对 | | secure-file-priv | 对 | 对 |   |   | 全球的 | 不 | | - Variable: secure_file_priv |   |   | 对 |   | 全球的 | 不 | | skip-grant-tables | 对 | 对 |   |   |   |   | | skip-name-resolve | 对 | 对 |   |   | 全球的 | 不 | | - Variable: skip_name_resolve |   |   | 对 |   | 全球的 | 不 | | skip-networking | 对 | 对 |   |   | 全球的 | 不 | | - Variable: skip_networking |   |   | 对 |   | 全球的 | 不 | | skip-show-database | 对 | 对 |   |   | 全球的 | 不 | | - Variable: skip_show_database |   |   | 对 |   | 全球的 | 不 |

Reference: https://dev.mysql.com/doc/refman/8.0/en/security-options.html

不要信任应用程序用户输入的任何数据,因为用户可能已经为 MySQL 数据库输入了一个dropdelete语句。因此,始终存在安全漏洞和数据丢失的风险。作为 MySQL 数据库的管理员,应遵循以下检查表:

  • 在将数据传递到 MySQL 8 之前,必须检查数据的大小。
  • 要使 MySQL 8 更具限制性,请启用严格的 MySQL 模式。
  • 对于数字字段,输入字符、特殊字符和空格,而不是数字本身。在将字段值发送到 MySQL 8 服务器之前,应用程序会将字段值更改为其原始形式。
  • 使用两个不同的用户进行数据库的应用程序连接和数据库管理。
  • 在动态 URL 和 web 表单的情况下,通过添加引号将数据类型从数字类型修改为字符类型。还可以在动态 URL 中添加%22(“)、%23(#)和%27(')。

所有编程接口都内置了以前定义的功能。例如,Java JDBC 提供了带有占位符的准备语句,Ruby DBI 提供了quote()方法。

特权主要用于对用户进行身份验证,并将验证用户凭据,检查是否允许用户执行请求的操作。当我们连接 MySQL 8 服务器时,它将首先通过提供的主机和用户名检查用户的身份。连接后,当请求传入时,系统将根据用户的身份授予特权。基于这种理解,我们可以说,当我们尝试使用客户端程序连接 MySQL 8 服务器时,访问控制包含两个阶段:

  • 第一阶段:MySQL 服务器将根据提供的身份接受或拒绝连接
  • 第二阶段:从 MySQL 服务器获得连接后,当用户发送执行任何操作的请求时,服务器会检查用户是否有足够的权限

MySQL 8 特权系统有一些限制:

  • 不允许用户在特定对象(如表或例程)上设置密码。MySQL 8 允许在帐户级别进行全局访问。
  • 作为管理员用户,我们不能以允许创建/删除表的方式指定权限,但不允许创建/删除该表的数据库。

不允许显式限制用户访问,这意味着不可能显式匹配用户并拒绝其连接。MySQL 8 管理内存中 grant 表的内容,因此在INSERTUPDATEDELETE语句的情况下,grant 表的执行需要服务器重启才能生效。为了避免服务器重启,MySQL 提供了刷新权限的命令。我们可以用三种不同的方式执行此命令:

  1. 通过发布FLUSH PRIVILEGES
  2. 使用mysqladmin reload
  3. 使用mysqladmin flush-privileges

当我们重新加载 grant 表时,它将按照以下几点工作:

  • 表和列权限:这些权限的更改将在下一个客户端请求时可用
  • 数据库权限:这些权限的更改将在客户端下次执行USE dbname语句时可用
  • 全局权限和密码:对于连接的客户端,这些权限的更改不受影响;它将适用于后续连接

权限定义允许用户帐户执行的操作。根据操作级别和应用它的上下文,它将起作用。主要分类如下:

  • 数据库权限:应用于数据库,以及数据库中的所有对象。可以将其授予单个数据库,也可以全局定义以应用于所有数据库。
  • 管理权限:在全局级别定义,不局限于单个数据库。它使用户能够管理 MySQL 8 服务器的操作。
  • 数据库对象权限:用于定义对数据库对象的权限,如表、视图、索引、存储例程等。它可以应用于数据库的特定对象,可以应用于数据库中给定类型的所有对象,也可以全局应用于所有数据库中给定类型的所有对象。

MySQL 8 将在服务器启动时将帐户特权相关信息存储到 grant 表中,并将这些表的内容存储到内存中,以获得更好的性能。特权进一步分为静态和动态特权:

  • 静态权限:这些权限是服务器内置的,不能注销。这些权限始终可供要授予的用户使用。
  • 动态权限:这些权限可以在运行时注册或注销。如果未注册特权,则无法为用户帐户授予特权。

授权表包含与用户帐户相关的信息以及为该用户授予的权限。当我们在数据库中执行任何账户管理语句时,MySQL 8 会自动将数据插入这些表中,如CREATE USERGRANTREVOKE。MySQL 允许向管理员用户授予表上的 insert、update 或 delete 选项,但这不是更好的方法。MySQL 8 数据库的下表包含授权信息:

  • user:包含用户账号、全局权限等非权限列的详细信息
  • password_history:包含密码变更的历史记录
  • columns_priv:包含列级权限
  • procs_priv:包含与存储过程和函数相关的权限
  • proxies_priv:包含代理用户的权限
  • tables_priv:包含表级权限
  • global_grants:包含动态全局权限分配的详细信息
  • role_edges:包含角色子图的边
  • db:包含数据库级权限
  • default_roles:包含默认用户角色的详细信息

授权表包含范围和权限列:

  • 范围列:此列定义表中行的范围,表示该行应用的上下文。
  • 权限栏:此栏表示允许用户进行的操作。MySQL 服务器将来自各种授权表的信息结合起来,以构建用户权限的完整细节。

从 MySQL 8.0 开始,grant 表通过管理事务状态使用InnoDB存储引擎,但在此之前,MySQL 通过管理非事务状态使用MyISAM引擎。此更改使用户能够在事务模式下管理所有帐户管理语句,因此在多个语句的情况下,要么全部成功执行,要么全部不执行。

MySQL 8 在两个不同的阶段执行访问控制检查。

这是连接验证阶段,因此在验证之后,MySQL 8 将接受或拒绝您的连接请求。验证将在以下条件下进行:

  1. 基于用户的身份及其密码。
  2. 用户的帐户是否已锁定。

如果其中一种情况失败,服务器将拒绝访问。在这里,标识包含请求来自的用户名和主机名。MySQL 对用户表的account_locked列进行锁定检查,对用户表作用域的HostUserauthentication_string三列进行凭证检查。

一旦与 MySQL 服务器建立了连接,第 2 阶段就进入了画面,MySQL 服务器将检查您要执行的操作以及您是否允许执行该操作。对于这个验证,MySQL 使用 grant 表的特权列;它可能来自userdbtables_privcolumns_privprocs_priv表。

顾名思义,本主题介绍如何在 MySQL 8 中管理用户帐户。我们将介绍如何添加新帐户,如何删除帐户,如何定义帐户的用户名和密码,等等。

MySQL 8 提供了两种不同的创建帐户的方法:

  • 使用账户管理对账单:这些对账单用于创建用户并设置其权限;例如,CREATE USERGRANT语句通知服务器对授权表进行修改

  • 使用格兰特表操作:使用INSERTUPDATEDELETE语句,我们可以操作格兰特表

在这两种方法中,帐户管理报表更可取,因为它们更简洁,更不容易出错。现在,让我们看一个使用命令的示例:

#1 mysql> CREATE USER 'user1'@'localhost' IDENTIFIED BY 'user1_password';
#2 mysql> GRANT ALL PRIVILEGES ON *.* TO 'user1'@'localhost' WITH GRANT OPTION;

#3 mysql> CREATE USER 'user2'@'%' IDENTIFIED BY 'user2_password';
#4 mysql> GRANT ALL PRIVILEGES ON *.* TO 'user2'@'%' WITH GRANT OPTION;

#5 mysql> CREATE USER 'adminuser'@'localhost' IDENTIFIED BY 'password';
#6 mysql> GRANT RELOAD,PROCESS ON *.* TO 'adminuser'@'localhost';

#7 mysql> CREATE USER 'tempuser'@'localhost';

#8 mysql> CREATE USER 'user4'@'host4.mycompany.com' IDENTIFIED BY 'password';
#9 mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP ON db1.* TO 'user4'@'host4\. mycompany.com';

上述命令执行以下操作:

  • #1命令创建'user1'命令#2'user1'分配完全权限。但'user1'@'localhost'表示只允许'user1'localhost连接。
  • #3命令创建'user2',命令#4'user2'分配完全权限,与'user1'相同。但在#4 中提到了'user2'@'%',表示允许'user2'与任何主机连接。
  • #5创建'adminuser'只允许与localhost连接。在#6中,我们可以看到'adminuser'只提供RELOADPROCESS特权。它允许'adminuser'执行mysqladmin reloadmysqladmin refreshmysqladmin flush-xxxmysqladmin processlist命令,但对任何数据库都没有访问权限。
  • #7创建无密码的'tempuser'账号,只允许用户连接localhost。但没有为'tempuser'指定授权,因此该用户无法访问数据库,也无法执行任何管理命令
  • #8创建'user4'并允许用户仅使用'host4'访问数据库。#10表示'user4'已在'db1'上授予所有提及的操作。

要删除用户帐户,请执行以下DROP USER命令:

mysql> DROP USER 'user1'@'localhost';

此命令将从系统中删除'user1'帐户。

与拥有特权的用户帐户角色相同,我们也可以说角色是特权的集合。作为管理员用户,我们可以授予和撤销角色的权限。MySQL 8 提供了以下与角色配置相关的命令、函数和变量。

SET ROLE更改当前会话中的活动角色。参考以下与SET ROLE相关的命令:

mysql> SET ROLE NONE; SELECT CURRENT_ROLE();
+----------------+
| CURRENT_ROLE() |
+----------------+
| NONE |
+----------------+
mysql> SET ROLE 'developer_read'; SELECT CURRENT_ROLE();
+----------------+
| CURRENT_ROLE() |
+----------------+
| `developer_read`@`%` |
+----------------+

第一个命令将停用当前会话中用户的所有角色。您可以通过CURRENT_ROLE();功能看到效果。在第二个命令中,我们将'developer_read'角色设置为默认角色,然后再次使用预定义函数检查当前角色。

CREATE ROLE用于创建角色;请参阅以下命令,该命令将创建一个名为'developer_role'的角色:

CREATE ROLE 'developer_role';

DROP ROLE用于删除角色。请参阅以下命令,该命令将删除'developer_role'角色:

DROP ROLE 'developer_role';

GRANT为角色分配权限,为账户分配角色。例如,以下命令将所有权限分配给开发人员角色:

GRANT ALL ON my_db.* TO 'developer_role';

同样,要向用户帐户分配角色,请执行以下命令:

GRANT 'developer_role' TO 'developer1'@'localhost';

此命令将'developer_role'角色分配给developer1帐户。MySQL 8 还提供了一个功能,可以将GRANT从用户分配到用户,从角色分配到角色。考虑下面的例子:

CREATE USER 'user1';
CREATE ROLE 'role1';
GRANT SELECT ON mydb.* TO 'user1';
GRANT SELECT ON mydb.* TO 'role1';
CREATE USER 'user2';
CREATE ROLE 'role2';
GRANT 'user1', 'role1'TO 'user2';
GRANT 'user1', 'role1'TO 'role2';

在本例中,创建了user1role1,并使用GRANT命令以简单的方式将GRANT应用于它们。现在,对于user2role2,我们分别应用了user1role1中的GRANT

REVOKE用于从角色中删除权限,并从用户帐户中删除角色分配。请参阅以下命令:

REVOKE developer_role FROM user1;
REVOKE INSERT, UPDATE ON app_db.* FROM 'role1';

第一个命令用于删除user1'developer_role',第二个命令用于删除'app_db''role1'的插入和更新权限。

SET DEFAULT ROLE指示当用户登录默认角色时,默认情况下哪些角色处于活动状态。要设置默认根目录,请执行以下命令:

mysql>SET DEFAULT ROLE app_developer TO root@localhost;

mysql> SELECT CURRENT_ROLE();
+---------------------+
| CURRENT_ROLE() |
+---------------------+
| `app_developer`@`%` |
+---------------------+
1 row in set (0.04 sec)

设置默认角色后,重启服务器,执行current_role()功能检查是否分配了角色。

SHOW GRANTS列出与帐户和角色相关的权限和角色分配。对于角色,执行以下命令:

mysql> show grants for app_developer;
+-------------------------------------------+
| Grants for app_developer@% |
+-------------------------------------------+
| GRANT USAGE ON *.* TO `app_developer`@`%` |
+-------------------------------------------+
1 row in set (0.05 sec)

此命令显示'app_developer'角色上可用的授权。同样,要检查用户的授权,请执行以下命令:

mysql> show grants for root@localhost;

前面的命令列出了用户根目录下可用的所有访问权限:

  • CURRENT_ROLE ():此功能用于列出当前会话中的当前角色。如默认角色命令中所述,它显示用户当前分配的角色。
  • activate_all_roles_on_login:这是一个系统变量,用于在用户登录时自动激活所有授予的角色。默认情况下,禁用角色的自动激活。
  • mandatory_roles:系统变量,用于定义强制角色。记住,不能使用drop命令删除定义为强制的角色。在服务器文件my.cnf中定义您的强制角色,如下所示:
 [mysqld]
 mandatory_roles='app_developer'

要在运行时持久化和设置这些角色,请使用以下语句:

SET PERSIST mandatory_roles = 'app_developer';

此语句将更改应用于正在运行的 MySQL 8 实例,并将其保存以供后续重新启动。如果要对正在运行的实例应用更改,而不是对其他重新启动应用更改,请使用关键字GLOBAL而不是PERSIST

MySQL 8 提供以下与密码管理相关的功能:

  • 密码到期:用于定义密码到期的期限,以便用户可以定期更改。MySQL 8 允许为帐户手动设置密码过期,以及过期策略。对于过期策略,可以使用mysql_native_passwordsha256_passwordcaching_sha2_password插件。要手动设置密码,请执行以下命令:
 ALTER USER 'testuser'@'localhost' PASSWORD EXPIRE;

这将为提到的用户将密码标记为过期。对于密码策略,必须根据天数定义持续时间。MySQL 使用系统变量default_password_lifetime,它包含一个正整数来定义天数。我们可以在my.cnf文件中定义,也可以在运行时使用PERSIST选项定义:

  • 密码重复使用限制:用于防止再次使用旧密码。MySQL 8 基于两个参数定义此限制-更改的数量和经过的时间;它们可以单独使用,也可以组合使用。MySQL 8 分别定义password_historypassword_reuse_interval系统变量以应用限制。我们可以在my.cnf文件中定义这些变量,也可以将它们持久化。
  • password_history:此变量表示不能在旧密码的基础上设置/复制新密码。这里,根据指定的数字考虑最近的旧密码。
  • password_reuse_interval:此变量表示不能从旧密码设置/复制密码。在这里,interval 定义了特定的时间段,MySQL 8 将检查新密码以及用户在该时间段内的所有密码。例如,如果间隔设置为 20 天,则新密码在最近 20 天的更改数据中不应存在。
  • 密码强度评估:用于定义强密码。它是使用validate_password插件实现的。

当需要通过网络传输数据时,必须对连接使用加密。如果您使用的是未加密的数据,那么有权访问网络的人可以轻松地监视您的所有流量,并可以查看在客户端和服务器之间传输的数据。要通过网络保护数据,请使用加密。确保使用的加密算法包含安全元素,以保护您的连接免受已知攻击,如更改消息顺序或对数据重播两次。根据您的应用程序要求,您可以选择加密或未加密类型的连接。MySQL 8 使用传输层安全TLS协议)对每个连接执行加密。

本节介绍如何为加密连接配置服务器和客户端。

在服务器端,MySQL 8 使用–ssl选项指定与加密相关的属性。服务器端使用以下选项来配置加密:

  • --ssl-ca:此选项指定证书颁发机构CA)证书文件的路径名
  • --ssl-cert:此选项指定服务器公钥证书文件的路径名
  • --ssl-key:此选项指定服务器私钥文件的路径名

您可以在my.cnf文件中指定上述选项,如下所示:

[mysqld]
ssl-ca=ca.pem
ssl-cert=server-cert.pem
ssl-key=server-key.pem

--ssl选项默认启用,所以在服务器启动时,MySQL 8 会尝试在数据目录下查找证书和密钥文件,即使您在my.cnf文件中没有定义它。如果找到了这些文件,那么 MySQL 8 将提供加密连接,或者在没有加密连接的情况下继续。

在客户端,MySQL 使用与服务器端相同的–ssl选项来指定证书和密钥文件,但除此之外,它还有–ssl-mode选项。默认情况下,如果服务器允许,客户端可以与服务器建立加密连接。为了进一步控制,客户端程序使用以下–ssl-mode选项:

  • --ssl-mode=REQUIRED:此选项表示必须建立加密连接,未建立则失败
  • --ssl-mode=PREFFERED:此选项表示客户端程序可以在服务器允许的情况下建立加密连接,或者不失败地建立未加密连接
  • --ssl-mode=DISABLED:此选项表示客户端程序无法使用加密连接,只允许使用未加密连接
  • --ssl-mode=VERIFY_CA:此选项与REQUIRED相同,但除此之外,它还根据配置的 CA 证书验证 CA 证书,如果未找到匹配项,则返回失败
  • --ssl-mode=VERIFY_IDENTITY:与VERIFY_CA选项相同,但除此之外,还将执行主机名标识

以下选项在 MySQL 8 中可用于加密连接。您可以在命令行上使用这些选项,也可以在选项文件中定义它们:

| 格式 | 说明 | | --skip-ssl | 不要使用加密连接 | | --ssl | 启用加密连接 | | --ssl-ca | 包含受信任 SSL 证书颁发机构列表的文件 | | --ssl-capath | 包含受信任的 SSL 证书颁发机构证书文件的目录 | | --ssl-cert | 包含 X509 证书的文件 | | --ssl-cipher | 连接加密允许使用的密码列表 | | --ssl-crl | 包含证书吊销列表的文件 | | --ssl-crlpath | 包含证书吊销列表文件的目录 | | --ssl-key | 包含 X509 密钥的文件 | | --ssl-mode | 与服务器的连接的安全状态 | | --tls-version | 允许用于加密连接的协议 |

Reference: https://dev.mysql.com/doc/refman/8.0/en/encrypted-connection-options.html

要从 Microsoft Windows 系统使用 SSH 远程连接 MYSQL 8,请执行以下步骤:

  1. 在本地系统上安装 SSH 客户端。

  2. 启动 SSH 客户端后,设置要用于连接服务器的主机名和用户 ID。

  3. 按如下方式配置端口转发并保存信息:

    • 远程转发配置local_port:3306remote_host:mysqlservername_or_ipremote_port:3306
    • 本地转发配置local_port:3306remote_host:localhostremote_port:3306
  4. 使用创建的 SSH 会话登录到服务器。

  5. 在本地 Microsoft Windows 计算机中,启动任何 ODBC 应用程序,如 Microsoft Access。

  6. 在本地系统中,创建新文件并尝试使用 ODBC 驱动程序与 MySQL 服务器链接。确保您在连接中定义了localhost,而不是mysqlservername

MySQL 8 提供了几个插件来实现安全性。这些插件提供与身份验证协议、密码验证、安全存储等相关的各种功能。让我们详细讨论各种类型的插件。

下面列出了身份验证插件及其详细信息:

  • 本机可插拔认证:为了实现本机认证,MySQL 8 使用mysql_native_password插件。这个插件在服务器端和客户端都使用了一个通用名称,MySQL 8 为服务器和客户端程序提供了内置名称。

  • SHA-256 可插拔身份验证

为了实现 SHA-256 哈希,MySQL 8 提供了两种不同的插件:

  1. sha256_password:此插件用于实现基本的 SHA-256 认证。
  2. caching_sha2_password:该插件实现了 SHA-256 认证和缓存,性能更好,与基本插件相比,该插件还增加了一些功能。

此插件内置于 MySQL 8 服务器和与sha256_password同名的客户端程序中。在客户端,它位于libmysqlclient库下。要将此插件用于帐户,请执行以下命令:

CREATE USER 'testsha256user'@'localhost'
IDENTIFIED WITH sha256_password BY 'userpassword';

SHA-2 可插拔认证与 SHA-256 可插拔插件相同,只是其插件名称为caching_sha2_passwordsha256_password相比,该插件具有以下优势:

  1. 如果您使用的是 Unix 套接字文件和共享内存协议,则会为客户端连接提供支持。
  2. 内存缓存在 SHA-2 插件中可用,这为以前连接过的用户提供了更快的重新身份验证。
  3. 这个插件提供了基于 RSA 的密码交换,无论 MySQL 8 提供的 SSL 库如何,它都可以工作。

此插件用于向服务器发送密码,无需哈希或加密。在客户端提供,名称为mysql_clear_password。MySQL 8 在客户端库中内置了它。

这是一个服务器端插件,用于防止所有客户端连接到使用它的任何帐户。插件名为'mysql_no_login',不是内置的 MySQL 插件,所以必须使用mysql_no_login.so库。要使其可用,请首先将库文件放在插件目录下,然后执行以下任一步骤:

  1. 通过在my.cnf文件中添加--plugin-load-add参数,在服务器启动时加载插件:
 [mysqld]
 plugin-load-add=mysql_no_login.so
  1. 要在运行时注册插件,请执行以下命令:
 INSTALL PLUGIN mysql_no_login SONAME 'mysql_no_login.so';

要卸载此插件,请执行以下命令:

**1. 如果插件是使用--plugin-load-adoption在服务器启动时安装的,则通过删除该选项重新启动服务器。 2. 如果插件是使用INSTALL PLUGIN命令安装的,则使用卸载命令将其删除:

UNINSTALL PLUGIN mysql_no_login;

名为auth_socket的服务器端插件用于验证使用 Unix 套接字文件从本地主机连接的客户端。仅用于支持SO_PEERCRED选项的系统。SO_PEERCRED用于获取用户运行客户端程序的信息。这不是一个内置插件;我们必须使用带有此插件的auth_socket.so库。要使其可用,请首先将库文件放在插件目录下,然后执行以下任一步骤:

  1. 通过在my.cnf文件中添加--plugin-load-add参数,在服务器启动时加载插件:
 [mysqld]
 plugin-load-add=auth_socket.so
  1. 通过执行以下命令在运行时注册插件:
 INSTALL PLUGIN auth_socket SONAME 'auth_socket.so';

要卸载此插件,请执行以下命令:

**1. 如果插件是在服务器启动时使用--plugin-load-addoption安装的,则通过删除该选项重新启动服务器。 2. 如果插件是使用INSTALL PLUGIN命令安装的,则使用UNINSTALL命令将其删除:

 UNINSTALL PLUGIN auth_socket;

MySQL 8 提供了一个测试插件,用于检查帐户凭据并在服务器日志上记录成功或失败。它不是内置插件,需要在使用前安装。这对服务器端和客户端都可用,分别命名为test_plugin_serverauth_test_plugin。MySQL 8 使用auth_test_plugin.so库来实现此插件。要安装和卸载此插件,请执行前面插件中提到的相同步骤。

MySQL 8 使用这些插件在特定次数的连接尝试失败后,在服务器对客户端的响应中引入越来越大的延迟。MySQL 提供了两个用于连接控制的插件。

此插件将检查所有传入的连接请求,并在此基础上,根据需要在服务器响应中添加延迟。该插件使用一些系统变量进行配置,使用状态变量进行监控。它还使用一些其他插件、事件类和进程,如审计插件、MYSQL_AUDIT_CONNECTION_CLASSMASK事件类、MYSQL_AUDIT_CONNECTION_CONNECTMYSQL_AUDIT_CONNECTION_CHANGE_USER进程来检查服务器是否应该在参与任何客户端连接之前添加延迟:

**```sql CONNECTION_CONTROL_FAILED_LOGIN_ATTEMPTS


这个插件实现了使用`INFORMATION_SCHEMA`表来提供监控失败连接的详细信息。

# 插件安装

我们必须使用这个插件的`connection_control.so`库。要使其可用,请先将库文件放在插件目录下,然后执行以下任一步骤:

1.  通过在`my.cnf`文件中添加`--plugin-load-add`**参数,在服务器启动时加载插件:**

 **```sql
 [mysqld]
 plugin-load-add= connection_control.so
  1. 通过执行以下命令在运行时注册插件:
 INSTALL PLUGIN CONNECTION_CONTROL SONAME 
          'connection_control.so';
 INSTALL PLUGIN CONNECTION_CONTROL_FAILED_LOGIN_ATTEMPTS SONAME 
          'connection_control.so';

以下变量由CONNECTION-CONTROL插件提供:

  • Connection_control_delay_generated:状态变量,主要用于管理计数器。它指示服务器在连接尝试失败时在响应中添加延迟的次数。它还取决于connection_control_failed_connections_threshold系统变量,因为此状态变量不会增加计数,除非尝试次数达到阈值变量定义的限制。
  • connection_control_failed_connections_threshold:这是一个系统变量,表示在服务器每次尝试添加延迟之前,允许客户端连续尝试失败的次数。
  • 这是一个系统变量,它定义了服务器连接响应失败的毫秒级最大延迟时间。当 MySQL 8 包含一个高于零的值时,MySQL 席将考虑这个变量。
  • connection_control_min_connection_delay:此系统变量定义服务器尝试连接失败的最小延迟时间(毫秒)。一旦阈值变量包含高于零的值,MySQL 8 将考虑此变量。

对于密码验证,MySQL 提供了一个名为validate_password的插件。它主要用于测试密码和提高安全性。以下是该插件的两个主要功能:

  • VALIDATE_PASSWORD_STRENGTH():用于查找密码强度的 SQL 函数。它将密码作为参数,并返回一个介于 0 和 100 之间的整数值。这里,0 表示弱密码,100 表示强密码。

  • 根据 SQL 语句中的策略检查密码:对于所有使用密码作为明文值的 SQL 语句,插件将根据密码的策略检查提供的密码,并在此基础上返回响应。如果密码弱,插件将返回一个ER_NOT_VALID_PASSWORD错误。如果密码在参数中定义为明文,则此插件始终会检查ALTER USERCREATE USERGRANTSET PASSWORD语句和PASSWORD()函数。

我们必须使用这个插件的validate_password.so库。要使其可用,请首先将库文件放在插件目录下,然后执行以下任一步骤:

  1. 通过在my.cnf文件中添加--plugin-load-add参数,在服务器启动时加载插件:

**```sql [mysqld] plugin-load-add=validate_password.so


2.  通过执行以下命令在运行时注册插件:

```sql
 INSTALL PLUGIN validate_password SONAME 'validate_password.so';

MySQL 8 提供以下与密码验证插件相关的系统变量、状态变量和选项。

  • validate_password_check_user_name:系统变量,MySQL 8 默认启用。顾名思义,它用于将密码与当前有效用户的用户名进行比较。如果密码与用户名匹配或与用户名相反,MySQL 8 将拒绝该密码,而不考虑VALIDATE_PASSWORD_STRENGTH()函数值。
  • validate_password_dictionary_file:此系统变量包含validate_password插件使用的目录的路径名。您可以在运行时进行设置,无需重新启动服务器,插件安装后即可使用。如果您定义了密码检查目录,请将密码策略值设置为 2(strong)。密码策略的可能值在validate_password_policy系统变量下描述
  • validate_password_length:此系统变量在插件安装后可用,用于定义密码的最小字符数,以便与validate_password插件进行检查。
  • validate_password_mixed_case_count:此系统变量在插件安装后可用,用于定义密码检查的最小大小写字符数。
  • validate_password_number_count:此系统变量在插件安装后可用,用于定义密码检查的最小位数。
  • validate_password_special_char_count:此系统变量在插件安装后可用,用于定义密码检查中非字母数字字符的最小数量。
  • validate_password_policy:此系统变量在插件安装后可用,表示插件在其他系统变量情况下的行为。此变量的以下值描述了validate_password插件的行为:

| 政策 | 进行的试验 | | 0 或低 | 长 | | 1 或中等 | 长数字、小写/大写和特殊字符 | | 2 或更高 | 长数字、小写/大写和特殊字符;字典文件 |

Reference:https://dev.mysql.com/doc/refman/8.0/en/validate-password-options-variables.html

  • validate_password_dictionary_file_last_parsed:这是一个状态变量,用于指示上次解析目录文件的时间。
  • validate_password_dictionary_file_words_count:这是一个状态变量,用于指示从目录文件读取的字数。
  • --validate-password[=value]:此选项用于定义服务器在启动时如何加载validate_password插件。此选项仅在插件注册为INSTALL PLUGIN或加载了--plugin-load-add功能时可用。

MySQL 8 提供了一个 keyring 服务,它允许 MySQL 服务器的内部组件和插件存储它们的敏感信息以供以后使用。对于这个特性,MySQL 8 使用keyring_file插件,它将数据存储到服务器主机上的文件中。该插件在 MySQL 的所有发行版中都可用,例如社区版和企业版。

我们必须使用这个插件的keyring_file.so库。要使其可用,请首先将库文件放在插件目录下,然后执行以下任一步骤:

  • 通过在my.cnf文件中添加--plugin-load-add参数,在服务器启动时加载插件:
 mysqld]
 plugin-load-add=keyring_file.so
  • 通过执行以下命令在运行时注册插件:
 INSTALL PLUGIN keyring_file SONAME 'keyring_file.so';

MySQL 8 提供以下与 keyring 插件相关的系统变量:

  • keyring_file_data:此系统变量在插件安装后可用,用于定义keyring_file插件用于存储安全数据的数据文件的路径名。Keyring 操作是事务性的,所以这个插件在写操作期间使用一个备份文件来处理回滚场景。在这种情况下,反作用也使用与keyring_file_data系统变量中定义的相同命名约定命名,后缀为.backup

在本章中,我们从安全概述开始,然后从 MySQL 8 安全相关特性开始。首先,我们讨论了一些常见的安全问题,然后介绍了如何在 MySQL 8 中分配权限和管理访问控制。本章还介绍了加密,以保护您的敏感数据。最后,我们介绍了一些重要的安全插件,它们对于在 MySQL 8 中实现安全性非常有用。

现在是进入下一章的时候了,在这里我们将配置 MySQL 8 进行优化。对于优化,我们将涵盖数据库的不同领域,例如优化查询、优化表、优化缓冲和缓存等。除了服务器配置之外,它还介绍了如何配置客户端进行优化。**

教程来源于Github,感谢apachecn大佬的无私奉献,致敬!

技术教程推荐

AI技术内参 -〔洪亮劼〕

如何设计一个秒杀系统 -〔许令波〕

Linux实战技能100讲 -〔尹会生〕

网络编程实战 -〔盛延敏〕

移动端自动化测试实战 -〔思寒〕

Linux内核技术实战课 -〔邵亚方〕

代码之丑 -〔郑晔〕

零基础入门Spark -〔吴磊〕

反爬虫兵法演绎20讲 -〔DS Hunter〕