分享到

简介

身份验证和授权是管理和保护您的 MySQL 服务器的重要考虑因素。身份验证(有时缩写为“authn”)指的是验证客户端是否被允许以特定用户身份连接的策略和机制类别。授权(有时缩写为“authz”)是在身份验证之后发生的过程,用于确定帐户被允许执行哪些操作。

在本指南中,我们将了解 MySQL 提供的用于管理此访问控制系统的概念和组件。我们将讨论用户、角色、身份验证方法和权限之间的相互作用,它们共同解决了如何控制谁可以在 MySQL 数据库服务器上执行哪些操作的问题。

MySQL 如何配置身份验证和授权?

MySQL 通过许多不同的相关系统来管理其身份验证和授权要求。广义上讲,其组成部分是

  • 用户: 用户是在 MySQL 服务器上配置的充当身份的单个帐户。这些身份可以与身份验证方法结合使用,以允许客户端以用户身份连接,并且可以被授予权限,以允许他们访问和控制各种粒度级别的不同数据库对象。MySQL 中的用户由 User 名称和用户连接来源的 Host 组成。从不同 Host 连接的相同 User 名称被视为不同的用户。
  • 身份验证方法: 身份验证方法是确定是否应允许连接客户端使用特定用户帐户的方式。这些方法通常涉及接受和验证来自客户端的密码,但其他身份验证方法也可用。
  • 权限: 用户的能力和访问级别由直接授予他们的权限、通过角色成员资格或通过对象所有权授予的权限定义。这些权限在各种范围内定义,并针对用户尝试的每个操作进行检查。
  • 角色: 实际上,角色是可以应用于用户的权限集。将相关的权限组添加到角色,然后通过角色成员资格分配这些权限可以简化权限管理。

实际的访问控制过程分为两个不同的部分。首先,客户端以特定用户身份向服务器进行身份验证。之后,每个操作都会根据用户的授权权限进行检查,以确定是允许还是拒绝每个请求。

第 1 部分:身份验证

MySQL 访问控制系统中的第一阶段是验证连接。MySQL 根据以下因素决定是否接受连接请求

  • 您是否可以正确地以您请求的用户帐户进行身份验证
  • 该用户帐户是否在系统内被锁定

如果您连接的用户未被锁定,并且您能够正确地进行身份验证,则 MySQL 接受连接并允许您继续访问控制系统的第 2 部分。如果用户被标记为锁定,如果您的身份验证尝试失败,或者如果您提供的用户无效,MySQL 将拒绝连接请求。

为了执行这些功能,MySQL 查询其内部 mysql 数据库中 user 表内的以下列

User

客户端连接的用户名帮助 MySQL 确定如何验证用户身份。当与下面的 Host 字段结合使用时,它在 MySQL 中形成一个完整的、唯一的身份。

mysql.user 表中,空白 User 值将匹配客户端提供的任何用户。但是,当这种情况发生时,在会话期间,客户端被视为匿名用户。这在访问控制的第二阶段中具有影响,服务器将针对匿名用户而不是客户端提供的用户检查操作。

Host

客户端连接的主机被认为是用户身份的关键部分。在 MySQL 中,唯一身份由用户名和他们连接的主机组合而成。

因此,来自 example.comuser1 被认为与来自 test.orguser1 不同。User 字段和 Host 字段共同告诉 MySQL 要尝试验证哪个帐户。

plugin

一旦 MySQL 使用 UserHost 确定要检索的连接请求的正确记录,它将使用 plugin 字段来决定如何验证客户端的身份。

用户的 plugin 字段定义了应用于验证用户凭据的身份验证方法。默认插件 caching_sha2_password 将检查用户的密码是否与存储在表中的密码哈希版本匹配。

authentication_string

对于“原生”身份验证插件(那些仅使用 mysql.user 表中的信息验证用户的插件),authentication_string 列包含用于检查用户密码的字符串。大多数时候,这是一个密码的哈希版本。如果 mysql.user 表中原生插件的 authentication_string 为空,则客户端必须不指定密码才能成功进行身份验证。

