针对MYSQL用户和权限管理,准备分两个部分来介绍
第一部分:主要是MYSQL数据库的权限体系以及MYSQL访问控制的两个阶段;我们都知道,MYSQL初始化完成之后,自带四个默认的数据库;下面的内容主要涉及到的是mysql库中相关的内容;
第二部分:主要是MYSQL账户以及密码管理,会涉及到账户的创建、删除、授权等问题;
授予MySQL帐户的权限决定了帐户可以执行的操作。MySQL权限在它们适用的上下文和不同操作级别上有所不同: 管理权限使用户能够管理MySQL服务器的操作;这些权限是全局的,因为它们不是特定于特定数据库的。 数据库权限适用于数据库及其中的所有对象。可以为特定数据库或全局授予这些权限,以便它们适用于所有数据库。 可以为数据库中的特定对象,数据库中给定类型的所有对象(例如,数据库中的所有表)或全局的所有对象授予数据库对象(如表,索引,视图和存储例程)的权限。所有数据库中给定类型的对象
MySQL的认证方式是“用户”+“主机”形式,而权限是访问资源对象,MySQL服务器通过权限表来控制用户对数据库的访问,权限表存放在mysql数据库中,初始化数据库时会初始化这些权限表。存储账户权限信息表主要有:user,db,tables_priv,columns_priv,procs_priv这五张表(5.6之前还有host表,现在已经把host内容整合进user表)。
官方文档对权限有比较详细的描述,为了方便我把其中的表格列在下面。第一列表示所有的权限,可以在 Grant 语句中指定的,第二列是对应权限存储在系统数据库 mysql 几张表中的定义,第三列表示权限作用的范围,其中 Global(Server administration)对应 mysql.user 表,Database 对应 mysql.db 表,Tables 对应 mysql.tables_priv 表,Columns 对应 mysql.columns_priv 表,Stored routines 对应 mysql.procs_priv 表。
GRANT语句赋予对应用户相应的权限,会根据不同的语法存储到不同的表中,以链接中官方文档中的语句为例:
GRANT ALL ON *.* TO ‘someuser’@’somehost’;GRANT SELECT, INSERT ON *.* TO ‘someuser’@’somehost’; 其中 *.* 表示所有数据的所有表,对应的权限会保存在 mysql.user 表中,和 user 相关联。
MySQL [(none)]> show create table mysql.user\G;
*************************** 1. row ***************************
Table: user
Create Table: CREATE TABLE `user` (
`Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '',
`User` char(32) COLLATE utf8_bin NOT NULL DEFAULT '',
`Select_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`Insert_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`Update_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`Delete_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`Create_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`Drop_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`Reload_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`Shutdown_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`Process_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`File_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`Grant_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`References_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`Index_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`Alter_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`Show_db_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`Super_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`Create_tmp_table_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`Lock_tables_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`Execute_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`Repl_slave_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`Repl_client_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`Create_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`Show_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`Create_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`Alter_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`Create_user_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`Event_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`Trigger_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`Create_tablespace_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`ssl_type` enum('','ANY','X509','SPECIFIED') CHARACTER SET utf8 NOT NULL DEFAULT '',
`ssl_cipher` blob NOT NULL,
`x509_issuer` blob NOT NULL,
`x509_subject` blob NOT NULL,
`max_questions` int(11) unsigned NOT NULL DEFAULT '0',
`max_updates` int(11) unsigned NOT NULL DEFAULT '0',
`max_connections` int(11) unsigned NOT NULL DEFAULT '0',
`max_user_connections` int(11) unsigned NOT NULL DEFAULT '0',
`plugin` char(64) COLLATE utf8_bin NOT NULL DEFAULT 'mysql_native_password',
`authentication_string` text COLLATE utf8_bin,
`password_expired` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`password_last_changed` timestamp NULL DEFAULT NULL,
`password_lifetime` smallint(5) unsigned DEFAULT NULL,
`account_locked` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
PRIMARY KEY (`Host`,`User`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Users and global privileges'
1 row in set (0.01 sec)
GRANT ALL ON mydb.* TO ‘someuser’@’somehost’;GRANT SELECT, INSERT ON mydb.* TO ‘someuser’@’somehost’; 其中 mydb.* 表示 mydb 数据库下的所有表,对应的权限会保存在 mysql.db 表中,和 db 相关联。
MySQL [(none)]> show create table mysql.db\G;
*************************** 1. row ***************************
Table: db
Create Table: CREATE TABLE `db` (
`Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '',
`Db` char(64) COLLATE utf8_bin NOT NULL DEFAULT '',
`User` char(32) COLLATE utf8_bin NOT NULL DEFAULT '',
`Select_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`Insert_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`Update_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`Delete_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`Create_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`Drop_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`Grant_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`References_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`Index_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`Alter_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`Create_tmp_table_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`Lock_tables_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`Create_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`Show_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`Create_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`Alter_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`Execute_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`Event_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`Trigger_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
PRIMARY KEY (`Host`,`Db`,`User`),
KEY `User` (`User`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Database privileges'
1 row in set (0.00 sec)
GRANT ALL ON mydb.mytbl TO ‘someuser’@’somehost’;GRANT SELECT, INSERT ON mydb.mytbl TO ‘someuser’@’somehost’; 对应的权限保存在 mysql.tables_priv 中,和 db , user 关联。
MySQL [(none)]> show create table mysql.tables_priv\G;
*************************** 1. row ***************************
Table: tables_priv
Create Table: CREATE TABLE `tables_priv` (
`Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '',
`Db` char(64) COLLATE utf8_bin NOT NULL DEFAULT '',
`User` char(32) COLLATE utf8_bin NOT NULL DEFAULT '',
`Table_name` char(64) COLLATE utf8_bin NOT NULL DEFAULT '',
`Grantor` char(93) COLLATE utf8_bin NOT NULL DEFAULT '',
`Timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`Table_priv` set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view','Trigger') CHARACTER SET utf8 NOT NULL DEFAULT '',
`Column_priv` set('Select','Insert','Update','References') CHARACTER SET utf8 NOT NULL DEFAULT '',
PRIMARY KEY (`Host`,`Db`,`User`,`Table_name`),
KEY `Grantor` (`Grantor`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Table privileges'
1 row in set (0.00 sec)
GRANT SELECT (col1), INSERT (col1,col2) ON mydb.mytbl TO ‘someuser’@’somehost’; 对应的权限保存在 mysql.columns_priv 中,和 db, table, user 关联。
MySQL [(none)]> show create table mysql.columns_priv\G;
*************************** 1. row ***************************
Table: columns_priv
Create Table: CREATE TABLE `columns_priv` (
`Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '',
`Db` char(64) COLLATE utf8_bin NOT NULL DEFAULT '',
`User` char(32) COLLATE utf8_bin NOT NULL DEFAULT '',
`Table_name` char(64) COLLATE utf8_bin NOT NULL DEFAULT '',
`Column_name` char(64) COLLATE utf8_bin NOT NULL DEFAULT '',
`Timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`Column_priv` set('Select','Insert','Update','References') CHARACTER SET utf8 NOT NULL DEFAULT '',
PRIMARY KEY (`Host`,`Db`,`User`,`Table_name`,`Column_name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Column privileges'
1 row in set (0.00 sec)
GRANT CREATE ROUTINE ON mydb.* TO ‘someuser’@’somehost’;GRANT EXECUTE ON PROCEDURE mydb.myproc TO ‘someuser’@’somehost’; 对应的权限保存在 mysql.procs_priv 中,和 routine_name, db,user 关联。
MySQL [(none)]> show create table mysql.procs_priv\G;
*************************** 1. row ***************************
Table: procs_priv
Create Table: CREATE TABLE `procs_priv` (
`Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '',
`Db` char(64) COLLATE utf8_bin NOT NULL DEFAULT '',
`User` char(32) COLLATE utf8_bin NOT NULL DEFAULT '',
`Routine_name` char(64) CHARACTER SET utf8 NOT NULL DEFAULT '',
`Routine_type` enum('FUNCTION','PROCEDURE') COLLATE utf8_bin NOT NULL,
`Grantor` char(93) COLLATE utf8_bin NOT NULL DEFAULT '',
`Proc_priv` set('Execute','Alter Routine','Grant') CHARACTER SET utf8 NOT NULL DEFAULT '',
`Timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`Host`,`Db`,`User`,`Routine_name`,`Routine_type`),
KEY `Grantor` (`Grantor`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Procedure privileges'
1 row in set (0.00 sec)
阶段1:客户端连接验证阶段 当尝试连接到MySQL服务器时,服务器会根据以下条件接受或拒绝连接:
您的身份以及是否可以通过提供正确的密码来验证您的身份 您的帐户是锁定还是解锁
当连接MySQL服务器时,服务器基于用户的身份以及用户是否能通过正确的密码身份验证,来接受或拒绝连接。使用三个执行凭证检查 user表范围列(Host,User,和 authentication_string)。锁定状态记录在user表格 account_locked列中。仅当某些 表行中的Host和 User列user与客户端主机名和用户名匹配时,服务器才接受连接,客户端提供该行中指定的密码, account_locked值为’N’。服务器首先检查凭据,然后检查帐户锁定状态。任一步骤失败都会导致服务器完全拒绝您的访问权限。否则,服务器接受连接,然后进入阶段2并等待请求。
如果User列值为非空,则传入连接中的用户名必须完全匹配。如果 User值为空,则它匹配任何用户名。如果user与传入连接匹配的表行具有空白用户名,则该用户被视为没有名称的匿名用户,而不是具有客户端实际指定名称的用户。这意味着空白用户名用于连接持续时间内的所有进一步访问检查(即,在阶段2期间)。
该authentication_string列可以为空白。这不是通配符,并不表示任何密码匹配。这意味着用户必须在不指定密码的情况下进行连接。如果服务器使用插件对客户端进行身份验证,则插件实现的身份验证方法可能会也可能不会使用authentication_string 列中的密码。在这种情况下,外部密码也可能用于向MySQL服务器进行身份验证。
下表显示了表中各种组合User和Host值。
传入连接的客户端主机名和用户名可以匹配user表中的多个行 。前述组实例证明这一点:若干条目的匹配示出从连接h1.example.net的fred。 当可能存在多个匹配项时,服务器必须确定要使用哪些匹配项。它解决了这个问题如下: 只要服务器将user表读入内存,它就会对行进行排序。 当客户端尝试连接时,服务器按排序顺序查看行。 服务器使用与客户端主机名和用户名匹配的第一行。
关于连接验证阶段详细可参考官方文档说明:https://dev.mysql.com/doc/refman/5.7/en/connection-access.html
阶段2:客户端请求验证阶段
建立连接后,服务器进入访问控制的第2阶段。对于通过该连接发出的每个请求,服务器确定您要执行的操作,然后检查您是否具有足够的权限来执行此操作。这是授权表中的特权列发挥作用的地方。这些权限可以来自mysql库下的 user,db, tables_priv,columns_priv,或procs_priv表。
那么接下来就可以发送数据库的操作命令给服务器端处理,服务器检查用户要执行的操作,在确认权限时,MySQL首先检查user表,如果指定的权限没有在user表中被授权;MySQL将检查db表,db表时下一安全层级,其中的权限限定于数据库层级,在该层级的SELECT权限允许用户查看指定数据库的所有表中的数据;如果在该层级没有找到限定的权限,则MySQL继续检查tables_priv表以及columns_priv表,如果所有权限表都检查完毕,但还是没有找到允许的权限操作,MySQL将返回错误信息,用户请求的操作不能执行,操作失败。
关于请求验证阶段详细可参考官方文档说明:https://dev.mysql.com/doc/refman/5.7/en/request-access.html
MYSQL账户与权限管理的第一部分就先介绍到这里,请关注第二部分的介绍与使用;