简介
认证和授权是管理和保护 MySQL 服务器的重要考虑因素。认证(有时缩写为“authn”)指验证客户端是否被允许以特定用户身份连接的策略和机制。 授权(有时缩写为“authz”)是在认证后发生的过程,用于确定账户被允许执行哪些操作。
在本指南中,我们将探讨 MySQL 提供的用于管理此访问控制系统的概念和组件。我们将讨论用户、角色、认证方法和权限之间的相互作用,这些共同解决了如何控制谁可以在 MySQL 数据库服务器上做什么的问题。
MySQL 如何配置认证和授权?
MySQL 通过许多不同的相关系统来管理其认证和授权需求。广义上讲,其组成部分是:
- 用户: 用户是在 MySQL 服务器上配置的独立账户,起到身份的作用。这些身份可以与认证方法结合,允许客户端以该用户身份连接,并可以被授予权限,以允许他们在不同粒度级别访问和控制不同的数据库对象。MySQL 中的用户由一个
User名和一个用户连接的Host组成。从不同的Host连接的相同User名被视为不同的用户。 - 认证方法: 认证方法是确定连接客户端是否应被允许使用特定用户账户的方式。这些方法通常涉及接受和验证客户端的密码,但也提供其他认证方法。
- 权限: 用户的能力和访问级别由直接授予他们、通过角色成员身份或通过对象所有权授予的权限定义。这些权限在各种范围内定义,并针对用户尝试的每个操作进行检查。
- 角色: 实际上,角色是可应用于用户的权限集。将相关的权限组添加到角色,然后通过角色成员身份分配这些权限可以简化权限管理。
实际的访问控制过程分为两个不同的部分。首先,客户端以特定用户身份向服务器进行认证。然后,每个操作都将对照用户的授权权限进行检查,以确定是允许还是拒绝每个请求。
第一部分:认证
MySQL 访问控制系统的第一阶段是认证连接。MySQL 根据以下因素决定是否接受连接请求:
- 您是否可以正确地以您请求的用户账户进行认证
- 该用户账户在系统中是否被锁定
如果您连接的用户未被锁定,并且您能够正确认证,MySQL 会接受连接并允许您进入访问控制系统的第二部分。如果用户被标记为锁定,如果您的认证尝试失败,或者如果您提供的用户无效,MySQL 将拒绝连接请求。
mysql.user 表中与认证相关的列
为了执行这些功能,MySQL 会查询其内部 mysql 数据库中 user 表内的以下列:
User
客户端连接时使用的用户名有助于 MySQL 确定如何认证用户。当与下面的 Host 字段结合时,它在 MySQL 中形成了一个完整、唯一的身份。
在 mysql.user 表中,一个空白的 User 值将匹配客户端提供的任何用户。但是,当这种情况发生时,客户端在该会话期间被视为匿名用户。这在访问控制的第二阶段有影响,服务器将针对匿名用户而不是客户端提供的用户检查操作。
Host
客户端连接的主机被认为是用户身份的关键部分。在 MySQL 中,唯一的身份由用户名和他们连接的主机的组合形成。
因此,来自 example.com 的 user1 被认为与来自 test.org 的 user1 不同。User 字段和 Host 字段一起告诉 MySQL 尝试认证哪个账户。
plugin
一旦 MySQL 使用 User 和 Host 确定要为连接请求检索的正确记录,它就使用 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 列的特异性对行进行排序。 Host 包含完整域名或 IP 地址的行被排在顶部,其次是 Host 字段中使用通配符的行(将仅包含 % — 匹配所有通配符 — 的行排在最后,作为最不具体的条目),最后是 Host 为空的行。
MySQL 将 User 列作为次要排序字段。这意味着如果两行具有相同的 Host 特异性,则具有更具体 User 条目的行将优先。 User 字段中不允许使用通配符。
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和Host值,就像user表一样,但还包含一个名为Db的列,用于定义行的数据库范围。tables_priv:tables_priv表以类似于db表对数据库的方式定义表级权限。为了启用表级范围,除了User、Host和Db之外,还提供了一个名为Table_name的列。columns_priv:比tables_priv表更进一步,columns_priv表确定列级别的访问权限。为了增加这种额外的粒度,除了tables_priv表中可用的列之外,还包含了一个名为Column_name的列。procs_priv:procs_priv表定义了执行存储过程和函数的权限。它使用User、Host、Db、Routine_name和Routine_type列来限定用户对不同类型过程的权限范围。proxies_priv:proxies_priv表定义了用户的代理权限。代理允许一个用户扮演另一个用户的角色,继承其权限。proxies_priv表使用User和Host列来匹配用户,然后使用单独的列Proxied_host和Proxied_user来定义匹配用户可以扮演谁的角色。
这些表的用户账户匹配功能与我们之前描述的 mysql.user 表如何读入内存并排序的方式类似。
要显示当前与用户关联的授权,您可以输入:
SHOW GRANTS FOR '<user>'@'<host>';
您还可以使用以下命令查看非权限账户属性:
SHOW CREATE USER '<user>'@'<host>';
角色
角色是相关组件,也适用于授权过程。角色是管理员可以创建的命名权限捆绑,以使权限管理更容易。一旦一组权限授予给一个角色,您就可以通过将用户添加为该角色的成员来授予他们这些权限。
因此,如果您想让多个用户能够在特定表中插入和更新值,您可以创建一个具有这些权限的角色。然后,您可以通过在该角色中添加或删除用户来控制谁可以插入和更新该表。这为不同类型的用户创建了特定的定义访问级别,并有助于确保访问级别在不同账户之间一致应用。
角色对它们所涉及的认证过程的复杂性影响最小。但是,我们在这里提及它们是因为它们作为管理权限的一种方式非常有用。
结论
认证和授权是 MySQL 安全方法的重要要求。它们共同作为系统的访问控制控制器,通过规范谁可以连接到服务器、他们可以查看和交互的结构以及他们可以访问的数据来发挥作用。了解这些系统如何交互可以帮助您配置安全策略,以保护您的数据,同时不阻碍所有合法操作。