对于使用外部系统进行身份验证的插件,authentication_string 通常用于指定外部系统正确验证用户身份所需的其他信息(如服务名称、其他识别信息等)。

account_locked

此列确定此特定用户帐户是否在系统内被锁定。帐户可以由数据库管理员手动锁定。帐户必须解锁才能继续。

确定 mysql.user 表中行的优先级

MySQL 使用上述五个字段来确定是否接受连接。但是,在某些情况下,多个条目可能与客户端的连接匹配。例如,客户端可能不提供主机,或者 mysql.user 表可能包含没有用户的行。MySQL 需要一种方法来建立这些行的优先级,以确定如何验证客户端的身份。

为此,MySQL 在服务器启动时或收到从磁盘重新加载其信息的信号时,将 mysql.user 表中的行读取到其内存中。当它读取行时,它还会按特异性对它们进行排序,以便表中的行从最具体到最不具体排序。

首先,MySQL 根据 Host 列的特异性对行进行排序。具有由完整域名或 IP 地址组成的 Host 的行排在最前面,其次是在 Host 字段中使用通配符的行(将包含 %(匹配所有内容的通配符)的行放在最后,作为最不具体的条目),最后是具有空白 Host 的行。

MySQL 使用 User 列作为辅助排序字段。这意味着,如果两行具有相同的 Host 特异性,则具有更具体的 User 条目的行将被优先考虑。通配符在 User 字段中是不允许的。

User 字段由以下内容组成:

  • 必须与提供的用户名完全匹配的字符串,
  • 空白字段,它将匹配客户端提供的任何用户名,但将以匿名用户身份继续会话

MySQL 将仅使用 mysql.user 表中的一行来验证客户端连接。这意味着,如果身份验证失败或匹配了错误的行,它将不会检查可能正确验证身份的其他替代方案。为了确定用于验证客户端连接请求的行,MySQL 从排序列表的顶部开始。它按顺序检查每一行,并使用找到的第一个与客户端连接匹配的行。

如果您不注意上面描述的排序顺序,这可能会产生一些令人惊讶的影响。例如,包含 Host 值但没有 User 的行将始终优先于具有 User 值但没有 Host 的行被选中。了解此排序系统将帮助您避免一整类身份验证问题。

如果您在以某个用户身份进行身份验证时遇到问题,请检查以查看是否没有更具体的条目与该用户匹配。如果您可以连接,但无法执行您认为应该能够执行的操作,请验证 MySQL 是否允许您以您请求的用户名而不是匿名用户身份访问,这可能会如上所述发生。

此命令将打印出您当前经过身份验证的用户:

SELECT CURRENT_USER()

第 2 部分:授权

一旦客户端的凭据通过身份验证,MySQL 就会建立连接,然后进入访问控制系统的第二部分,以确定授权。MySQL 授权是一个持续的过程,它针对用户帐户的特定权限检查每个命令。如果命令在用户权限范围内,则允许该操作。否则,服务器将拒绝该请求。

不同类型的权限

为了解释为什么某些权限存储在某些位置,有必要讨论 MySQL 中不同类型的权限。

权限范围

可以在不同的范围分配权限,这决定了授予权限的影响区域。某些权限仅在特定范围内有效,而其他权限可以在不同的范围内分配,具体取决于您希望启用的粒度。

全局权限是不绑定到特定数据库的权限。它们在整个 MySQL 服务器中都有效。许多全局权限与系统管理相关,并且与系统管理职责相关联,而不是直接与数据管理相关联。

数据库权限绑定到 MySQL 服务器中的特定数据库。在数据库范围授予的权限会影响用户可以对数据库以及其中包含的任何数据库对象(如表)执行的操作。数据库权限可以授予给特定数据库,也可以授予给一般数据库。

对象权限使您可以控制数据库中的表、索引等。这些权限可以授予给特定对象、特定数据库中某种类型的所有对象,或者可以授予给整个服务器中某种类型的所有对象。

