MySQL权限级别 • 全局性的管理权限,作用于整个MySQL实例级别 • 数据库级别的权限,作用于某个指定的数据库上或者所有的数据库上 • 数据库对象级别的权限,作用于指定的数据库对象上(表、视图等)或 者所有的数据库对象上 • 权限存储在mysql库的user, db, tables_priv, columns_priv, and procs_priv这几个系统表中,待MySQL实例启动后就加载到内存中
mysql> show grants for 'root'@'%'; +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Grants for root@% | +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE, CREATE ROLE, DROP ROLE ON *.* TO `root`@`%` WITH GRANT OPTION | +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec)对比root用户在几个权限系统表中的数据
select * from user where user='root' and host='%';##都是’Y’ select * from db where user='root' and host='%';##无记录 select * from tables_priv where user='root' and host='%';##无记录 select * from columns_priv where user='root' and host='%';##无记录 select * from procs_priv where user='root' and host='%';##无记录
mysql.user里存放的是全局性的管理权限
mysql.db里存放的是数据库级别的权限
mysql.tables_priv里存放的是数据库的对象级别的权限
mysql> select * from db where user='mysql.sys' and host='localhost'; +-----------+-----+-----------+-------------+-------------+-------------+-------------+-------------+-----------+------------+-----------------+------------+------------+-----------------------+------------------+------------------+----------------+---------------------+--------------------+--------------+------------+--------------+ | Host | Db | User | Select_priv | Insert_priv | Update_priv | Delete_priv | Create_priv | Drop_priv | Grant_priv | References_priv | Index_priv | Alter_priv | Create_tmp_table_priv | Lock_tables_priv | Create_view_priv | Show_view_priv | Create_routine_priv | Alter_routine_priv | Execute_priv | Event_priv | Trigger_priv | +-----------+-----+-----------+-------------+-------------+-------------+-------------+-------------+-----------+------------+-----------------+------------+------------+-----------------------+------------------+------------------+----------------+---------------------+--------------------+--------------+------------+--------------+ | localhost | sys | mysql.sys | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | Y | +-----------+-----+-----------+-------------+-------------+-------------+-------------+-------------+-----------+------------+-----------------+------------+------------+-----------------------+------------------+------------------+----------------+---------------------+--------------------+--------------+------------+--------------+ 1 row in set (0.00 sec)
mysql> show grants for 'mysql.sys'@'localhost'; +---------------------------------------------------------------+ | Grants for mysql.sys@localhost | +---------------------------------------------------------------+ | GRANT USAGE ON *.* TO `mysql.sys`@`localhost` |##usage是无权限的同义词,所以在user表可以查看到这个用户的权限基本是N | GRANT TRIGGER ON `sys`.* TO `mysql.sys`@`localhost` |##有trigger权限,可以看到db表里仅有trigger_priv是Y | GRANT SELECT ON `sys`.`sys_config` TO `mysql.sys`@`localhost` |##有select权限,可以看到tables_priv 里tables_priv的值是select +---------------------------------------------------------------+ 3 rows in set (0.00 sec) mysql> select * from user where user='mysql.sys'; +-----------+-----------+-------------+-------------+-------------+-------------+-------------+-----------+-------------+---------------+--------------+-----------+------------+-----------------+------------+------------+--------------+------------+-----------------------+------------------+--------------+-----------------+------------------+------------------+----------------+---------------------+--------------------+------------------+------------+--------------+------------------------+----------+------------+-------------+--------------+---------------+-------------+-----------------+----------------------+-----------------------+------------------------------------------------------------------------+------------------+-----------------------+-------------------+----------------+------------------+----------------+------------------------+---------------------+--------------------------+ | Host | User | Select_priv | Insert_priv | Update_priv | Delete_priv | Create_priv | Drop_priv | Reload_priv | Shutdown_priv | Process_priv | File_priv | Grant_priv | References_priv | Index_priv | Alter_priv | Show_db_priv | Super_priv | Create_tmp_table_priv | Lock_tables_priv | Execute_priv | Repl_slave_priv | Repl_client_priv | Create_view_priv | Show_view_priv | Create_routine_priv | Alter_routine_priv | Create_user_priv | Event_priv | Trigger_priv | Create_tablespace_priv | ssl_type | ssl_cipher | x509_issuer | x509_subject | max_questions | max_updates | max_connections | max_user_connections | plugin | authentication_string | password_expired | password_last_changed | password_lifetime | account_locked | Create_role_priv | Drop_role_priv | Password_reuse_history | Password_reuse_time | Password_require_current | +-----------+-----------+-------------+-------------+-------------+-------------+-------------+-----------+-------------+---------------+--------------+-----------+------------+-----------------+------------+------------+--------------+------------+-----------------------+------------------+--------------+-----------------+------------------+------------------+----------------+---------------------+--------------------+------------------+------------+--------------+------------------------+----------+------------+-------------+--------------+---------------+-------------+-----------------+----------------------+-----------------------+------------------------------------------------------------------------+------------------+-----------------------+-------------------+----------------+------------------+----------------+------------------------+---------------------+--------------------------+ | localhost | mysql.sys | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | | | | | 0 | 0 | 0 | 0 | caching_sha2_password | $A$005$THISISACOMBINATIONOFINVALIDSALTANDPASSWORDTHATMUSTNEVERBRBEUSED | N | 2020-06-27 03:12:11 | NULL | Y | N | N | NULL | NULL | NULL | +-----------+-----------+-------------+-------------+-------------+-------------+-------------+-----------+-------------+---------------+--------------+-----------+------------+-----------------+------------+------------+--------------+------------+-----------------------+------------------+--------------+-----------------+------------------+------------------+----------------+---------------------+--------------------+------------------+------------+--------------+------------------------+----------+------------+-------------+--------------+---------------+-------------+-----------------+----------------------+-----------------------+------------------------------------------------------------------------+------------------+-----------------------+-------------------+----------------+------------------+----------------+------------------------+---------------------+--------------------------+ 1 row in set (0.00 sec) mysql> select * from db where user='mysql.sys'; +-----------+-----+-----------+-------------+-------------+-------------+-------------+-------------+-----------+------------+-----------------+------------+------------+-----------------------+------------------+------------------+----------------+---------------------+--------------------+--------------+------------+--------------+ | Host | Db | User | Select_priv | Insert_priv | Update_priv | Delete_priv | Create_priv | Drop_priv | Grant_priv | References_priv | Index_priv | Alter_priv | Create_tmp_table_priv | Lock_tables_priv | Create_view_priv | Show_view_priv | Create_routine_priv | Alter_routine_priv | Execute_priv | Event_priv | Trigger_priv | +-----------+-----+-----------+-------------+-------------+-------------+-------------+-------------+-----------+------------+-----------------+------------+------------+-----------------------+------------------+------------------+----------------+---------------------+--------------------+--------------+------------+--------------+ | localhost | sys | mysql.sys | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | Y | +-----------+-----+-----------+-------------+-------------+-------------+-------------+-------------+-----------+------------+-----------------+------------+------------+-----------------------+------------------+------------------+----------------+---------------------+--------------------+--------------+------------+--------------+ 1 row in set (0.00 sec) mysql> select * from tables_priv where user='mysql.sys'; +-----------+-----+-----------+------------+----------------+---------------------+------------+-------------+ | Host | Db | User | Table_name | Grantor | Timestamp | Table_priv | Column_priv | +-----------+-----+-----------+------------+----------------+---------------------+------------+-------------+ | localhost | sys | mysql.sys | sys_config | root@localhost | 2020-06-27 03:12:11 | Select | | +-----------+-----+-----------+------------+----------------+---------------------+------------+-------------+ 1 row in set (0.00 sec) mysql>
MySQL权限详解
• All/All Privileges权限代表全局或者全数据库对象级别的所有权限 • Alter权限代表允许修改表结构的权限,但必须要求有create和insert权限配合。如果是rename表名,则要求有alter和drop原表,create和insert新表的权限 • Alter routine权限代表允许修改或者删除存储过程、函数的权限 • Create权限代表允许创建新的数据库和表的权限 • Create routine权限代表允许创建存储过程、函数的权限 • Create tablespace权限代表允许创建、修改、删除表空间和日志组的权限 • Create temporary tables权限代表允许创建临时表的权限 • Create user权限代表允许创建、修改、删除、重命名user的权限 • Create view权限代表允许创建视图的权限 • Delete权限代表允许删除行数据的权限 • Drop权限代表允许删除数据库、表、视图的权限,包括truncate table命令 • Event权限代表允许查询,创建,修改,删除MySQL事件 • Execute权限代表允许执行存储过程和函数的权限 • File权限代表允许在MySQL可以访问的目录进行读写磁盘文件操作,可使用的命令包括load data infile,select … into outfile,load file()函数 • Grant option权限代表是否允许此用户授权或者收回给其他用户你给予的权限 • Index权限代表是否允许创建和删除索引 • Insert权限代表是否允许在表里插入数据,同时在执行analyze table,optimizetable,repair table语句的时候也需要insert权限 • Lock权限代表允许对拥有select权限的表进行锁定,以防止其他链接对此表的读或写 • Process权限代表允许查看MySQL中的进程信息,比如执行show processlist,mysqladmin processlist, show engine等命令 • Reference权限是在5.7.6版本之后引入,代表是否允许创建外键 • Reload权限代表允许执行flush命令,指明重新加载权限表到系统内存中,refresh命令代表关闭和重新开启日志文件并刷新所有的表 • Replication client权限代表允许执行show master status,showslave status,showbinary logs命令 • Replication slave权限代表允许slave主机通过此用户连接master以便建立主从复制关系 • Select权限代表允许从表中查看数据,某些不查询表数据的select执行则不需要此权限,如Select 1+1,Select PI()+2;而且select权限在执行update/delete语句中含有where条件的情况下也是需要的 • Show databases权限代表通过执行show databases命令查看所有的数据库名 • Show view权限代表通过执行show create view命令查看视图创建的语句 • Shutdown权限代表允许关闭数据库实例,执行语句包括mysqladmin shutdown • Super权限代表允许执行一系列数据库管理命令,包括kill强制关闭某个连接命令,change master to创建复制关系命令,以及create/alter/drop server等命令 • Trigger权限代表允许创建,删除,执行,显示触发器的权限 • Update权限代表允许修改表中的数据的权限 • Usage权限是创建一个用户之后的默认权限,其本身代表连接登录权限 验证下全局权限效果: 首先使用新建用户njh进入命令行,切换到company库,提示没权限。mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | +--------------------+ 1 row in set (0.00 sec) mysql> use company; ERROR 1044 (42000): Access denied for user 'njh'@'localhost' to database 'company' mysql> select user(); +---------------+ | user() | +---------------+ | njh@localhost | +---------------+ 1 row in set (0.00 sec)
mysql> use mysql;
ERROR 1044 (42000): Access denied for user 'njh'@'localhost' to database 'mysql'
mysql>
使用root用户给njh授权
mysql> show grants for 'njh'@'localhost'; +-----------------------------------------+ | Grants for njh@localhost | +-----------------------------------------+ | GRANT USAGE ON *.* TO `njh`@`localhost` | #*.*第一个星号表示所有数据库 ,第二个星号表示数据库对象 +-----------------------------------------+ 1 row in set (0.00 sec) mysql> select user(); +----------------+ | user() | +----------------+ | root@localhost | +----------------+ 1 row in set (0.00 sec) mysql> grant select on *.* to 'njh'@'localhost'; Query OK, 0 rows affected (0.15 sec) mysql> flush privileges; Query OK, 0 rows affected (0.00 sec) mysql> show grants for 'njh'@'localhost'; +------------------------------------------+ | Grants for njh@localhost | +------------------------------------------+ | GRANT SELECT ON *.* TO `njh`@`localhost` | +------------------------------------------+ 1 row in set (0.00 sec) mysql>
然后重新用njh进入命令行,发现mysql和company库的表都能查到,因为select授权是全局性的管理权限
mysql> show databases; +--------------------+ | Database | +--------------------+ | company | | information_schema | | mysql | | performance_schema | | sys | +--------------------+ 5 rows in set (0.00 sec) mysql> use company; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> show tables; +-------------------+ | Tables_in_company | +-------------------+ | customers | | customers2 | | orderitems | | orders | | productnotes | | products | | vendors | +-------------------+ 7 rows in set (0.01 sec) mysql> select * from customers ; +---------+----------------+---------------------+-----------+------------+----------+--------------+--------------+---------------------+ | cust_id | cust_name | cust_address | cust_city | cust_state | cust_zip | cust_country | cust_contact | cust_email | +---------+----------------+---------------------+-----------+------------+----------+--------------+--------------+---------------------+ | 10001 | Coyote Inc. | 200 Maple Lane | Detroit | MI | 44444 | USA | Y Lee | ylee@coyote.com | | 10002 | Mouse House | 333 Fromage Lane | Columbus | OH | 43333 | USA | Jerry Mouse | NULL | | 10003 | Wascals | 1 Sunny Place | Muncie | IN | 42222 | USA | Jim Jones | rabbit@wascally.com | | 10004 | Yosemite Place | 829 Riverside Drive | Phoenix | AZ | 88888 | USA | Y Sam | sam@yosemite.com | | 10005 | E Fudd | 4545 53rd Street | Chicago | IL | 54545 | USA | E Fudd | NULL | +---------+----------------+---------------------+-----------+------------+----------+--------------+--------------+---------------------+ 5 rows in set (0.00 sec) mysql> use mysql; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> select * from db; +-----------+--------------------+---------------+-------------+-------------+-------------+-------------+-------------+-----------+------------+-----------------+------------+------------+-----------------------+------------------+------------------+----------------+---------------------+--------------------+--------------+------------+--------------+ | Host | Db | User | Select_priv | Insert_priv | Update_priv | Delete_priv | Create_priv | Drop_priv | Grant_priv | References_priv | Index_priv | Alter_priv | Create_tmp_table_priv | Lock_tables_priv | Create_view_priv | Show_view_priv | Create_routine_priv | Alter_routine_priv | Execute_priv | Event_priv | Trigger_priv | +-----------+--------------------+---------------+-------------+-------------+-------------+-------------+-------------+-----------+------------+-----------------+------------+------------+-----------------------+------------------+------------------+----------------+---------------------+--------------------+--------------+------------+--------------+ | localhost | performance_schema | mysql.session | Y | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | | localhost | sys | mysql.sys | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | Y | +-----------+--------------------+---------------+-------------+-------------+-------------+-------------+-------------+-----------+------------+-----------------+------------+------------+-----------------------+------------------+------------------+----------------+---------------------+--------------------+--------------+------------+--------------+ 2 rows in set (0.00 sec) mysql>
但是执行insert语句时会提示没权限。
mysql> insert into customers value(2,'b'); ERROR 1142 (42000): INSERT command denied to user 'njh'@'localhost' for table 'customers' mysql>
接着给njh用户授权能给company库的表插入数据,查看mysql.user 和 mysql.db可以发现select权限是存放在user表,insert是存放在db表,因为授权select时,是所有数据库,而授权insert时,只是company库
mysql> grant insert on company.* to 'njh'@'localhost'; Query OK, 0 rows affected (0.02 sec) mysql> show grants for 'njh'@'localhost'; +--------------------------------------------------+ | Grants for njh@localhost | +--------------------------------------------------+ | GRANT SELECT ON *.* TO `njh`@`localhost` | | GRANT INSERT ON `company`.* TO `njh`@`localhost` | +--------------------------------------------------+ 2 rows in set (0.00 sec) mysql> select select_priv,insert_priv from user where user='njh'; +-------------+-------------+ | select_priv | insert_priv | +-------------+-------------+ | Y | N | +-------------+-------------+ 1 row in set (0.00 sec) mysql> select select_priv,insert_priv from db where user='njh'; +-------------+-------------+ | select_priv | insert_priv | +-------------+-------------+ | N | Y | +-------------+-------------+ 1 row in set (0.00 sec) mysql>
重新用njh进入命令行,这次没提示权限了
mysql> insert into customers value(2,'b'); ERROR 1136 (21S01): Column count doesn't match value count at row 1 mysql>
收回njh用户的insert和select权限,并再授予company库下的select权限,可以看到user表的select_priv变成N,db表的select_priv变成Y。
mysql> revoke select on *.* from 'njh'@'loaclhost'; ERROR 1141 (42000): There is no such grant defined for user 'njh' on host 'loaclhost' mysql> revoke select on *.* from 'njh'@'localhost'; Query OK, 0 rows affected (0.09 sec) mysql> grant select on company.* to 'njh'@'localhost'; Query OK, 0 rows affected (0.09 sec) mysql> revoke insert on company.* from 'njh'@'localhost'; Query OK, 0 rows affected (0.10 sec) mysql> select select_priv,insert_priv from user where user='njh'; +-------------+-------------+ | select_priv | insert_priv | +-------------+-------------+ | N | N | +-------------+-------------+ 1 row in set (0.00 sec) mysql> select select_priv,insert_priv from db where user='njh'; +-------------+-------------+ | select_priv | insert_priv | +-------------+-------------+ | Y | N | +-------------+-------------+ 1 row in set (0.00 sec) mysql>
验证下:
mysql> select user(); +---------------+ | user() | +---------------+ | njh@localhost | +---------------+ 1 row in set (0.00 sec) mysql> select * from mysql.user; ERROR 1142 (42000): SELECT command denied to user 'njh'@'localhost' for table 'user' mysql> select * from company.customers; +---------+----------------+---------------------+-----------+------------+----------+--------------+--------------+---------------------+ | cust_id | cust_name | cust_address | cust_city | cust_state | cust_zip | cust_country | cust_contact | cust_email | +---------+----------------+---------------------+-----------+------------+----------+--------------+--------------+---------------------+ | 10001 | Coyote Inc. | 200 Maple Lane | Detroit | MI | 44444 | USA | Y Lee | ylee@coyote.com | | 10002 | Mouse House | 333 Fromage Lane | Columbus | OH | 43333 | USA | Jerry Mouse | NULL | | 10003 | Wascals | 1 Sunny Place | Muncie | IN | 42222 | USA | Jim Jones | rabbit@wascally.com | | 10004 | Yosemite Place | 829 Riverside Drive | Phoenix | AZ | 88888 | USA | Y Sam | sam@yosemite.com | | 10005 | E Fudd | 4545 53rd Street | Chicago | IL | 54545 | USA | E Fudd | NULL | +---------+----------------+---------------------+-----------+------------+----------+--------------+--------------+---------------------+ 5 rows in set (0.00 sec) mysql> insert into company.customers value(1,2); ERROR 1142 (42000): INSERT command denied to user 'njh'@'localhost' for table 'customers' mysql>
在数据库级别上授权njh用户对company下所有表有select权限,然后再数据库对象级别授权njh用户对company.customers有select权限
mysql> grant select on company.customers to 'njh'@'localhost'; Query OK, 0 rows affected (0.11 sec) mysql> select * from tables_priv t; +-----------+---------+---------------+------------+----------------------+---------------------+------------+-------------+ | Host | Db | User | Table_name | Grantor | Timestamp | Table_priv | Column_priv | +-----------+---------+---------------+------------+----------------------+---------------------+------------+-------------+ | localhost | company | njh | customers | root@localhost | 0000-00-00 00:00:00 | Select | | | localhost | mysql | mysql.session | user | boot@connecting host | 0000-00-00 00:00:00 | Select | | | localhost | sys | mysql.sys | sys_config | root@localhost | 2020-06-27 03:12:11 | Select | | +-----------+---------+---------------+------------+----------------------+---------------------+------------+-------------+ 3 rows in set (0.00 sec) mysql> select select_priv,insert_priv from db where user='njh'; +-------------+-------------+ | select_priv | insert_priv | +-------------+-------------+ | Y | N | +-------------+-------------+ 1 row in set (0.00 sec) mysql>
测试发现njh用户可以对除customers外的表select。
mysql> select * from customers; +---------+----------------+---------------------+-----------+------------+----------+--------------+--------------+---------------------+ | cust_id | cust_name | cust_address | cust_city | cust_state | cust_zip | cust_country | cust_contact | cust_email | +---------+----------------+---------------------+-----------+------------+----------+--------------+--------------+---------------------+ | 10001 | Coyote Inc. | 200 Maple Lane | Detroit | MI | 44444 | USA | Y Lee | ylee@coyote.com | | 10002 | Mouse House | 333 Fromage Lane | Columbus | OH | 43333 | USA | Jerry Mouse | NULL | | 10003 | Wascals | 1 Sunny Place | Muncie | IN | 42222 | USA | Jim Jones | rabbit@wascally.com | | 10004 | Yosemite Place | 829 Riverside Drive | Phoenix | AZ | 88888 | USA | Y Sam | sam@yosemite.com | | 10005 | E Fudd | 4545 53rd Street | Chicago | IL | 54545 | USA | E Fudd | NULL | +---------+----------------+---------------------+-----------+------------+----------+--------------+--------------+---------------------+ 5 rows in set (0.00 sec) mysql> select * from orderitems ; +-----------+------------+---------+----------+------------+ | order_num | order_item | prod_id | quantity | item_price | +-----------+------------+---------+----------+------------+ | 20005 | 1 | ANV01 | 10 | 5.99 | | 20005 | 2 | ANV02 | 3 | 9.99 | | 20005 | 3 | TNT2 | 5 | 10.00 | | 20005 | 4 | FB | 1 | 10.00 | | 20006 | 1 | JP2000 | 1 | 55.00 | | 20007 | 1 | TNT2 | 100 | 10.00 | | 20008 | 1 | FC | 50 | 2.50 | | 20009 | 1 | FB | 1 | 10.00 | | 20009 | 2 | OL1 | 1 | 8.99 | | 20009 | 3 | SLING | 1 | 4.49 | | 20009 | 4 | ANV03 | 1 | 14.99 | +-----------+------------+---------+----------+------------+ 11 rows in set (0.00 sec)
给njh用户授予company.orderitem表授予insert权限:
mysql> grant insert on company.orderitems to 'njh'@'localhost'; Query OK, 0 rows affected (0.05 sec) mysql> select select_priv,insert_priv from db where user='njh'; +-------------+-------------+ | select_priv | insert_priv | +-------------+-------------+ | Y | N | +-------------+-------------+ 1 row in set (0.00 sec) mysql> select select_priv,insert_priv from user where user='njh'; +-------------+-------------+ | select_priv | insert_priv | +-------------+-------------+ | N | N | +-------------+-------------+ 1 row in set (0.00 sec) mysql> select * from tables_priv t where user='njh'; +-----------+---------+------+------------+----------------+---------------------+------------+-------------+ | Host | Db | User | Table_name | Grantor | Timestamp | Table_priv | Column_priv | +-----------+---------+------+------------+----------------+---------------------+------------+-------------+ | localhost | company | njh | customers | root@localhost | 0000-00-00 00:00:00 | Select | | | localhost | company | njh | orderitems | root@localhost | 0000-00-00 00:00:00 | Insert | | +-----------+---------+------+------------+----------------+---------------------+------------+-------------+ 2 rows in set (0.00 sec) mysql>
测试下,可以insert成功:
mysql> use company; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> insert into customers value('1','2'); ERROR 1142 (42000): INSERT command denied to user 'njh'@'localhost' for table 'customers' mysql> insert into orderitems value('20009',5,'ANV03',1,11.99); Query OK, 1 row affected (0.14 sec) mysql>
mysql的权限控制,可以到字段,只需要在授权时设置便可以:
注:要注意原有是否有全局性的管理权限和数据库级别的权限,有的话需要revoke
mysql> show grants for 'njh'@'localhost'; +-------------------------------------------------------------+ | Grants for njh@localhost | +-------------------------------------------------------------+ | GRANT USAGE ON *.* TO `njh`@`localhost` | | GRANT INSERT ON `company`.`orderitems` TO `njh`@`localhost` | +-------------------------------------------------------------+ 2 rows in set (0.00 sec) mysql> grant select(cust_name) on company.customers to 'njh'@'localhost'; Query OK, 0 rows affected (0.07 sec) mysql> show grants for 'njh'@'localhost'; +--------------------------------------------------------------------------+ | Grants for njh@localhost | +--------------------------------------------------------------------------+ | GRANT USAGE ON *.* TO `njh`@`localhost` | | GRANT SELECT (`cust_name`) ON `company`.`customers` TO `njh`@`localhost` | | GRANT INSERT ON `company`.`orderitems` TO `njh`@`localhost` | +--------------------------------------------------------------------------+ 3 rows in set (0.00 sec) mysql>
测试下,生效了:
mysql> select * from company.customers ; ERROR 1143 (42000): SELECT command denied to user 'njh'@'localhost' for column 'cust_id' in table 'customers' mysql> select cust_name from company.customers; +----------------+ | cust_name | +----------------+ | Coyote Inc. | | Mouse House | | Wascals | | Yosemite Place | | E Fudd | +----------------+ 5 rows in set (0.00 sec) mysql>
系统权限表
权限存储在mysql库的user,db, tables_priv, columns_priv, and procs_priv这几个系统表中,待MySQL实例启动后就加载到内存中 • User表:存放用户账户信息以及全局级别(所有数据库)权限,决定了来自哪些主机的哪些用户可以访问数据库实例,如果有全局权限则意味着对所有数据库都有此权限 • Db表:存放数据库级别的权限,决定了来自哪些主机的哪些用户可以访问此数据库 • Tables_priv表:存放表级别的权限,决定了来自哪些主机的哪些用户可以访问数据库的这个表 • Columns_priv表:存放列级别的权限,决定了来自哪些主机的哪些用户可以访问数据库表的这个字段 • Procs_priv表:存放存储过程和函数级别的权限 User权限表结构中的特殊字段 • Plugin,password,authentication_string三个字段存放用户认证信息 • Password_expired设置成’Y’则表明允许DBA将此用户的密码设置成过期而且过期后要求用户的使用者重置密码(alter user/set password重置密码) • Password_last_changed作为一个时间戳字段代表密码上次修改时间,执行create user/alter user/set password/grant等命令创建用户或修改用户密码时此数值自动更新 • Password_lifetime代表从password_last_changed时间开始此密码过期的天数 • Account_locked代表此用户被锁住,无法使用 User和db权限表结构Tables_priv和columns_priv权限表结构
Timestamp和grantor两个字段暂时没用
Tables_priv和columns_priv权限值procs_priv权限表结构
• Routine_type是枚举类型,代表是存储过程还是函数 • Timestamp和grantor两个字段暂时没用系统权限表字段长度限制表
权限认证中的大小写敏感问题
• 字段user,password,authencation_string,db,table_name大小写敏感 • 字段host,column_name,routine_name大小写不敏感 User用户大小写敏感 • mysql> create user abc@localhost; • ERROR 1396 (HY000): Operation CREATE USER failed for 'abc'@'localhost' • mysql> create user Abc@localhost; • Query OK, 0 rows affected (0.01 sec) • Host主机名大小写不敏感 • mysql> create user abc@Localhost; • ERROR 1396 (HY000): Operation CREATE USER failed for 'abc'@'localhost' MySQL的授权用户由两部分组成:用户名和登录主机名 • 表达用户的语法为‘user_name’@‘host_name’ • 单引号不是必须,但如果其中包含特殊字符则是必须的 • ‘’@‘localhost’代表匿名登录的用户 • Host_name可以使主机名或者ipv4/ipv6的地址。Localhost代表本机,127.0.0.1代表ipv4的本机地址,::1代表ipv6的本机地址 • Host_name字段允许使用%和_两个匹配字符,比如’%’代表所有主机,’%.mysql.com’代表来自mysql.com这个域名下的所有主机,‘192.168.1.%’代表所有来自192.168.1网段的主机MySQL修改权限的生效
• 执行Grant,revoke,set password,rename user命令修改权限之后,MySQL会自动将修改后的权限信息同步加载到系统内存中 • 如果执行insert/update/delete操作上述的系统权限表之后,则必须再执行刷新权限命令才能同步到系统内存中,刷新权限命令包括:flush privileges/mysqladmin flush-privileges/mysqladmin reload • 如果是修改tables和columns级别的权限,则客户端的下次操作新权限就会生效 • 如果是修改database级别的权限,则新权限在客户端执行use database命令后生效 • 如果是修改global级别的权限,则需要重新创建连接新权限才能生效 • --skip-grant-tables可以跳过所有系统权限表而允许所有用户登录,只在特殊情况下暂时使用 MySQL用户连接 • shell> mysql --user=finley --password db_name • shell> mysql -u finley -p db_name • shell> mysql --user=finley --password=password db_name • shell> mysql -u finley -ppassword db_name 创建MySQL用户 • 有两种方式创建MySQL授权用户 • 执行create user/grant命令(推荐方式) • 通过insert语句直接操作MySQL系统权限表 • mysql> CREATE USER 'finley'@'localhost' IDENTIFIED BY 'some_pass'; • mysql> GRANT ALL PRIVILEGES ON *.* TO 'finley'@'localhost' WITH GRANT OPTION; • mysql> CREATE USER 'finley'@'%' IDENTIFIED BY 'some_pass'; • mysql> GRANT ALL PRIVILEGES ON *.* TO 'finley'@'%‘ WITH GRANT OPTION; • mysql> CREATE USER 'admin'@'localhost' IDENTIFIED BY 'admin_pass'; • mysql> GRANT RELOAD,PROCESS ON *.* TO 'admin'@'localhost'; • mysql> grant select(id) on test.temp to cdq@localhost;创建MySQL用户 • mysql> SHOW GRANTS FOR 'admin'@'localhost'; • +-----------------------------------------------------+ • | Grants for admin@localhost | • +-----------------------------------------------------+ • | GRANT RELOAD, PROCESS ON *.* TO 'admin'@'localhost' | • +-----------------------------------------------------+ • mysql> SHOW CREATE USER 'admin'@'localhost'\G • *************************** 1. row *************************** • CREATE USER for admin@localhost: CREATE USER 'admin'@'localhost' • IDENTIFIED WITH 'mysql_native_password' • AS '*67ACDEBDAB923990001F0FFB017EB8ED41861105' • REQUIRE NONE PASSWORD EXPIRE DEFAULT ACCOUNT UNLOCK创建MySQL用户 • mysql> CREATE USER 'custom'@'localhost' IDENTIFIED BY 'obscure'; • mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP • -> ON bankaccount.* • -> TO 'custom'@'localhost'; • mysql> CREATE USER 'custom'@'host47.example.com' IDENTIFIED BY 'obscure'; • mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP • -> ON expenses.* • -> TO 'custom'@'host47.example.com'; • mysql> CREATE USER 'custom'@'%.example.com' IDENTIFIED BY 'obscure'; • mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP • -> ON customer.* • -> TO 'custom'@'%.example.com';回收MySQL用户权限 • 通过revoke命令收回用户权限回收MySQL用户权限
• 通过revoke命令收回用户权限 • mysql> show grants for 'mysql.sys'@localhost; • +---------------------------------------------------------------+ • | Grants for mysql.sys@localhost | • +---------------------------------------------------------------+ • | GRANT USAGE ON *.* TO 'mysql.sys'@'localhost' | • | GRANT TRIGGER ON `sys`.* TO 'mysql.sys'@'localhost' | • | GRANT SELECT ON `sys`.`sys_config` TO 'mysql.sys'@'localhost' | • mysql> revoke select on `sys`.`sys_config` from 'mysql.sys'@localhost; • mysql> show grants for 'mysql.sys'@localhost; • +-----------------------------------------------------+ • | Grants for mysql.sys@localhost | • +-----------------------------------------------------+ • | GRANT USAGE ON *.* TO 'mysql.sys'@'localhost' | • | GRANT TRIGGER ON `sys`.* TO 'mysql.sys'@'localhost' |删除MySQL用户 • 通过执行drop user命令删除MySQL用户 • mysql> DROP USER 'jeffrey'@'localhost'; 设置MySQL用户资源限制 通过设置全局变量max_user_connections可以限制所有用户在同一时间连接MySQL实例的数量,但此参数无法对每个用户区别对待,所以MySQL提供了对每个用户的资源限制管理 • MAX_QUERIES_PER_HOUR:一个用户在一个小时内可以执行查询的次数(基本包含所有语句) • MAX_UPDATES_PER_HOUR:一个用户在一个小时内可以执行修改的次数(仅包含修改数据库或表的语句) • MAX_CONNECTIONS_PER_HOUR:一个用户在一个小时内可以连接MySQL的时间 • MAX_USER_CONNECTIONS:一个用户可以在同一时间连接MySQL实例的数量 • 从5.0.3版本开始,对用户‘user’@‘%.example.com’的资源限制是指所有通过example.com域名主机连接user用户的连接,而不是分别指从host1.example.com和host2.example.com主机过来的连接通过执行create user/alter user设置/修改用户的资源限制 • mysql> CREATE USER 'francis'@'localhost' IDENTIFIED BY 'frank' -> WITH MAX_QUERIES_PER_HOUR 20 -> MAX_UPDATES_PER_HOUR 10 -> MAX_CONNECTIONS_PER_HOUR 5 -> MAX_USER_CONNECTIONS 2; • mysql> ALTER USER 'francis'@'localhost' WITH MAX_QUERIES_PER_HOUR 100; • 取消某项资源限制既是把原先的值修改成0 • mysql> ALTER USER 'francis'@'localhost' WITH MAX_CONNECTIONS_PER_HOUR 0; • 当针对某个用户的max_user_connections非0时,则忽略全局系统参数max_user_connections,反之则全局系统参数生效 设置MySQL用户的密码 执行create user创建用户和密码 • mysql> CREATE USER 'jeffrey'@'localhost' IDENTIFIED BY 'mypass'; • 修改用户密码的方式包括: • mysql> ALTER USER 'jeffrey'@'localhost' IDENTIFIED BY 'mypass'; • mysql> SET PASSWORD FOR 'jeffrey'@'localhost' = PASSWORD('mypass'); • mysql> GRANT USAGE ON *.* TO 'jeffrey'@'localhost' IDENTIFIED BY 'mypass'; • shell> mysqladmin -u user_name -h host_name password "new_password" • 修改本身用户密码的方式包括: • mysql> ALTER USER USER() IDENTIFIED BY 'mypass'; • mysql> SET PASSWORD = PASSWORD('mypass'); 设置MySQL用户密码过期策略 设置系统参数default_password_lifetime作用于所有的用户账户 • default_password_lifetime=180 设置180天过期 • default_password_lifetime=0 设置密码不过期 • 如果为每个用户设置了密码过期策略,则会覆盖上述系统参数 • ALTER USER 'jeffrey'@'localhost' PASSWORD EXPIRE INTERVAL 90 DAY; • ALTER USER ‘jeffrey’@‘localhost’ PASSWORD EXPIRE NEVER; 密码不过期 • ALTER USER ‘jeffrey’@‘localhost’ PASSWORD EXPIRE DEFAULT; 默认过期策略 • 手动强制某个用户密码过期 • ALTER USER 'jeffrey'@'localhost' PASSWORD EXPIRE; mysql> SELECT 1; ERROR 1820 (HY000): You must SET PASSWORD before executing this statement mysql> ALTER USER USER() IDENTIFIED BY 'new_password'; Query OK, 0 rows affected (0.01 sec) mysql> SELECT 1; MySQL用户lock • 通过执行create user/alter user命令中带account lock/unlock子句设置用户的lock状态 • Create user语句默认的用户是unlock状态 • mysql> create user abc2@localhost identified by 'mysql' account lock; • Query OK, 0 rows affected (0.01 sec) • Alter user语句默认不会修改用户的lock/unlock状态 • mysql> alter user 'mysql.sys'@localhost account lock; • Query OK, 0 rows affected (0.00 sec) • mysql> alter user 'mysql.sys'@localhost account unlock; • Query OK, 0 rows affected (0.00 sec) • 当客户端使用lock状态的用户登录MySQL时,会收到如此报错Access denied for user 'user_name'@'host_name'.Account is locked.