MySQL 权限控制细节分析

今天周天,早上懒了一会儿,起的有点儿晚,中午没事儿干,重新看了看MySQL里面的权限控制模块,再次回头看,还是有很多收获的细节,这里记录一下,方便自己后续查看。
    关于权限部分的内容,之前3月11号的文章中有写过一些,今天的内容,我们使用一个一个的细节知识点来撰写(本文中所使用的MySQL版本是5.7.16),在写这些知识点之前,我们首先介绍一下MySQL的权限控制粒度、然后了解一下MySQL中客户端发起请求的时候,服务端所做的核实工作,先来看权限控制粒度:

1、全局层级

全局权限使用于给一个给定服务器中的所有数据库,这些权限存储在mysql.user表中,使用grant all on *.*的方法和revoke all on *.*的方法授予或者回收权限。

2、数据库层级

数据库权限适用于一个给定数据库中的所有目标,包含表对象和存储过程,这些权限存储在mysql.db表中,使用grant all on db_name.*或者对应的revoke方法可以授予和回收数据库权限

3、表层级

表权限适用于一个给定表中的所有列,这些权限存储在mysql的tables_priv表中,一般使用grant all on db_name.tbl_name和对应的revoke语句来授予或者撤销权限。

4、列层级的权限

列层级的权限适用于一个给定表中的指定列,这些权限存储在mysql.columns_priv的表中,由于这个权限不常用,这里给出它的授权方法示例,如下:

首先我们创建一个用户,拥有yeyztest.test1这个表的select权限:

mysql:mysql 19:35:38>>show grants for dba_yeyz@'192.168.18.%' ;
+------------------------------------------------------------------------------+
| Grants for dba_yeyz@192.168.18.%                       |
+------------------------------------------------------------------------------+
| GRANT USAGE ON *.* TO 'dba_yeyz'@'192.168.18.%'               |
| GRANT SELECT ON `yeyztest`.`test1` TO 'dba_yeyz'@'192.168.18.%'        |
+------------------------------------------------------------------------------+
2 rows in set (0.00 sec)

然后我们多test1中的一个字段id进行update操作,结果如下:

mysql> select * from test1;
+---------------+
| id      |
+---------------+
|      22 |
| 3333333333333 |
+---------------+
2 rows in set (0.00 sec)

mysql> update test1 set id=2 where id=22;
ERROR 1142 (42000): UPDATE command denied to user 'dba_yeyz'@'192.168.18.**' for table 'test1'

当然,我们是不能进行update的,这个时候,我们使用root账号给这个dba_yeyz的账号一个id列的权限,然后再看它的结果:

mysql:mysql 19:38:38>>show grants for dba_yeyz@'192.168.18.%' ;
+------------------------------------------------------------------------------+
| Grants for dba_yeyz@192.168.18.%                       |
+------------------------------------------------------------------------------+
| GRANT USAGE ON *.* TO 'dba_yeyz'@'192.168.18.%'               |
| GRANT SELECT ON `yeyztest`.`test1` TO 'dba_yeyz'@'192.168.18.%'       |
| GRANT SELECT, UPDATE (id) ON `yeyztest`.`test1` TO 'dba_yeyz'@'192.168.18.%' |
+------------------------------------------------------------------------------+
3 rows in set (0.00 sec)

这里需要注意给字段添加权限的语句,也就是:

grant  update (id) on yeyztest.test1 to XXXXXX

也就是在权限后面跟上字段的名称。

这个时候,我们查询一下columns_priv的表,可以看到里面的记录是:

mysql:mysql 19:39:46>>select * from columns_priv;
+--------------+----------+----------+------------+-------------+---------------------+-------------+
| Host     | Db    | User   | Table_name | Column_name | Timestamp      | Column_priv |
+--------------+----------+----------+------------+-------------+---------------------+-------------+
| 192.168.18.% | yeyztest | dba_yeyz | test1   | id     | 0000-00-00 00:00:00 | Update   |
+--------------+----------+----------+------------+-------------+---------------------+-------------+
1 row in set (0.00 sec)

再次用dba_yeyz进行update操作,可以看到结果:

mysql> update test1 set id=2 where id=22;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0

