• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • 基于SQL的帐户活动审核

    应用程序可以使用以下准则来执行将数据库活动与MySQL帐户相关联的基于SQL的审核。

    MySQL帐户对应于mysql.user系统表中的行。客户端成功连接后,服务器会将客户端认证到该表中的特定行。该行中的UserHost列值唯一地标识帐户,并对应于在SQL语句中写入帐户名的格式。'user_name'@'host_name'

    用于认证客户端的帐户确定该客户端具有哪些特权。通常,CURRENT_USER()可以调用该函数来确定该帐户适用于客户用户。其值是从该帐户的表行的UserHost列构造user的。

    但是,在某些情况下,该CURRENT_USER()值不对应于客户端用户,而是对应于另一个帐户。当特权检查不是基于客户的帐户时,会发生以下情况:

    • SQL SECURITY DEFINER特性定义的存储例程(过程和函数)
    • SQL SECURITY DEFINER特征定义的视图
    • 触发器和事件

    在这些情况下,特权检查是针对该DEFINER帐户进行的,并且CURRENT_USER()是针对该帐户的,而不是针对调用存储例程或视图或导致触发触发器的客户端的帐户。要确定调用用户,您可以调用USER()函数,该函数返回一个值,该值指示客户端和客户端所连接的主机提供的实际用户名。但是,此值不一定直接对应于user表中的帐户,因为该USER()值永远不会包含通配符,而帐户值(由返回CURRENT_USER())可能包含用户名和主机名通配符。

    例如,一个空白的用户名与任何用户匹配,因此一个帐户''@'localhost'使客户端可以使用任何用户名从本地主机作为匿名用户连接。在这种情况下,如果客户端user1以本地主机的身份进行连接,USER()CURRENT_USER()返回不同的值:

    mysql> SELECT USER(), CURRENT_USER();
    +-----------------	+----------------	+
    | USER()           | CURRENT_USER()  |
    +-----------------	+----------------	+
    | user1@localhost  | @localhost      |
    +-----------------	+----------------	+
    

    帐户的主机名部分也可以包含通配符。如果主机名包含'%''_'模式字符或使用网络掩码符号,则该帐户可用于从多个主机连接的客户端,并且该CURRENT_USER()值不会指示哪个主机。例如,'user2'@'%.example.com'可以使用该帐户user2example.com域中的任何主机进行连接。如果user2从连接remote.example.comUSER()CURRENT_USER()返回不同的值:

    mysql> SELECT USER(), CURRENT_USER();
    +--------------------------	+---------------------	+
    | USER()                    | CURRENT_USER()       |
    +--------------------------	+---------------------	+
    | user2@remote.example.com  | user2@%.example.com  |
    +--------------------------	+---------------------	+
    

    如果应用程序必须调用USER()用户审核(例如,如果从触发器内部进行审核),但还必须能够将该USER()值与user表中的帐户关联,则必须避免在UserHost列中包含通配符的帐户。具体来说,不允许User为空(这将创建一个匿名用户帐户),并且不允许值中使用模式字符或网络掩码符号Host。所有帐户必须具有非空User值和文字Host值。

    关于前面的示例,应该更改''@'localhost''user2'@'%.example.com'帐户以不使用通配符:

    RENAME USER ''@'localhost' TO 'user1'@'localhost';
    RENAME USER 'user2'@'%.example.com' TO 'user2'@'remote.example.com';
    

    如果user2必须能够从example.com域中的多个主机进行连接,则每个主机应该有一个单独的帐户。

    要从CURRENT_USER()USER()值中提取用户名或主机名部分,请使用以下SUBSTRING_INDEX()函数:

    mysql> SELECT SUBSTRING_INDEX(CURRENT_USER(),'@',1);
    +---------------------------------------	+
    | SUBSTRING_INDEX(CURRENT_USER(),'@',1)  |
    +---------------------------------------	+
    | user1                                  |
    +---------------------------------------	+
    
    mysql> SELECT SUBSTRING_INDEX(CURRENT_USER(),'@',-1);
    +----------------------------------------	+
    | SUBSTRING_INDEX(CURRENT_USER(),'@', -1)  |
    +----------------------------------------	+
    | localhost                               |
    +----------------------------------------	+