• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • 代理用户

    MySQL服务器使用身份验证插件对客户端连接进行身份验证。验证给定连接的插件可以请求出于特权检查目的将连接(外部)用户视为其他用户。这使外部用户可以成为第二个用户的代理。也就是说,要承担第二个用户的特权:

    • 外部用户是“代理用户”(可以模拟或成为其他用户的用户)。
    • 第二用户是“代理用户”(其身份和特权可以由代理用户承担的用户)。

    本节介绍代理用户功能的工作方式。有关身份验证插件的一般信息,有关特定插件的信息,请参见“编写身份验证插件”。有关编写支持代理用户的身份验证插件的信息,请参见“在身份验证插件中实现代理用户支持”。

    • 代理用户支持的要求
    • 简单代理用户示例
    • 防止直接登录到代理帐户
    • 授予和撤销代理权限
    • 默认代理用户
    • 默认代理用户和匿名用户冲突
    • 服务器对代理用户映射的支持
    • 代理用户系统变量
    注意

    通过代理获得的管理优势是,DBA可以使用一组特权来设置一个帐户,然后使多个代理用户拥有这些特权,而不必分别为每个用户分配特权。作为代理用户的替代,DBA可能会发现角色提供了一种合适的方式来将用户映射到特定的一组命名特权上。可以给每个用户一个给定的单一角色,实际上是被授予适当的特权集。请参见“授权控制”。

    代理用户支持的要求

    为了使给定的身份验证插件进行代理,必须满足以下条件:

    • 必须由插件本身或代表该插件的MySQL服务器支持代理。在后一种情况下,可能需要显式启用服务器支持。请参阅服务器支持代理用户映射。
    • 必须将外部代理用户的帐户设置为由插件进行身份验证。使用该CREATE USER语句将帐户与身份验证插件相关联,或ALTER USER更改其插件。
    • 代理用户的帐户必须存在,并被授予代理用户要承担的特权。为此使用CREATE USER nd GRANT语句。
    • 通常,已配置代理用户,使其只能在代理场景中使用,而不能用于直接登录。
    • 代理用户帐户必须具有PROXY代理帐户的特权。GRANT为此使用语句。
    • 为了使连接到代理帐户的客户端被视为代理用户,身份验证插件必须返回与客户端用户名不同的用户名,以指示定义了代理所享有的特权的代理帐户的用户名。用户。

      替代地,对于由服务器提供代理映射的插件,根据代理用户所拥有的PROXY特权来确定代理用户。

    代理机制仅允许将外部客户端用户名映射到代理用户名。没有映射主机名的规定:

    • 当客户端连接到服务器时,服务器将根据客户端程序传递的用户名和客户端连接的主机来确定适当的帐户。
    • 如果该帐户是代理帐户,则服务器尝试使用身份验证插件返回的用户名和代理帐户的主机名,找到与代理帐户匹配的项,从而确定适当的代理帐户。代理帐户中的主机名将被忽略。

    简单代理用户示例

    请考虑以下帐户定义:

    -- create proxy account
    CREATE USER 'employee_ext'@'localhost'
    IDENTIFIED WITH my_auth_plugin
    AS 'my_auth_string';
    
    -- create proxied account and grant its privileges;
    -- use mysql_no_login plugin to prevent direct login
    CREATE USER 'employee'@'localhost'
    IDENTIFIED WITH mysql_no_login;
    GRANT ALL
    ON employees.*
    TO 'employee'@'localhost';
    
    -- grant to proxy account the
    -- PROXY privilege for proxied account
    GRANT PROXY
    ON 'employee'@'localhost'
    TO 'employee_ext'@'localhost';
    

    当客户端employee_ext从本地主机连接时,MySQL使用名为的插件my_auth_plugin执行身份验证。假设根据的内容并通过咨询某些外部身份验证系统,my_auth_plugin将用户名返回employee给服务器。名称与有所不同,因此返回请求服务器,将出于特权检查目的将外部用户视为本地用户。'my_auth_string'employeeemployee_extemployeeemployee_extemployee

    在这种情况下,employee_ext是代理用户,employee是代理用户。

    服务器通过检查(代理用户)是否具有(代理用户)的特权来验证employeeemployee_ext用户是否可以进行代理身份验证。如果尚未授予此特权,则会发生错误。否则,将承担的特权。服务器根据授予的特权检查在客户端会话期间执行的语句。在这种情况下,可以访问数据库中的表。employee_extPROXYemployeeemployee_extemployeeemployee_extemployeeemployee_extemployees

    代理帐户,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 GRANTREVOKE语法扩展照常工作。例子:

    -- grant PROXY to multiple accounts
    GRANT PROXY ON 'a' TO 'b', 'c', 'd';
    
    -- revoke PROXY from multiple accounts
    REVOKE PROXY ON 'a' FROM 'b', 'c', 'd';
    
    -- grant PROXY to an account and enable the account to grant
    -- PROXY to the proxied account
    GRANT PROXY ON 'a' TO 'd' WITH GRANT OPTION;
    
    -- grant PROXY to default proxy account
    GRANT 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 sally TO joe;
    

    默认代理用户

    要指定部分或所有用户应使用给定的身份验证插件进行连接,请创建一个具有空用户名和主机名()的“空白” MySQL帐户''@'',并将其与该插件关联,然后让该插件返回经过身份验证的真实用户名((如果与空白用户不同)。假设存在一个名为的插件ldap_auth,该插件实现LDAP身份验证并将连接的用户映射到开发人员或管理员帐户。要在这些帐户上设置用户代理,请使用以下语句:

    -- create default proxy account
    CREATE USER ''@''
    IDENTIFIED WITH ldap_auth
    AS 'O=Oracle, OU=MySQL';
    
    -- create proxied accounts; use 
    -- mysql_no_login plugin to prevent direct login
    CREATE 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 accounts
    GRANT 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考虑凭据或凭据。但是,如果客户端尝试直接以developermanager帐户连接并进行身份验证,则仍会使用它们,这就是为什么应保护这些代理帐户以防止直接登录(请参阅防止直接登录代理帐户)。

    默认代理用户和匿名用户冲突

    如果要创建默认代理用户,请检查其他优先于默认代理用户的现有“匹配任何用户”帐户,因为它们会阻止该用户按预期工作。

    在前面的讨论中,默认代理用户帐户''在主机部分中,该帐户与任何主机匹配。如果设置默认代理用户,请注意还要检查非代理帐户是否与同一用户部分以及'%'在主机部分中存在,因为它'%'也匹配任何主机,但是优先于''服务器用来对帐户行进行排序的规则内部(请)。

    假设MySQL安装包括以下两个帐户:

    -- create default proxy account
    CREATE USER ''@''
    IDENTIFIED WITH some_plugin
    AS 'some_auth_string';
    -- create anonymous account
    CREATE USER ''@'%'
    IDENTIFIED BY ' non_user_password';
    

    第一个帐户(''@'')用作默认代理用户,用于为与其他特定帐户不匹配的用户认证连接。第二个帐户(''@'%')是一个匿名用户帐户,例如,它可以被创建为允许没有自己帐户的用户匿名连接。

    这两个帐户具有相同的用户部分(''),该用户部分与任何用户匹配。每个帐户都有一个与任何主机匹配的主机部分。不过,帐户匹配对于连接尝试仍具有优先级,因为匹配规则将排序在'%'之前''。对于与任何其他特定帐户都不匹配的帐户,服务器将尝试根据''@'%'(匿名用户)而不是''@''(默认代理用户)对它们进行身份验证。结果,从不使用默认代理帐户。

    为避免此问题,请使用以下策略之一:

    • 删除匿名帐户,以免与默认代理用户冲突。
    • 使用更特定的默认代理用户,该用户比匿名用户先匹配。例如,要仅允许localhost代理连接,请使用''@'localhost'

      CREATE USER ''@'localhost'
      IDENTIFIED WITH some_plugin
      AS 'some_auth_string';
      

      另外,修改任何GRANT PROXY语句以命名''@'localhost'而不是''@''作为代理用户。

      请注意,此策略会阻止来自的匿名用户连接localhost

    • 使用命名的默认帐户,而不是匿名的默认帐户。有关此技术的示例,请查阅使用 uthentication_windows插件的说明。请参见“ Windows可插入身份验证”。
    • 创建多个代理用户,一个用于本地连接,一个用于“其他所有”(远程连接)。这在本地用户应具有与远程用户不同的特权时特别有用。

      创建代理用户:

      -- create proxy user for local connections
      CREATE USER ''@'localhost'
      IDENTIFIED WITH some_plugin
      AS 'some_auth_string';
      -- create proxy user for remote connections
      CREATE USER ''@'%'
      IDENTIFIED WITH some_plugin
      AS 'some_auth_string';
      

      创建代理用户:

      -- create proxied user for local connections
      CREATE USER 'developer'@'localhost'
      IDENTIFIED WITH mysql_no_login;
      -- create proxied user for remote connections
      CREATE 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_plugindeveloper''@'localhost''developer'@'localhost'''@'%''developer'@'%'

    服务器对代理用户映射的支持

    一些身份验证插件自己实现代理用户映射(例如,PAM和Windows身份验证插件)。默认情况下,其他身份验证插件不支持代理用户。其中,有些可以要求MySQL服务器本身根据授予的代理特权来映射代理用户:mysql_native_passwordsha256_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