mysql> select *from test1;
+---------------+
| id      |
+---------------+
|       2 |
| 3333333333333 |
+---------------+
2 rows in set (0.00 sec)

将id=22的列成功改成了id=2。

5、子程序层级

create routine、alter routine、execute和grant权限适用于已经存储的子程序,这些权限可以被授予为全局层级和数据库层级,可以被存储在mysql.procs_priv中。

客户端发起请求的时候,MySQL服务器核实请求时候的流程图如下:

我将今天看到的一些细节的知识点一个一个罗列出来,希望对大家有点儿帮助:

1、在MySQL5.7.16版本中,mysql系统库中已经没有host表了,跟权限控制相关的表只有5个,分别是user、db、table_priv、proc_priv、column_priv。

2、mysql.user表的主键是用user和host联合起来组成的,且看表结构:

mysql--dba_admin@127.0.0.1:mysql 19:44:56>>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 '',
---------------权限字段(29个)--------------
 `Select_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
 ......此处省略

---------------安全字段(4个)---------------
 `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,
---------------资源控制字段(4个)--------------
 `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',
--------------插件字段(1个)---------------
 `plugin` char(64) COLLATE utf8_bin NOT NULL DEFAULT 'mysql_native_password',
--------------密码字段(5个)--------------
 `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`) -------------联合主键,host在前-----------
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Users and global privileges'
1 row in set (0.00 sec)

3、tables_priv表中只有以下权限,也就是关于表的权限:

select、insert、update、delete、drop、create、alter、grant、references、index、create view、show view、trigger;

columns_priv表中的权限只有下面四个:select、insert、update,references

4、修改一个用户的密码,一般有以下几种方式:

set password for user@host = password('newpassword');
update mysql.user set authentication_string=password('pwd') where user='username' and host='hostname';
alter user user@host identified by 'newpassword';
mysqladmin -u username -h hostname -p password "new password";

最好的方式是alter user的方法,事实上,在新的版本8.0中,set password的方法已经不能使用了,所以建议使用alter user的方法设置新的密码。

除此之外,还有一种方法,不太常用,就是使用grant的方法覆盖掉之前的密码,这里我们简单实验一般,看看效果:

mysql:mysql 20:01:05>>GRANT SELECT ON `yeyztest`.`test` TO 'dba_yeyz'@'192.168.18.%' identified by '111111';
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql:mysql 20:01:29>>select user,host,concat(user,'@','\'',host,'\''),authentication_string from mysql.user;
+------------------+----------------+-----------------------------------+-------------------------------------------+
| user       | host      | concat(user,'@','\'',host,'\'')  | authentication_string           |
+------------------+----------------+-----------------------------------+-------------------------------------------+
| dba_yeyz     | 192.168.18.%  | dba_yeyz@'192.168.18.%'      | *FD571203974BA9AFE270FE62151AE967ECA5E0AA |
+------------------+----------------+-----------------------------------+-------------------------------------------+
11 rows in set (0.00 sec)

mysql:mysql 20:01:31>>GRANT SELECT ON `yeyztest`.`test` TO 'dba_yeyz'@'192.168.18.%' identified by '123456';
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql:mysql 20:01:57>>select user,host,concat(user,'@','\'',host,'\''),authentication_string from mysql.user;
+------------------+----------------+-----------------------------------+-------------------------------------------+
| user       | host      | concat(user,'@','\'',host,'\'')  | authentication_string           |
+------------------+----------------+-----------------------------------+-------------------------------------------+
| dba_yeyz     | 192.168.18.%  | dba_yeyz@'192.168.18.%'      | *6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9 |
+------------------+----------------+-----------------------------------+-------------------------------------------+
1 rows in set (0.00 sec)

上面的测试可以看到,当我们使用grant的方法给一个指定的用户重新设置密码的时候,之前的老密码会被覆盖,所以这个操作在线上应该慎用,在每次grant的时候看看有没有已经存在的账号,确认没有之后,再进行grant操作

5、如果我们不慎忘记了mysql的root密码,可以重新启动mysql服务,加上--skip-grant-tables这个参数来启动mysql服务,这样就可以直接免除了在权限表里面的匹配工作,直接登陆进mysql服务中,从而修改root账号的密码。

6、如果使用update或者insert记录到mysql.user表中的方法创建账户或者修改密码,在执行完语句之后,必须使用flush privileges的操作刷新权限表,否则该操作无法产生效果。

7、有几个权限会影响mysqladmin工具的执行,分别是

reload权限:影响flush操作

shutdown权限:影响shutdown操作

process权限:影响processlist操作

super权限:影响kill操作

8、之前提到了mysql.user表中的资源控制的字段,分别是

max_questions每小时最大请求数、max_updates每小时最大更新数、max_connections每小时最大连接数、max_user_connections单个用户可同时建立的最大连接数。

如果我们想给一个用户设置这个参数,可以使用如下的SQL来进行设置:

mysql:mysql 20:01:58>>GRANT SELECT ON `yeyztest`.`test` TO 'dba_yeyz'@'192.168.18.%' with max_queries_per_hour 1000;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql:mysql 20:13:13>>select user,host,max_questions from mysql.user where user='dba_yeyz';
+----------+--------------+---------------+
| user   | host     | max_questions |
+----------+--------------+---------------+
| dba_yeyz | 192.168.18.% |     1000 |
+----------+--------------+---------------+
1 row in set (0.00 sec)

注意到,这里的grant语句中使用了with这个选项,with后面可以跟的选项有5个,分别是:

grant option:被授权的用户可以将这些权限赋予别的用户

max_queries_per_hour count:每个小时可以执行count次查询;

max_updates_per_hour count:每个小时可以执行count次更新;

max_connections_per_hour count:每个小时可以建立count个连接;

max_user_connections count:设置单个用户可以同时建立count个连接

9、设置全局变量:

SET GLOBAL default_password_lifetime = 180;

SET GLOBAL default_password_lifetime = 0;

可以设置密码的生命周期为6个月,6个月之后失效,如果设置为0,则一直有效。

当然,还可以在创建用户的时候就指定密码的修改周期或者禁用密码的修改周期:

CREATE USER 'jeffrey'@'localhost' PASSWORD EXPIRE INTERVAL 90 DAY;
ALTER USER 'jeffrey'@'localhost' PASSWORD EXPIRE INTERVAL 90 DAY;

CREATE USER 'jeffrey'@'localhost' PASSWORD EXPIRE NEVER;
ALTER USER 'jeffrey'@'localhost' PASSWORD EXPIRE NEVER;

10、有时候我们似乎已经删除了账号密码,但是却还可以通过账号密码进行访问,这个时候,需要检查一个设置,就是看看user表中是否有空记录:

select user,host from mysql.user where user='';

很有可能是你设置了user为空的记录,这样导致所有的用户都可以直接登陆。如果有,最好直接干掉它,因为它违背了安全的宗旨。

以上就是MySQL 权限控制细节分析的详细内容,更多关于MySQL 权限控制的资料请关注我们其它相关文章!

(0)

相关推荐

  • Mysql修改存储过程相关权限问题

    在使用mysql数据库经常都会遇到这么一个问题,其它用户定义的存储过程,现在使用另一个用户却无法修改或者删除等:正常情况下存储过程的定义者对它有修改.删除的权限:但是其它的用户就要相于的授权,不然无法查看.调用: mysql 中使用用户A创建一个存储过程,现在想通过另一个用户B来修改A创建的存储过程:以下记录就是基于这样的情况产生的: 用户A对OTO3库的权限: mysql> show grants for 'a'@'%'; +----------------------------------

  • MySQL用户与权限的管理详解

    本文实例讲述了MySQL用户与权限的管理.分享给大家供大家参考,具体如下: 用户连接到MySQL,可以做各种查询,这都是MySQL用户与权限功能在背后维持着操作. 用户与数据库服务器交互数据,分为两个阶段: (1)你有没有权连接上来 (2)你有没有权执行本操作 1.你有没有权连接上来 服务器如何判断用户有没有权连接上来? 依据: 1)你从哪里来?host 2)你是谁?user 3)你的密码是多少?password 用户的这三个信息,存储在mysql库中的user表中. 修改host域,使IP可以

  • MySQL给新建用户并赋予权限最简单的方法

    创建一个用户: create user 'oukele'@'%' identified by 'oukele'; 提示下面所列出的信息的话,得刷新一下权限表 The MySQL server is running with the --skip-grant-tables option so it cannot execute this st... 步骤如下: 扩展学习 mysql 新建用户并赋予远程访问权限 [root@demo /]# mysql -u root -p #登录服务器数据库 En

  • MYSQL开启远程访问权限的方法

    1.登陆mysql数据库 mysql -u root -p 查看user表 mysql> use mysql; Database changed mysql> select host,user,password from user; +--------------+------+-------------------------------------------+ | host | user | password | +--------------+------+--------------

  • mysql用户权限管理实例分析

    本文实例讲述了mysql用户权限管理.分享给大家供大家参考,具体如下: 本文内容: 什么是用户权限 恰当的用户权限 查看权限 修改权限 删除权限 首发日期:2018-04-19 什么是用户权限: 每个用户都有自己的用户权限,这些用户权限比如有查询表权限.修改表权限.插入表权限.新增用户权限等等. 具体的权限: 恰当的用户权限: 多数用户只需要对表进行读和写,但少数用户甚至需要能创建和删除表: 某些用户需要读表,但可能不需要更新表: 对于大多数用户,应该只提供对表的读写,不应该允许他们创建表.修改

  • mysql创建用户并赋予用户权限详细操作教程

    用户管理 新建用户 语法 CREATE USER 'username'@'localhost' IDENTIFIED BY 'password' 示例 mysql> create user 'lisi'@'localhost' identified by '123123'; Query OK, 0 rows affected (0.00 sec) username:将创建的用户名 localhost:指定用户那些主机上可以登录,可登录的IP地址,网段,主机名,如果是本机可以用localhost,

  • MySQL 权限控制详解

    mysql权限控制 作为一名DBA,想必大家对MySQL中的权限都不陌生,MySQL中对于权限的控制分为三个层面: 全局性的管理权限,作用于整个MySQL实例级别 数据库级别的权限,作用于某个指定的数据库上或者所有的数据库上 数据库对象级别的权限,作用于指定的数据库对象上(表.视图等)或 者所有的数据库对象上 这里,我们将mysql中的所有权限列出来,最后给出一个特殊的案例来反应mysql权限控制中的一个小bug.首先来看权限列表,权限的顺序按照首字母的顺序进行排列: •All/All Priv

  • MySQL如何利用DCL管理用户和控制权限

    DCL(Data Control Language):数据控制语言,用来定义数据库的访问权限和安全级别,及创建用户. 一.管理用户 1.创建用户 -- 创建用户 CREATE USER '用户名'@'主机名' IDENTIFIED BY '密码'; CREATE USER 'Summerday'@'localhost' IDENTIFIED BY '123456'; ps:如果出现了[The MySQL server is running with the --skip-grant-tables

  • MySQL查询用户权限的方法总结

    介绍两种查看MySQL用户权限的两种方法 1. 使用MySQL grants命令 mysql> show grants for username@localhost; +---------------------------------------------------------------------+ | Grants for root@localhost | +---------------------------------------------------------------

  • MySQL创建用户和权限管理的方法

    一.如何创建用户和密码 1.进入到mysql数据库下 mysql> use mysql Database changed 2.对新用户增删改 1.创建用户 # 指定ip:192.118.1.1的chao用户登录 create user 'chao'@'192.118.1.1' identified by '123'; # 指定ip:192.118.1.开头的chao用户登录 create user 'chao'@'192.118.1.%' identified by '123'; # 指定任何i

  • MySQL8.0设置远程访问权限的方法

    上一篇文章讲解了重置 MySQL 的密码,有同学反馈无法程连接到数据库,这是因为 MySQL 安装完成后只支持 localhost 访问,我们必须设置一下才可以远程访问,另外还有一些 MySQL 8.0 连接时的一些问题,本文也会一并进行讲解如何解决. 1.登录MySQL mysql -u root -p 输入您的密码 2.选择 mysql 数据库 use mysql; 因为 mysql 数据库中存储了用户信息的 user 表. 3.在 mysql 数据库的 user 表中查看当前 root 用

随机推荐