静态权限 vs 动态权限

在内部,权限可以分为静态权限或动态权限。

静态权限内置于服务器中,无法取消注册(禁用)。无论服务器上启用了哪些组件,这些权限始终可用。一般来说,静态权限通常是基本权限(例如,读取或写入数据的能力),这些权限适用于所有或大多数系统。

另一方面,动态权限取决于定义它们的插件或组件的可用性。这些权限可以在运行时注册或取消注册,以影响其可用性。未注册的权限无法授予,但已授予的权限会在启动时自动注册。动态权限始终是全局范围的(适用于整个 MySQL 服务器)。

权限的定义位置

MySQL 的权限在内部 mysql 系统数据库中的许多不同表中定义。其中定义的权限组合将决定用户相对于操作或数据库对象的特定权限。mysql 数据库中的以下表参与定义权限

  • user:除了定义用于身份验证的用户帐户外,user 表还定义了每个用户的静态全局权限。这些权限适用于整个 MySQL 服务器,并且不受任何插件或组件的可用性的影响。
  • global_grantsglobal_grants 表定义了每个用户的动态全局权限。插件或组件定义的任何权限都将在此表中注册。
  • dbdb 表定义了数据库级别的权限。db 表匹配用户的 UserHost 值,就像 user 表一样,但还有一个名为 Db 的列,用于定义行的数据库范围。
  • tables_privtables_priv 表以类似于 db 表对数据库执行的方式定义表级别的权限。为了启用表级别的范围,除了 UserHostDb 之外,还有一个名为 Table_name 的列可用。
  • columns_priv:比 tables_priv 表更进一步,columns_priv 表确定了列级别的访问权限。为了增加这种额外的粒度,除了 tables_priv 表中可用的列之外,还包含一个名为 Column_name 的列。
  • procs_privprocs_priv 表定义了执行过程和函数的权限。它使用 UserHostDbRoutine_nameRoutine_type 列来限定用户对不同类型过程的权限范围。
  • proxies_privproxies_priv 表定义了用户的代理权限。代理允许一个用户充当另一个用户,继承他们的权限。proxies_priv 表使用 UserHost 列来匹配用户,然后使用单独的列 Proxied_hostProxied_user 来定义匹配的用户可以充当谁。

这些表的用户名匹配功能与我们之前描述的将 mysql.user 表读取到内存并排序的方式类似。

要显示当前与用户关联的授权,您可以键入

SHOW GRANTS FOR '<user>'@'<host>';

您还可以使用以下命令查看非权限帐户属性

SHOW CREATE USER '<user>'@'<host>';

角色

角色是相关的组件,也适合授权过程。角色是由管理员创建的命名权限包,以便更轻松地管理权限。一旦一组权限被授予给一个角色,您可以通过将用户添加为该角色的成员,将这些权限授予给用户。

因此,如果您想让多个用户能够在特定表中插入和更新值,您可以创建一个具有这些权限的角色。然后,您可以通过从该角色中添加或删除用户来控制谁可以在该表上插入和更新。这为不同类型的用户创建了特定的定义的访问级别,并有助于确保访问级别在帐户之间保持一致应用。

角色对它们参与的身份验证过程复杂性的影响很小。但是,我们在这里提到它们是因为它们作为一种管理权限的方式非常有用。

结论

身份验证和授权是 MySQL 安全方法的重要要求。它们共同充当系统的访问控制控制器,通过调节谁可以连接到服务器、他们可以看到和与之交互的结构以及他们可以访问的数据。了解这些系统如何交互可以帮助您配置安全策略,以保护您的数据,同时让所有合法操作畅通无阻。

关于作者
Justin Ellingwood

Justin Ellingwood

自 2013 年以来,Justin 一直在撰写关于数据库、Linux、基础设施和开发者工具的文章。他目前与妻子和两只兔子住在柏林。他通常不必以第三人称写作,这对所有相关方来说都是一种解脱。