分享到

引言

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

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

MySQL 如何配置认证和授权?

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

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

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

第一部分:认证

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

  • 您是否可以正确认证为所请求的用户账户
  • 该用户账户是否在系统中被锁定

如果您连接的用户未被锁定,并且您能够正确认证,MySQL 将接受连接并允许您继续访问控制系统的第二部分。如果用户被标记为锁定,如果您的认证尝试失败,或者如果您提供的用户无效,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 列包含用于检查用户密码的字符串。大多数情况下,这是密码的哈希版本。如果原生插件的 authentication_stringmysql.user 表中为空,则客户端不得指定密码才能成功认证。

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

account_locked

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

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

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

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

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

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

The User 字段由以下之一组成

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

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

如果您不注意上述排序顺序,这可能会产生一些令人惊讶的影响。例如,包含 Host 值但没有 User 的行总是优先于包含 User 值但没有 Host 的行被选中。理解这个排序系统将帮助您避免一整类认证问题。

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

此命令将打印出您当前认证的用户:

SELECT CURRENT_USER()

第二部分:授权

客户端凭据认证成功后,MySQL 建立连接并进入访问控制系统的第二部分以确定授权。MySQL 授权是一个持续进行的过程,它根据用户账户的特定权限检查每个命令。如果命令在用户权限范围内,则允许该操作。否则,服务器将拒绝该请求。

不同类型的权限

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

权限范围

权限可以在不同的范围级别进行分配,这决定了所授予权限的作用区域。某些权限仅在特定范围有效,而其他权限可以根据您希望启用的粒度在不同范围进行分配。

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

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

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

静态权限与动态权限

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

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

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

权限定义位置

MySQL 的权限在内部 mysql 系统数据库的许多不同表中定义。这些内部定义的权限组合将决定用户针对某个操作或数据库对象的特定权限。 mysql 数据库中的以下表涉及权限定义

  • user: 除了为认证定义用户账户外,user 表还定义了每个用户的静态全局权限。这些权限适用于整个 MySQL 服务器,不受任何插件或组件可用性的影响。
  • global_grants: global_grants 表定义了每个用户的动态全局权限。任何由插件或组件定义的权限都会注册到此表中。
  • db: db 表定义了数据库级别的权限。db 表与 user 表一样匹配用户的 UserHost 值,但它还有一个名为 Db 的列,用于定义该行的数据库范围。
  • tables_priv: tables_priv 表以类似于 db 表定义数据库权限的方式定义表级权限。为了启用表级范围,除了 UserHostDb 之外,还提供了一个名为 Table_name 的列。
  • columns_priv: columns_priv 表比 tables_priv 表更进一步,它决定了列级别的访问。为了增加这种额外的粒度,除了 tables_priv 表中可用的列之外,还包含了一个名为 Column_name 的列。
  • procs_priv: procs_priv 表定义了执行存储过程和函数的权限。它使用 UserHostDbRoutine_nameRoutine_type 列来限定用户对不同类型进程的权限范围。
  • proxies_priv: proxies_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 年以来一直撰写有关数据库、Linux、基础设施和开发者工具的文章。他目前与妻子和两只兔子住在柏林。他通常不需要以第三人称写作,这让所有相关方都松了一口气。
© . All rights reserved.