代理用户
MySQL服务器使用身份验证插件对客户端连接进行身份验证。验证给定连接的插件可以请求出于特权检查目的将连接(外部)用户视为其他用户。这使外部用户可以成为第二个用户的代理。也就是说,要承担第二个用户的特权:
- 外部用户是“代理用户”(可以模拟或成为其他用户的用户)。
- 第二用户是“代理用户”(其身份和特权可以由代理用户承担的用户)。
本节介绍代理用户功能的工作方式。有关身份验证插件的一般信息,有关特定插件的信息,请参见“编写身份验证插件”。有关编写支持代理用户的身份验证插件的信息,请参见“在身份验证插件中实现代理用户支持”。
- 代理用户支持的要求
- 简单代理用户示例
- 防止直接登录到代理帐户
- 授予和撤销代理权限
- 默认代理用户
- 默认代理用户和匿名用户冲突
- 服务器对代理用户映射的支持
- 代理用户系统变量
注意通过代理获得的管理优势是,DBA可以使用一组特权来设置一个帐户,然后使多个代理用户拥有这些特权,而不必分别为每个用户分配特权。作为代理用户的替代,DBA可能会发现角色提供了一种合适的方式来将用户映射到特定的一组命名特权上。可以给每个用户一个给定的单一角色,实际上是被授予适当的特权集。请参见“授权控制”。
代理用户支持的要求
为了使给定的身份验证插件进行代理,必须满足以下条件:
- 必须由插件本身或代表该插件的MySQL服务器支持代理。在后一种情况下,可能需要显式启用服务器支持。请参阅服务器支持代理用户映射。
- 必须将外部代理用户的帐户设置为由插件进行身份验证。使用该
CREATE USER
语句将帐户与身份验证插件相关联,或ALTER USER
更改其插件。 - 代理用户的帐户必须存在,并被授予代理用户要承担的特权。为此使用
CREATE USER
ndGRANT
语句。 - 通常,已配置代理用户,使其只能在代理场景中使用,而不能用于直接登录。
- 代理用户帐户必须具有
PROXY
代理帐户的特权。GRANT
为此使用语句。 为了使连接到代理帐户的客户端被视为代理用户,身份验证插件必须返回与客户端用户名不同的用户名,以指示定义了代理所享有的特权的代理帐户的用户名。用户。
替代地,对于由服务器提供代理映射的插件,根据代理用户所拥有的
PROXY
特权来确定代理用户。
代理机制仅允许将外部客户端用户名映射到代理用户名。没有映射主机名的规定:
- 当客户端连接到服务器时,服务器将根据客户端程序传递的用户名和客户端连接的主机来确定适当的帐户。
- 如果该帐户是代理帐户,则服务器尝试使用身份验证插件返回的用户名和代理帐户的主机名,找到与代理帐户匹配的项,从而确定适当的代理帐户。代理帐户中的主机名将被忽略。
简单代理用户示例
请考虑以下帐户定义:
-- create proxy accountCREATE USER 'employee_ext'@'localhost'IDENTIFIED WITH my_auth_pluginAS 'my_auth_string'; -- create proxied account and grant its privileges; -- use mysql_no_login plugin to prevent direct loginCREATE USER 'employee'@'localhost'IDENTIFIED WITH mysql_no_login;GRANT ALL ON employees.*TO 'employee'@'localhost'; -- grant to proxy account the -- PROXY privilege for proxied accountGRANT PROXY ON 'employee'@'localhost'TO 'employee_ext'@'localhost';
当客户端employee_ext
从本地主机连接时,MySQL使用名为的插件my_auth_plugin
执行身份验证。假设根据的内容并通过咨询某些外部身份验证系统,my_auth_plugin
将用户名返回employee
给服务器。名称与有所不同,因此返回请求服务器,将出于特权检查目的将外部用户视为本地用户。'my_auth_string'
employee
employee_ext
employee
employee_ext
employee
在这种情况下,employee_ext
是代理用户,employee
是代理用户。
服务器通过检查(代理用户)是否具有(代理用户)的特权来验证employee
该employee_ext
用户是否可以进行代理身份验证。如果尚未授予此特权,则会发生错误。否则,将承担的特权。服务器根据授予的特权检查在客户端会话期间执行的语句。在这种情况下,可以访问数据库中的表。employee_ext
PROXY
employee
employee_ext
employee
employee_ext
employee
employee_ext
employees
代理帐户,employee
使用mysql_no_login
身份验证插件来防止客户端使用该帐户直接登录。(这假定已安装了插件。有关说明,请参见“无登录可插入身份验证”。)有关防止代理帐户直接使用的替代方法,请参见防止直接登录代理帐户。
发生代理时,可以使用USER()
和CURRENT_USER()
功能来参见连接用户(代理用户)和在当前会话期间具有特权的帐户(代理用户)之间的区别。对于上述示例,这些函数返回以下值:
mysql>SELECT USER(), CURRENT_USER(); +------------------------ +-------------------- + | USER() | CURRENT_USER() | +------------------------ +-------------------- + | employee_ext@localhost | employee@localhost | +------------------------ +-------------------- +
在CREATE USER
创建代理用户帐户的IDENTIFIED WITH
语句中,可选的命名支持代理的身份验证插件的子句后面是指定用户连接时服务器传递给插件的字符串的子句。字符串(如果存在)提供的信息可帮助插件确定如何将代理(外部)客户端用户名映射到代理用户名。是否需要子句取决于每个插件。如果是这样,身份验证字符串的格式取决于插件打算如何使用它。有关给定插件接受的身份验证字符串值的信息,请查阅文档。AS ' uth_string'
AS
防止直接登录到代理帐户
代理帐户通常仅旨在通过代理帐户使用。也就是说,客户端使用代理帐户进行连接,然后被映射到适当的代理用户并享有相应的代理用户的特权。
有多种方法可以确保不能直接使用代理帐户:
- 将帐户与
mysql_no_login
身份验证插件关联。在这种情况下,该帐户在任何情况下都不能用于直接登录。假设已安装插件。有关说明,请参见“无登录可插入身份验证”。 ACCOUNT LOCK
创建帐户时包括该选项。请参见“ CREATE USER语句”。使用此方法时,还应包括一个密码,这样,如果以后解锁该帐户,就无法使用密码访问该帐户。(如果validate_password
启用了该组件,则即使该帐户已锁定,也将不允许创建没有密码的帐户。请参见“密码验证组件”。)- 用密码创建帐户,但不要告诉其他人该密码。如果您不让任何人知道该帐户的密码,则客户端将无法使用该帐户直接连接到MySQL服务器。
授予和撤销代理权限
PROXY
需要此特权才能使外部用户以其他用户的身份进行连接并具有其他用户的特权。要授予此特权,请使用以下GRANT
语句。例如:
GRANT PROXY ON 'proxied_user'TO 'proxy_user';
该语句在mysql.proxies_priv
授权表中创建一行。
在连接时,proxy_user
必须代表一个有效的外部认证的MySQL用户,并且proxied_user
必须代表一个有效的本地认证的用户。否则,连接尝试将失败。
相应的REVOKE
语法为:
REVOKE PROXY ON 'proxied_user'FROM 'proxy_user';
MySQL GRANT
和REVOKE
语法扩展照常工作。例子:
-- grant PROXY to multiple accountsGRANT PROXY ON 'a'TO 'b', 'c', 'd'; -- revoke PROXY from multiple accountsREVOKE PROXY ON 'a'FROM 'b', 'c', 'd'; -- grant PROXY to an account and enable the account to grant -- PROXY to the proxied accountGRANT PROXY ON 'a'TO 'd'WITH GRANT OPTION ; -- grant PROXY to default proxy accountGRANT PROXY ON 'a'TO ''@'';
该PROXY
特权可以在这些情况下被授予:
- 由具有的用户
GRANT PROXY ... WITH GRANT OPTION
使用proxied_user
。 - 按其
proxied_user
本身:对于帐户名的用户名和主机名部分,的值USER()
必须与CURRENT_USER()
和完全匹配proxied_user
。
root
在MySQL安装过程中创建的初始帐户具有的PROXY ... WITH GRANT OPTION
特权''@''
,即所有用户和所有主机的特权。这样可以root
设置代理用户,以及将设置代理用户的权限委托给其他帐户。例如,root
可以这样做:
CREATE USER 'admin'@'localhost'IDENTIFIED BY ' dmin_password';GRANT PROXY ON ''@''TO 'admin'@'localhost'WITH GRANT OPTION ;
这些语句创建一个 dmin
可以管理所有GRANT PROXY
映射的用户。例如, dmin
可以这样做:
GRANT PROXY ON sallyTO joe;
默认代理用户
要指定部分或所有用户应使用给定的身份验证插件进行连接,请创建一个具有空用户名和主机名()的“空白” MySQL帐户''@''
,并将其与该插件关联,然后让该插件返回经过身份验证的真实用户名((如果与空白用户不同)。假设存在一个名为的插件ldap_auth
,该插件实现LDAP身份验证并将连接的用户映射到开发人员或管理员帐户。要在这些帐户上设置用户代理,请使用以下语句:
-- create default proxy accountCREATE USER ''@''IDENTIFIED WITH ldap_authAS 'O=Oracle, OU=MySQL'; -- create proxied accounts; use -- mysql_no_login plugin to prevent direct loginCREATE USER 'developer'@'localhost'IDENTIFIED WITH mysql_no_login;CREATE USER 'manager'@'localhost'IDENTIFIED WITH mysql_no_login; -- grant to default proxy account the -- PROXY privilege for proxied accountsGRANT PROXY ON 'manager'@'localhost'TO ''@'';GRANT PROXY ON 'developer'@'localhost'TO ''@'';
现在假设客户端连接如下:
shell>mysql --user=myuser --password ... Enter password: myuser_password
该服务器将找不到myuser
定义为MySQL用户的服务器。但是,因为有一个空白的用户帐户(''@''
相匹配的客户端用户名和主机名),该服务器验证针对该帐户的客户端:服务器调用ldap_auth
身份验证插件和传递myuser
,并myuser_password
把它作为用户名和密码。
如果ldap_auth
插件在LDAP目录中找到的myuser_password
密码不正确myuser
,则认证失败,服务器将拒绝连接。
如果密码正确,并且ldap_auth
发现该密码是myuser
开发人员,则会将用户名返回developer
给MySQL服务器,而不是myuser
。将与myuser
信号的客户端用户名不同的用户名返回给服务器,该服务器应将其myuser
视为代理。服务器验证''@''
可以验证为身份developer
(因为''@''
有PROXY
这样做的权限)并接受连接。会话继续myuser
具有developer
代理用户的特权。(这些权限应该使用DBA设置GRANT
语句,未示出。)的USER()
和CURRENT_USER()
函数返回以下值:
mysql>SELECT USER(), CURRENT_USER(); +------------------ +--------------------- + | USER() | CURRENT_USER() | +------------------ +--------------------- + | myuser@localhost | developer@localhost | +------------------ +--------------------- +
相反,如果插件在myuser
作为管理员的LDAP目录中找到,它将manager
作为用户名返回,并且会话将继续myuser
具有manager
代理用户的特权。
mysql>SELECT USER(), CURRENT_USER(); +------------------ +------------------- + | USER() | CURRENT_USER() | +------------------ +------------------- + | myuser@localhost | manager@localhost | +------------------ +------------------- +
为简单起见,外部身份验证不能是多级的:在上一示例中,developer
没有manager
考虑凭据或凭据。但是,如果客户端尝试直接以developer
或manager
帐户连接并进行身份验证,则仍会使用它们,这就是为什么应保护这些代理帐户以防止直接登录(请参阅防止直接登录代理帐户)。
默认代理用户和匿名用户冲突
如果要创建默认代理用户,请检查其他优先于默认代理用户的现有“匹配任何用户”帐户,因为它们会阻止该用户按预期工作。
在前面的讨论中,默认代理用户帐户''
在主机部分中,该帐户与任何主机匹配。如果设置默认代理用户,请注意还要检查非代理帐户是否与同一用户部分以及'%'
在主机部分中存在,因为它'%'
也匹配任何主机,但是优先于''
服务器用来对帐户行进行排序的规则内部(请)。
假设MySQL安装包括以下两个帐户:
-- create default proxy accountCREATE USER ''@''IDENTIFIED WITH some_pluginAS 'some_auth_string'; -- create anonymous accountCREATE USER ''@'%'IDENTIFIED BY ' non_user_password';
第一个帐户(''@''
)用作默认代理用户,用于为与其他特定帐户不匹配的用户认证连接。第二个帐户(''@'%'
)是一个匿名用户帐户,例如,它可以被创建为允许没有自己帐户的用户匿名连接。
这两个帐户具有相同的用户部分(''
),该用户部分与任何用户匹配。每个帐户都有一个与任何主机匹配的主机部分。不过,帐户匹配对于连接尝试仍具有优先级,因为匹配规则将排序在'%'
之前''
。对于与任何其他特定帐户都不匹配的帐户,服务器将尝试根据''@'%'
(匿名用户)而不是''@''
(默认代理用户)对它们进行身份验证。结果,从不使用默认代理帐户。
为避免此问题,请使用以下策略之一:
- 删除匿名帐户,以免与默认代理用户冲突。
使用更特定的默认代理用户,该用户比匿名用户先匹配。例如,要仅允许
localhost
代理连接,请使用''@'localhost'
:CREATE USER ''@'localhost'IDENTIFIED WITH some_pluginAS 'some_auth_string';另外,修改任何
GRANT PROXY
语句以命名''@'localhost'
而不是''@''
作为代理用户。请注意,此策略会阻止来自的匿名用户连接
localhost
。- 使用命名的默认帐户,而不是匿名的默认帐户。有关此技术的示例,请查阅使用
uthentication_windows
插件的说明。请参见“ Windows可插入身份验证”。 创建多个代理用户,一个用于本地连接,一个用于“其他所有”(远程连接)。这在本地用户应具有与远程用户不同的特权时特别有用。
创建代理用户:
-- create proxy user for local connections
CREATE USER ''@'localhost'IDENTIFIED WITH some_pluginAS 'some_auth_string'; -- create proxy user for remote connectionsCREATE USER ''@'%'IDENTIFIED WITH some_pluginAS 'some_auth_string';创建代理用户:
-- create proxied user for local connections
CREATE USER 'developer'@'localhost'IDENTIFIED WITH mysql_no_login; -- create proxied user for remote connectionsCREATE USER 'developer'@'%'IDENTIFIED WITH mysql_no_login;向每个代理帐户
PROXY
授予相应代理帐户的特权:GRANT PROXY ON 'developer'@'localhost'TO ''@'localhost';GRANT PROXY ON 'developer'@'%'TO ''@'%';最后,为本地和远程代理用户(未显示)授予适当的特权。
假定
some_plugin
/组合导致将客户端用户名映射到。本地连接与代理用户匹配,该代理用户映射到代理用户。远程连接与代理用户匹配,该代理用户映射到代理用户。'some_auth_string'
some_plugin
developer
''@'localhost'
'developer'@'localhost'
''@'%'
'developer'@'%'
服务器对代理用户映射的支持
一些身份验证插件自己实现代理用户映射(例如,PAM和Windows身份验证插件)。默认情况下,其他身份验证插件不支持代理用户。其中,有些可以要求MySQL服务器本身根据授予的代理特权来映射代理用户:mysql_native_password
,sha256_password
。如果check_proxy_users
启用了系统变量,则服务器将对发出此类请求的所有身份验证插件执行代理用户映射:
- 默认情况下,它
check_proxy_users
是禁用的,因此即使请求服务器支持代理用户的身份验证插件,服务器也不执行代理用户映射。 如果
check_proxy_users
启用,则可能还需要启用特定于插件的系统变量,以利用服务器代理用户映射支持:- 对于
mysql_native_password
插件,请启用mysql_native_password_proxy_users
。 - 对于
sha256_password
插件,请启用sha256_password_proxy_users
。
- 对于
服务器执行的代理用户映射受以下限制:
- 即使
PROXY
授予了关联的特权,服务器也不会代理匿名用户或从匿名用户代理。 - 如果单个帐户已被授予多个代理帐户的代理特权,则服务器代理用户映射是不确定的。因此,不鼓励向单个帐户授予多个代理帐户的代理权限。
代理用户系统变量
有两个系统变量可帮助跟踪代理登录过程:
proxy_user
:此值NULL
是不使用代理的情况。否则,它指示代理用户帐户。例如,如果客户端通过''@''
代理帐户进行身份验证,则此变量的设置如下:mysql>
SELECT @@proxy_user; +-------------- + | @@proxy_user | +-------------- + | ''@'' | +-------------- +external_user
注意:有时,身份验证插件可能会使用外部用户向MySQL服务器进行身份验证。例如,当使用Windows本机身份验证时,使用Windows API进行身份验证的插件不需要将登录ID传递给它。但是,它仍然使用Windows用户ID进行身份验证。插件可以使用external_user
只读会话变量将此外部用户ID(或其首512个UTF-8字节)返回给服务器。如果插件未设置此变量,则其值为NULL
。