目录
在考虑MySQL安装中的安全性时,您应该考虑各种可能的主题以及它们如何影响MySQL服务器和相关应用程序的安全性:
影响安全性的一般因素。 这些包括选择好的密码,不向用户授予不必要的权限,通过防止SQL注入和数据损坏来确保应用程序安全性等。 请参见 第6.1节“一般安全问题” 。
安装本身的安全性。 应保护数据文件,日志文件和安装的所有应用程序文件,以确保未经授权方无法读取或写入这些文件。 有关更多信息,请参见 第2.10节“安装后设置和测试” 。
数据库系统本身内的访问控制和安全性,包括允许访问数据库中使用的数据库,视图和存储程序的用户和数据库。 有关更多信息,请参见 第6.2节“访问控制和帐户管理” 。
安全相关插件提供的功能。 请参见 第6.4节“安全组件和插件” 。
MySQL和您的系统的网络安全性。 安全性与单个用户的授权有关,但您可能还希望限制MySQL,以便它仅在MySQL服务器主机上本地可用,或者在一组有限的其他主机上可用。
确保您有足够和适当的数据库文件,配置和日志文件备份。 还要确保您已准备好恢复解决方案,并测试您是否能够成功从备份中恢复信息。 请参见 第7章, 备份和恢复 。
本节介绍了要注意的一般安全问题,以及如何使MySQL安装更安全,防止攻击或滥用。 有关MySQL用于设置用户帐户和检查数据库访问权限的访问控制系统的信息,请参见 第2.10节“安装后设置和测试” 。
有关经常被问及有关MySQL服务器安全性问题的一些问题的答案,请参见 第A.9节“MySQL 8.0 FAQ:安全性” 。
在连接到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,并且应该在其他系统下进行小的修改。
如果您没有看到明文数据,这并不总是意味着信息实际上是加密的。 如果您需要高安全性,请咨询安全专家。
密码出现在MySQL中的几个上下文中。
以下各节提供了一些指导原则,使最终用户和管理员能够确保这些密码的安全并避免泄露这些密码。
此外,该
validate_password
插件可用于对可接受的密码实施策略。
请参见
第6.4.3节“密码验证组件”
。
MySQL用户应使用以下准则来保证密码安全。
当您运行客户端程序以连接到MySQL服务器时,不建议以将其公开给其他用户发现的方式指定您的密码。 此处列出了运行客户端程序时可用于指定密码的方法,以及每种方法的风险评估。 简而言之,最安全的方法是让客户端程序提示输入密码或在受适当保护的选项文件中指定密码。
使用
mysql_config_editor
实用程序,该实用程序使您可以将身份验证凭据存储在名为的加密登录路径文件中
.mylogin.cnf
。
MySQL客户端程序稍后可以读取该文件以获取用于连接到MySQL服务器的身份验证凭据。
请参见
第4.6.7节“
mysql_config_editor
- MySQL配置实用程序”
。
在命令行上
使用
或
选项。
例如:
-p
your_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
。
任何此类文件都应具有限制性访问模式。
数据库管理员应使用以下准则来确保密码安全。
MySQL在
mysql.user
系统表中
存储用户帐户的密码
。
永远不应该向任何非管理帐户授予对此表的访问权限。
帐户密码可以过期,以便用户必须重置它们。 请参见 第6.2.15节“密码管理” 和 第6.2.16节“过期密码的服务器处理” 。
该
validate_password
插件可用于对可接受的密码强制实施策略。
请参见
第6.4.3节“密码验证组件”
。
有权修改插件目录(
plugin_dir
系统变量
的值
)或
my.cnf
指定插件目录位置
的
文件的用户可以替换插件并修改插件提供的功能,包括身份验证插件。
应该保护可能写入密码的日志文件等文件。 请参见 第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
选项,请记住这也会绕过密码重写。
只有在需要纯文本密码时才会进行密码重写。 对于具有期望密码哈希值的语法的语句,不会发生重写。 如果为此类语法错误地提供了纯文本密码,则会将密码记录为给定,而不进行重写。
要保护日志文件免受不必要的暴露,请将它们放在限制访问服务器和数据库管理员的目录中。
如果服务器记录到
mysql
数据库中的表,则仅将这些表的访问权限授予数据库管理员。
复制从属服务器将复制主服务器的密码存储在主信息存储库中,默认情况下,该信息存储库是
mysql
名为数据库
的表
slave_master_info
。
现在不推荐在主数据存储库的数据目录中使用文件,但仍然可以使用(请参见
第17.2.4节“复制中继和状态日志”
)。
确保只能由数据库管理员访问主信息存储库。
将密码存储在主信息存储库中的替代方法是使用该
START
SLAVE
语句指定用于连接到主服务器的凭据。
使用受限访问模式来保护包含日志表或包含密码的日志文件的数据库备份。
连接到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
可以安全地
进行
写入
的目录
来防止
。
下表显示 了影响安全性的 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 | 是 | 全球 | 没有 |
在Windows上,您可以使用普通用户帐户将服务器作为Windows服务运行。
在Linux上,对于使用MySQL存储库或RPM软件包执行的安装,MySQL服务器
mysqld
应由本地
mysql
操作系统用户启动。
从另一个操作系统用户开始,作为MySQL存储库的一部分包含的init脚本不支持该用户。
在Unix(或用于使用
tar.gz
软件包
执行的安装的Linux
)上,MySQL服务器
mysqld
可以由任何用户启动和运行。
但是,
root
出于安全原因
,应避免以Unix
用户
身份运行服务器
。
要将
mysqld
更改
为以普通的非特权Unix用户身份运行
user_name
,您必须执行以下操作:
如果服务器正在运行,请停止服务器(使用 mysqladmin shutdown )。
更改数据库目录和文件,以便
user_name
具有读取和写入文件的权限(您可能需要以Unix
root
用户
身份执行此
操作):
外壳> chown -R user_name
/path/to/mysql/datadir
如果不这样做,服务器在运行时将无法访问数据库或表
user_name
。
如果MySQL数据目录中的目录或文件是符号链接,则
chown -R
可能不会跟随符号链接。
如果没有,您还需要关注这些链接并更改它们指向的目录和文件。
以用户身份启动服务器
user_name
。
另一种方法是启动
mysqld
作为Unix
root
用户并使用该
选项。
mysqld
启动,然后
在接受任何连接之前
切换为以Unix用户身份运行
。
--user=
user_name
user_name
要在系统启动时自动以给定用户身份启动服务器,请通过向
选项文件
组
或
服务器数据目录
中的
选项文件
添加
user
选项来
指定用户名
。
例如:
[mysqld]
/etc/my.cnf
my.cnf
的[mysqld]
用户=user_name
如果你的Unix机器本身不安全,你应该
root
在授权表中
为MySQL
帐户
分配密码
。
否则,在该计算机上具有登录帐户的任何用户都可以
使用
选项
运行
mysql
客户端
--user=root
并执行任何操作。
(在任何情况下,最好将密码分配给MySQL帐户,但在服务器主机上存在其他登录帐户时尤其如此。)请参见
第2.10.4节“保护初始MySQL帐户”
。
该
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命令
访问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
对象和占位符。
其他编程接口可能具有类似的功能。
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特权系统做:
您无法明确指定应拒绝给定用户访问。 也就是说,您无法明确匹配用户,然后拒绝连接。
您不能指定用户具有在数据库中创建或删除表的权限,但不能指定创建或删除数据库本身的权限。
密码全局适用于帐户。 您无法将密码与特定对象(如数据库,表或例程)相关联。
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_name
mysql -u finley -p
password
db_name
如果使用该
-p
选项,则
密码值和以下密码值
之间
必须
没有空格
-p
。
在命令行上指定密码应该被认为是不安全的。 请参见 第6.1.2.1节“密码安全的最终用户指南” 。 要避免在命令行上输入密码,请使用选项文件或登录路径文件。 请参见 第4.2.2.2节“使用选项文件” 和 第4.6.7节“ mysql_config_editor - MySQL配置实用程序” 。
有关指定用户名,密码和其他连接参数的其他信息,请参见 第4.2.3节“连接到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语句可能具有比此处指示的更具体的权限要求。 如果是,则有关语句的描述提供了详细信息。
这些权限说明符的简写
“
可在给定的权限级别的所有权限
”
(除
GRANT OPTION
)。
例如,
ALL
在全局或表级别授予分别授予所有全局特权或所有表级特权。
允许使用该
ALTER
TABLE
语句来更改表的结构。
ALTER
TABLE
还需要
CREATE
和
INSERT
特权。
重命名表需要
ALTER
和
DROP
对旧表,
CREATE
以及
INSERT
对新表。
允许使用更改或删除存储例程(存储过程和函数)的语句。
允许使用创建新数据库和表的语句。
允许使用该
CREATE
ROLE
语句。
(该
CREATE
USER
权限还允许使用该
CREATE
ROLE
语句。)请参见
第6.2.10节“使用角色”
。
在
CREATE ROLE
和
DROP ROLE
特权的不那么强大
CREATE USER
,因为它们只能用于创建和删除帐户。
它们不能用作
CREATE
USER
修改帐户属性或重命名帐户。
请参阅
用户和角色互换性
。
允许使用创建存储例程(存储过程和函数)的语句。
允许使用创建,更改或删除表空间和日志文件组的语句。
允许使用该
CREATE TEMPORARY TABLE
语句
创建临时表
。
会话创建临时表后,服务器不会对表执行进一步的权限检查。
所述创建会话可以在桌子上进行任何操作,例如
DROP
TABLE
,
INSERT
,
UPDATE
,或
SELECT
。
有关更多信息,请参见
第13.1.20.3节“CREATE TEMPORARY TABLE语法”
。
允许使用的
ALTER
USER
,
CREATE
ROLE
,
CREATE
USER
,
DROP
ROLE
,
DROP
USER
,
RENAME
USER
,和
REVOKE
ALL
PRIVILEGES
语句。
允许使用该
CREATE
VIEW
语句。
允许从数据库中的表中删除行。
允许使用删除(删除)现有数据库,表和视图的语句。
在分区表上
DROP
使用该
ALTER TABLE ... DROP PARTITION
语句
需要
该
特权
。
该
DROP
也需要特权
TRUNCATE
TABLE
。
允许使用该
DROP
ROLE
语句。
(该
CREATE USER
权限还允许使用该
DROP
ROLE
语句。)请参见
第6.2.10节“使用角色”
。
在
CREATE ROLE
和
DROP ROLE
特权的不那么强大
CREATE USER
,因为它们只能用于创建和删除帐户。
它们不能用作
CREATE
USER
修改帐户属性或重命名帐户。
请参阅
用户和角色互换性
。
允许使用为事件调度程序创建,更改,删除或显示事件的语句。
允许使用执行存储例程(存储过程和函数)的语句。
影响以下操作和服务器行为:
使用
LOAD
DATA
和
SELECT
...
INTO OUTFILE
语句和
LOAD_FILE()
函数
启用在服务器主机上读取和写入文件
。
拥有该
FILE
权限的
用户
可以读取服务器主机上的任何文件,该文件是世界可读的或MySQL服务器可读的。
(这意味着用户可以读取任何数据库目录中的任何文件,因为服务器可以访问任何这些文件。)
允许在MySQL服务器具有写访问权限的任何目录中创建新文件。 这包括服务器的数据目录,其中包含实现权限表的文件。
允许
对
语句
使用
DATA DIRECTORY
or
INDEX DIRECTORY
table选项
CREATE
TABLE
。
作为安全措施,服务器不会覆盖现有文件。
要限制可以读取和写入文件的位置,请将
secure_file_priv
系统变量设置为特定目录。
请参见
第5.1.8节“服务器系统变量”
。
允许您向其他用户授予或撤消您自己拥有的权限。
允许使用创建或删除(删除)索引的语句。
INDEX
适用于现有表格。
如果您拥有
CREATE
表
的
权限,则可以在
CREATE
TABLE
语句中
包含索引定义
。
允许将行插入数据库中的表。
INSERT
还需要对
ANALYZE
TABLE
,
OPTIMIZE
TABLE
和
REPAIR
TABLE
表维护语句。
允许使用显式
LOCK
TABLES
语句来锁定您具有该
SELECT
权限的表。
这包括使用写锁定,这可以防止其他会话读取锁定的表。
允许显示有关服务器内执行的线程的信息(即有关会话正在执行的语句的信息)。
该权限允许使用
SHOW PROCESSLIST
或
mysqladmin进程列表
来查看属于其他帐户的线程;
你总能看到自己的主题。
该
PROCESS
权限还可以使用
SHOW
ENGINE
。
允许一个用户模拟或被称为另一个用户。 请参见 第6.2.18节“代理用户” 。
创建外键约束需要
REFERENCES
父表
的
权限。
允许使用该
FLUSH
语句。
这也使
中mysqladmin
等效于命令
FLUSH
操作:
flush-hosts
,
flush-logs
,
flush-privileges
,
flush-status
,
flush-tables
,
flush-threads
,
refresh
,和
reload
。
该
reload
命令告诉服务器将授权表重新加载到内存中。
flush-privileges
是...的同义词
reload
。
该
refresh
命令将关闭并重新打开日志文件并刷新所有表。
其他
命令执行类似
但更具体的
功能
,并且在某些情况下可能是优选的。
例如,如果要仅刷新日志文件,
则是比较好的选择
。
flush-
xxx
refresh
flush-logs
refresh
该
RELOAD
权限还允许使用
RESET
MASTER
和
RESET
SLAVE
语句。
允许使用的
SHOW MASTER
STATUS
,
SHOW SLAVE
STATUS
和
SHOW BINARY
LOGS
语句。
将此权限授予从服务器用于连接到当前服务器作为其主服务器的帐户。
启用请求已作出对数据库的主服务器上的更新,使用的帐户
SHOW SLAVE HOSTS
,
SHOW RELAYLOG EVENTS
和
SHOW
BINLOG EVENTS
语句。
使用
mysqlbinlog
选项
--read-from-remote-server
(
-R
)和时,
也需要此权限
--read-from-remote-master
。
将此权限授予从服务器用于连接到当前服务器作为其主服务器的帐户。
允许从数据库中的表中选择行。
只有在实际访问表时,
SELECT
语句才需要该
SELECT
权限。
某些
SELECT
语句不访问表,并且可以在没有任何数据库许可的情况下执行。
例如,您可以使用
SELECT
简单的计算器来计算不引用表的表达式:
SELECT 1 + 1; SELECT PI()* 2;
SELECT
读取列值的其他语句也需要
该
特权。
例如,
SELECT
需要用于上的右侧引用列
col_name
=
expr
赋值
UPDATE
语句或用于在指定的列
WHERE
的条款
DELETE
或
UPDATE
语句。
通过发出
SHOW DATABASE
语句
使帐户能够查看数据库名称
。
没有此权限的帐户只能看到具有某些权限的数据库,如果使用该
--skip-show-database
选项
启动服务器,则根本无法使用该语句
。
因为任何静态全局特权被认为是所有数据库的特权,任何静态全局特权使用户能够看到所有的数据库名称
SHOW
DATABASES
或通过检查
SCHEMATA
表
INFORMATION_SCHEMA
,除了已经在通过局部撤销数据库级别被限制的数据库。
允许使用该
SHOW CREATE
VIEW
语句。
使用的视图也需要此权限
EXPLAIN
。
允许使用
SHUTDOWN
和
RESTART
语句,
mysqladmin shutdown
命令和
mysql_shutdown()
C API函数。
SUPER
是一种强大而深远的特权,不应轻视。
如果帐户只需要执行一部分
SUPER
操作,则可以通过授予一个或多个动态特权来实现所需的特权集,每个动态特权赋予更多有限的能力。
请参阅
动态权限说明
。
SUPER
已弃用,将在未来的MySQL版本中删除。
请参阅将
帐户从SUPER迁移到动态权限
。
SUPER
影响以下操作和服务器行为:
在运行时启用系统变量:
启用服务器的配置变化与全球系统变量
SET
GLOBAL
和
SET
PERSIST
。
相应的动态权限是
SYSTEM_VARIABLES_ADMIN
。
允许设置需要特殊权限的受限会话系统变量。
相应的动态权限是
SESSION_VARIABLES_ADMIN
。
另请参见 第5.1.9.1节“系统变量权限” 。
允许更改全局事务特征(请参见 第13.3.7节“SET TRANSACTION语法” )。
相应的动态权限是
SYSTEM_VARIABLES_ADMIN
。
使该帐户能够启动和停止复制,包括组复制。
对于组
REPLICATION_SLAVE_ADMIN
复制,
相应的动态权限
用于常规复制
GROUP_REPLICATION_ADMIN
。
允许使用
CHANGE
MASTER
TO
和
CHANGE REPLICATION
FILTER
语句。
相应的动态权限是
REPLICATION_SLAVE_ADMIN
。
通过
PURGE BINARY LOGS
和
BINLOG
语句
启用二进制日志控制
。
相应的动态权限是
BINLOG_ADMIN
。
允许在执行视图或存储程序时设置有效的授权ID。
具有此权限的用户可以在
DEFINER
视图或存储程序
的
属性中
指定任何帐户
。
相应的动态权限是
SET_USER_ID
。
允许使用的
CREATE
SERVER
,
ALTER
SERVER
和
DROP
SERVER
语句。
允许使用 mysqladmin debug 命令。
启用
InnoDB
加密密钥轮换。
相应的动态权限是
ENCRYPTION_KEY_ADMIN
。
允许执行版本标记用户定义的函数。
相应的动态权限是
VERSION_TOKEN_ADMIN
。
允许授予和撤消角色,使用
语句
的
WITH ADMIN OPTION
子句
GRANT
以及
函数
<graphml>
结果中的
非空
元素内容
ROLES_GRAPHML()
。
相应的动态权限是
ROLE_ADMIN
。
允许控制不允许非
SUPER
帐户的
客户端连接
:
允许使用
KILL
statement或
mysqladmin kill
命令来终止属于其他帐户的线程。
(帐户总是可以杀死自己的线程。)
客户端连接
init_connect
时
,服务器不执行
系统变量内容
SUPER
。
SUPER
即使
max_connections
达到系统变量
配置的连接限制
,服务器
也会
接受来自
客户端的
一个连接
。
处于脱机模式(已
offline_mode
启用)的服务器不会
SUPER
在下一个客户端请求时
终止
客户端连接,并接受来自
SUPER
客户端的
新连接
。
即使
read_only
启用
了
系统变量,
也可以执行更新
。
这适用于明确的表的更新,并使用账户管理语句如
GRANT
与
REVOKE
该更新的表隐。
前面的连接控制操作的相应动态特权是
CONNECTION_ADMIN
。
SUPER
如果启用了二进制日志记录,则
可能还需要
创建或更改存储函数
的
权限,如
第24.7节“存储程序二进制日志记录”中所述
。
启用触发器操作。 您必须拥有此表的权限才能创建,删除,执行或显示该表的触发器。
当触发器被激活(由谁拥有特权执行用户
INSERT
,
UPDATE
或
DELETE
与触发器关联的表的语句),触发器执行要求谁定义触发器的用户仍然有
TRIGGER
对表的特权。
允许在数据库中的表中更新行。
这个特权说明符代表
“
没有特权。
“
它在全局级别
GRANT
用于指定子句,例如
WITH GRANT OPTION
不在特权列表中命名特定帐户特权。
SHOW
GRANTS
显示
USAGE
以指示帐户在特权级别没有特权。
动态特权是在运行时定义的,与内置于服务器的静态特权形成对比。 以下列表描述了MySQL中可用的每个动态权限。
大多数动态权限在服务器启动时定义。 其他由特定服务器组件或插件定义,如权限说明中所示。 在这种情况下,除非启用了定义它的组件或插件,否则该特权不可用。
特定的SQL语句可能具有比此处指示的更具体的权限要求。 如果是,则有关语句的描述提供了详细信息。
APPLICATION_PASSWORD_ADMIN
(在MySQL 8.0.14中添加)
对于双密码功能,此权限允许使用
适用于您自己帐户
的
RETAIN CURRENT PASSWORD
和
DISCARD OLD PASSWORD
子句
ALTER
USER
以及
SET
PASSWORD
语句。
需要此权限才能操作您自己的二级密码,因为大多数用户只需要一个密码。
如果允许某个帐户操作所有帐户的辅助密码,则应授予其
CREATE USER
权限,而不是
APPLICATION_PASSWORD_ADMIN
。
有关使用双密码的更多信息,请参见 第6.2.15节“密码管理” 。
启用审核日志配置。
此权限由
audit_log
插件
定义
;
请参见
第6.4.5节“MySQL Enterprise Audit”
。
允许执行
LOCK INSTANCE
FOR BACKUP
语句并访问Performance Schema
log_status
表。
从早期版本执行就地升级到MySQL 8.0时,
该
BACKUP_ADMIN
权限会自动授予具有该
RELOAD
权限的
用户
。
通过
PURGE BINARY LOGS
和
BINLOG
语句
启用二进制日志控制
。
启用设置系统变量
binlog_encryption
,该
变量
可激活或取消激活二进制日志文件和中继日志文件的加密。
这种能力不是由提供
BINLOG_ADMIN
,
SYSTEM_VARIABLES_ADMIN
或
SESSION_VARIABLES_ADMIN
特权。
binlog_rotate_encryption_master_key_at_startup
重新启动服务器时自动旋转二进制日志主密钥
的相关系统变量
不需要此权限。
允许使用
KILL
statement或
mysqladmin kill
命令来终止属于其他帐户的线程。
(帐户总是可以杀死自己的线程。)
允许设置与客户端连接相关的系统变量,或绕过与客户端连接相关的限制。
CONNECTION_ADMIN
适用于这些系统变量的影响:
init_connect
:
客户端连接
init_connect
时
,服务器不执行
系统变量内容
CONNECTION_ADMIN
。
max_connections
:
CONNECTION_ADMIN
即使
max_connections
达到系统变量
配置的连接限制
,服务器
也会
接受来自
客户端的
一个连接
。
offline_mode
:处于脱机模式(已
offline_mode
启用)的服务器不会
CONNECTION_ADMIN
在下一个客户端请求时
终止
客户端连接,并接受来自
CONNECTION_ADMIN
客户端的
新连接
。
read_only
:即使
read_only
启用
了
系统变量,
也可以执行更新
。
这适用于明确的表的更新,并使用账户管理语句如
GRANT
与
REVOKE
该更新的表隐。
启用
InnoDB
加密密钥轮换。
允许用户管理任何用户的防火墙规则。
此权限由
MYSQL_FIREWALL
插件
定义
;
请参见
第6.4.7节“MySQL Enterprise Firewall”
。
使用户能够更新自己的防火墙规则。
此权限由
MYSQL_FIREWALL
插件
定义
;
请参见
第6.4.7节“MySQL Enterprise Firewall”
。
允许帐户使用
START GROUP
REPLICATION
和
STOP GROUP
REPLICATION
语句
启动和停止组复制
,更改
group_replication_consistency
系统变量
的全局设置
以及使用
group_replication_set_write_concurrency()
和
group_replication_set_communication_protocol()
UDF。
将此权限授予用于管理作为复制组成员的服务器的帐户。
对于也拥有的用户
SYSTEM_VARIABLES_ADMIN
,
PERSIST_RO_VARIABLES_ADMIN
可以使用
SET
PERSIST_ONLY
将全局系统变量持久保存到
mysqld-auto.cnf
数据目录中
的
选项文件。
此语句类似于
SET
PERSIST
但不修改运行时全局系统变量值。
这
SET
PERSIST_ONLY
适用于配置只能在服务器启动时设置的只读系统变量。
另请参见 第5.1.9.1节“系统变量权限” 。
允许帐户连接到主服务器,使用
START
SLAVE
和
STOP
SLAVE
语句
启动和停止复制
,并使用
CHANGE
MASTER TO
和
CHANGE
REPLICATION FILTER
语句。
将此权限授予从服务器用于连接到当前服务器作为其主服务器的帐户。
此权限不适用于组复制;
使用
GROUP_REPLICATION_ADMIN
了点。
启用资源组管理,包括创建,更改和删除资源组,以及将线程和语句分配给资源组。 具有此权限的用户可以执行与资源组相关的任何操作。
允许将线程和语句分配给资源组。
具有此权限的用户可以使用该
SET RESOURCE GROUP
语句和
RESOURCE_GROUP
优化程序提示。
允许授予和撤消角色,使用
语句
的
WITH ADMIN OPTION
子句
GRANT
以及
函数
<graphml>
结果中的
非空
元素内容
ROLES_GRAPHML()
。
需要设置
mandatory_roles
系统变量
的值
。
启用与仅允许管理连接的网络接口的连接(请参见 第8.12.4.1节“MySQL如何处理客户端连接” )。
SESSION_VARIABLES_ADMIN
(在MySQL 8.0.14中添加)
对于大多数系统变量,设置会话值不需要特殊权限,任何用户都可以使用它来影响当前会话。
对于某些系统变量,设置会话值可能会在当前会话之外产生影响,因此是受限制的操作。
对于这些,该
SESSION_VARIABLES_ADMIN
权限使用户能够设置会话值。
如果系统变量受限制并且需要特殊权限来设置会话值,则变量说明指示该限制。
实例包括
binlog_format
,
sql_log_bin
,和
sql_log_off
。
在添加MySQL 8.0.14之前,
SESSION_VARIABLES_ADMIN
只有具有
SYSTEM_VARIABLES_ADMIN
或
SUPER
特权的
用户才能设置受限制的会话系统变量
。
该
SESSION_VARIABLES_ADMIN
特权的一个子集
SYSTEM_VARIABLES_ADMIN
和
SUPER
特权。
具有这些特权之一的用户也被允许设置受限制的会话变量,并且有效地
SESSION_VARIABLES_ADMIN
暗示并且不需要
SESSION_VARIABLES_ADMIN
明确
授予
。
另请参见 第5.1.9.1节“系统变量权限” 。
允许在执行视图或存储程序时设置有效的授权ID。
具有此权限的用户可以在
DEFINER
视图或存储程序
的
属性中
指定任何帐户
。
SYSTEM_USER
(在MySQL 8.0.16中添加)
该
SYSTEM_USER
权限将系统用户与普通用户区分开来:
具有该
SYSTEM_USER
权限的用户是系统用户。
没有
SYSTEM_USER
权限的用户是普通用户。
该
SYSTEM_USER
权限对给定用户可以应用其他权限的帐户有影响,以及用户是否受到其他帐户的保护:
系统用户可以修改系统和常规帐户。
也就是说,拥有对常规帐户执行给定操作的适当权限的用户通过拥有
SYSTEM_USER
也可以对系统帐户执行操作来
启用
。
系统帐户只能由具有适当权限的系统用户修改,而不能由常规用户修改。
具有适当权限的常规用户可以修改常规帐户,但不能修改系统帐户。 具有适当权限的系统和常规用户都可以修改常规帐户。
有关更多信息,请参见 第6.2.11节“帐户类别” 。
通过
SYSTEM_USER
特权
提供给系统帐户的常规帐户的修改保护
不适用于具有
mysql
系统模式
特权的常规帐户,
因此可以直接修改该模式中的授权表。
要获得完全保护,请不要
mysql
向常规帐户
授予
架构权限。
请参阅
通过常规帐户保护系统帐户免受操纵
。
影响以下操作和服务器行为:
在运行时启用系统变量:
启用服务器的配置变化与全球系统变量
SET
GLOBAL
和
SET
PERSIST
。
SET
PERSIST_ONLY
如果用户也具有,则
允许将服务器配置更改为全局系统变量
PERSIST_RO_VARIABLES_ADMIN
。
允许设置需要特殊权限的受限会话系统变量。
实际上,
SYSTEM_VARIABLES_ADMIN
暗示
SESSION_VARIABLES_ADMIN
没有明确授予
SESSION_VARIABLES_ADMIN
。
另请参见 第5.1.9.1节“系统变量权限” 。
允许更改全局事务特征(请参见 第13.3.7节“SET TRANSACTION语法” )。
TABLE_ENCRYPTION_ADMIN
(在MySQL 8.0.16中添加)
启用后,允许用户覆盖默认加密设置
table_encryption_privilege_check
;
请参阅
为架构和常规表空间定义加密默认值
。
允许执行版本标记用户定义的函数。
此权限由
version_tokens
插件
定义
;
请参见
第5.6.6节“版本标记”
。
允许执行
XA
RECOVER
语句;
请参见
第13.3.8.1节“XA事务SQL语法”
。
在MySQL 8.0之前,任何用户都可以执行该
XA
RECOVER
语句来发现未完成的准备好的XA事务的XID值,这可能导致由启动它的用户以外的用户提交或回滚XA事务。
在MySQL 8.0中,
XA
RECOVER
只允许拥有该用户的用户使用
XA_RECOVER_ADMIN
特权,预计仅授予需要它的管理用户。
例如,如果XA应用程序的管理员崩溃并且有必要查找应用程序启动的未完成事务以便可以回滚它们,则可能就是这种情况。
此权限要求可防止用户发现除自己以外的未完成的准备XA事务的XID值。
它不会影响XA事务的正常提交或回滚,因为启动它的用户知道它的XID。
最好只向帐户授予它所需的权限。
在授予
FILE
和管理权限
时应特别小心
:
FILE
可以滥用MySQL服务器可以在服务器主机上读取的任何文件来读入数据库表。
这包括服务器数据目录中的所有世界可读文件和文件。
然后可以使用该表
SELECT
将其内容传输到客户端主机
来访问该表
。
GRANT OPTION
使用户能够将其权限授予其他用户。
具有不同权限和权限的两个用户
GRANT
OPTION
可以组合权限。
ALTER
可用于通过重命名表来破坏权限系统。
SHUTDOWN
可以滥用通过终止服务器完全拒绝向其他用户提供服务。
PROCESS
可用于查看当前正在执行的语句的纯文本,包括设置或更改密码的语句。
SUPER
可用于终止其他会话或更改服务器的运行方式。
为
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
给出选项)。
列出的动态权限分配
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提供的权限” 。
在MySQL 8.0中,许多以前需要该
SUPER
权限的操作也与更有限范围的动态权限相关联。
(有关这些权限的说明,请参见
第6.2.2节“MySQL提供的权限”
。)通过授予关联的动态权限而不是,可以允许每个此类操作进入帐户
SUPER
。
此更改通过使DBA能够避免
SUPER
更
准确地授予
和定制用户权限
来提高安全性
。
SUPER
现已弃用,将在未来版本的MySQL中删除。
SUPER
发生
删除
时,
SUPER
除非已授予
SUPER
的
帐户
迁移到适当的动态权限,
否则
以前需要的操作
将失败
。
使用以下说明完成该目标,以便在
SUPER
删除
之前准备好帐户
:
执行此查询以标识已授予的帐户
SUPER
:
从INFORMATION_SCHEMA.USER_PRIVILEGES中选择GRANTEE WHERE PRIVILEGE_TYPE ='超级';
对于前面的查询标识的每个帐户,确定它需要的操作
SUPER
。
然后授予与这些操作对应的动态权限,并撤消
SUPER
。
例如,如果
'u1'@'localhost'
需要
SUPER
二进制日志清除和系统变量修改,则这些语句会对帐户进行必要的更改:
GRANT BINLOG_ADMIN,SYSTEM_VARIABLES_ADMIN ON *。* TO'u1'@'localhost'; REVOKE SUPER ON *。* FROM'u1'@'localhost';
修改完所有适用的帐户后,
INFORMATION_SCHEMA
第一步中
的
查询应生成一个空结果集。
该
mysql
系统数据库包括包含关于用户帐户和他们持有的特权信息的几个授权表。
本节介绍这些表。
有关系统数据库中其他表的信息,请参见
第5.3节“mysql系统模式”
。
此处的讨论描述了授权表的基础结构以及服务器在与客户端交互时如何使用其内容。
但是,通常不直接修改授权表。
当您使用帐户管理语句(例如
CREATE
USER
,
GRANT
)和
REVOKE
设置帐户并控制每个帐户可用的权限
时,间接会发生修改
。
请参见
第13.7.1节“帐户管理语句”
。
当您使用此类语句执行帐户操作时,服务器会代表您修改授权表。
使用诸如
,或者
不鼓励的
语句直接修改授权表
INSERT
,
并且风险自负。
服务器可以自由忽略由于此类修改而变得格式错误的行。
UPDATE
DELETE
对于修改授权表的任何操作,服务器检查该表是否具有预期结构,否则生成错误。 要将表更新为预期结构,请执行MySQL升级过程。 请参见 第2.11节“升级MySQL” 。
这些
mysql
数据库表包含授权信息:
user
:用户帐户,静态全局权限和其他非特权列。
global_grants
:动态全局权限。
db
:数据库级权限。
tables_priv
:表级权限。
columns_priv
:列级权限。
procs_priv
:存储过程和功能权限。
proxies_priv
:代理用户权限。
default_roles
:默认用户角色。
role_edges
:角色子图的边缘。
password_history
:密码更改历史记录。
有关静态和动态全局权限之间差异的信息,请参阅 静态与动态权限 。)
在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'<>'';
在访问控制的第二阶段,服务器执行请求验证以确保每个客户端对其发出的每个请求具有足够的权限。
除了
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
表,该表具有下表中显示的列。
表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
表记录有关代理帐户的信息。
它有以下列:
对于能够将
PROXY
权限
授予
其他帐户的帐户,它必须在
proxies_priv
表中具有
With_grant
设置为1的行,
Proxied_host
并
Proxied_user
设置为指示可以为其授予权限的帐户。
例如,
'root'@'localhost'
在MySQL安装期间创建
的
帐户在
proxies_priv
表中
有一行,该行
允许
为所有用户和所有主机
授予
PROXY
权限
''@''
。
这样可以
root
设置代理用户,以及委托其他帐户设置代理用户的权限。
请参见
第6.2.18节“代理用户”
。
该
global_grants
表列出了当前对用户帐户的动态全局权限的分配。
该表包含以下列:
USER
,
HOST
:授予权限的帐户的用户名和主机名。
PRIV
:权限名称。
WITH_GRANT_OPTION
:帐户是否可以将权限授予其他帐户。
该
default_roles
表列出了默认用户角色。
它有以下列:
HOST
,
USER
:默认角色适用的帐户或角色。
DEFAULT_ROLE_HOST
,
DEFAULT_ROLE_USER
:默认角色。
该
role_edges
表列出了角色子图的边缘。
它有以下列:
FROM_HOST
,
FROM_USER
:被授予角色的帐户。
TO_HOST
,
TO_USER
:授予帐户的角色。
WITH_ADMIN_OPTION
:帐户是否可以通过使用授予角色和从其他帐户撤消角色
WITH ADMIN OPTION
。
该
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
表中
指定
。
它本身不是管理权限,但用户在服务器主机上读取或写入文件的能力与所访问的数据库无关。
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
使用单独的用户名和主机名部分列
将帐户名存储在
系统数据库的
授权表中
:
有关授权表的结构更多细节,请参见 第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_ip
&netmask
=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帐户名中使用相同格式的值。
MySQL角色名称指的是角色,它们被命名为特权集合。 有关角色使用示例,请参见 第6.2.10节“使用角色” 。
角色名的语法和语义相似的账户名( 第6.2.4节“指定帐户名” )。 角色名称在这些方面与帐户名称不同:
角色名称的用户部分不能为空。 因此,没有 “ 匿名角色 ” 类似于 “ 匿名用户 ” 的概念 。 ”
作为一个帐户名,省略了在主机部分角色名称结果主机部分
'%'
。
但是,与
'%'
在一个帐户名,主机部分
'%'
的角色名称没有通配符性能。
例如,对于一个名称
'me'@'%'
用作角色名,主机部分(
'%'
)仅仅是一个文字值;
它没有
“
任何主机
”
匹配属性。
角色名称的主机部分中的网络掩码表示法没有意义。
帐户名称允许
CURRENT_USER()
在多个上下文中。
角色名称不是。
mysql.user
系统表中
的一行
可以同时用作帐户和角色。
在这种情况下,任何特殊用户或主机名匹配属性都不适用于将该名称用作角色名称的上下文。
例如,您不能执行以下语句,期望它将使用具有用户部分
myrole
和任何主机名的
所有角色设置当前会话角色
:
SET ROLE'myrole'@'%';
相反,该语句将会话的活动角色设置为具有完全名称的角色
'myrole'@'%'
。
因此,通常仅使用用户名部分指定角色名称,并隐式使用主机名部分
'%'
。
'%'
如果您打算创建一个既可用作角色又可用作允许从给定主机连接的用户帐户的名称,则
指定具有非
主机部件
的角色
非常有用。
当您尝试连接到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
表格并手动对其进行排序,以查看第一次匹配的位置。
建立连接后,服务器进入访问控制的第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
表授予特定于数据库的权限。
此表的范围列中的值可以采用以下形式:
服务器将
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专门为相关数据库授予另一个。
在这种情况下,您具有执行请求所需的权限,但服务器无法单独使用全局或数据库权限。
它必须根据组合的权限做出访问控制决策。
要管理MySQL帐户,请使用用于此目的的SQL语句:
CREATE
USER
并
DROP
USER
创建和删除帐户。
SHOW
GRANTS
显示帐户权限分配。
帐户管理语句使服务器对基础授权表进行适当的修改,这将在 第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';
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帐户时出现的问题。
此帐户已锁定,因此无法用于客户端连接。
MySQL角色是一组命名的特权。 与用户帐户一样,角色可以拥有授予和撤消的权限。
可以为用户帐户授予角色,该角色向帐户授予与每个角色关联的权限。 这样可以为帐户分配权限集,并为授予个人权限提供了一种方便的替代方法,既可以概念化所需的权限分配,也可以实现它们。
以下列表总结了MySQL提供的角色管理功能:
CREATE
ROLE
并
DROP
ROLE
创建和删除角色。
SHOW
GRANTS
显示用户帐户和角色的权限和角色分配。
SET
DEFAULT ROLE
指定默认情况下哪些帐户角色处于活动状
SET ROLE
更改当前会话中的活动角色。
该
CURRENT_ROLE()
函数显示当前会话中的活动角色。
该
mandatory_roles
和
activate_all_roles_on_login
系统变量定义启用强制角色和授予的角色的自动激活,当用户登录到服务器。
有关各个角色操作语句(包括使用它们所需的权限)的描述,请参见
第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
在启动时为具有该
SYSTEM_USER
特权
的角色分配了一个角色
,则服务器会将消息写入错误日志并退出。
如果
mandatory_roles
在运行时为具有该
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
以激活所需的角色。
正如角色可以授予帐户一样,可以从帐户中撤消它们:
REVOKErole
FROMuser
;
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
ROLE
,并
DROP
ROLE
分别发言。
该
CREATE USER
权限允许使用的
ALTER
USER
,
CREATE
ROLE
,
CREATE
USER
,
DROP
ROLE
,
DROP
USER
,
RENAME
USER
,和
REVOKE
ALL
PRIVILEGES
语句。
因此,
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';
效果是将原始开发者帐户权限分配给新帐户。
从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
使用帐户管理语句(例如
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;
在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
在启动时
禁用
,服务器会记录错误消息并启用
partial_revokes
。
对于
partial_revokes
在运行时
禁用的尝试
,会发生错误并且
partial_revokes
值保持不变。
要
partial_revokes
在存在限制时
禁用
,必须首先删除限制:
确定哪些帐户有部分撤销:
SELECT User,Host,User_attributes - >>'$。Restrictions' FROM mysql.user WHERE User_attributes - >>'$。Restrictions'<>'';
对于每个此类帐户,请删除其权限限制。
假设上一步显示帐户
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
部分撤销全局特权的语句对发生复制的所有主机的影响不同,可能导致复制不一致或错误。
如果
没有
选项
启动
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
选项
启动服务器
,则它不会读取授权表或实现任何访问控制。
任何用户都可以连接并执行任何操作,
这是不安全的。
为了使服务器因此开始读取表并启用访问检查,请刷新权限。
连接到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 -uuser_name
-hhost_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。)
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 '
查询OK,0行受影响(0.01秒) MySQL的>password
';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
启用,则密码更改必须指定当前密码。
如果
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
如果帐户的密码更改可能但不需要指定当前密码,则是可选的。