MySQL3-安全管理

MySQL安全管理

对于MySQL来说,其访问授权相关模块主要是由两部分组成:用户管理模块、访问授权控制模块。用户管理模块决定造访客人能否进门,而访问控制模块则决定每个客人进门能拿什么不能拿什么。

MySQL权限系统介绍

MySQL的权限系统在实现上比较简单,相关权限信息主要存储在几个被称为grant tables的系统表中,即: mysql.User,mysql.db,mysql.Host,mysql.table_priv 和mysql.column_priv。由于权限信息数据量比较小而且访问又非常频繁,所以Mysql在启动的时候,就会将所有的权限信息都Load 到内存中保存在几个特定的结构中。所以才有我们每次手工修改了权限相关的表之后,都需要执行“FLUSH PRIVILEGES”命令重新加载MySQL的权限信息。当然,如果我们通过GRANT,REVOKE 或者DROP USER 命令来修改相关权限,则不需要手工执行FLUSH PRIVILEGES命令,因为通过GRANT,REVOKE或者DROP USER命令所做的权限修改在修改系统表的同时也会更新内存结构中的权限信息。在MySQL5.0.2或更高版本的时候,MySQL还增加了CREATE USER 命令,以此创建无任何特别权限(仅拥有初始USAGE权限)的用户,通过CREATE USER 命令创建新了新用户之后,新用户的信息也会自动更新到内存结构中。所以建议尽量使用GRANT,REVOKE,CREATE USER 以及DROP USER命令来进行用户和权限的变更操作。

权限授予与去除

要为某个用户授权可以使用GRANT 命令,要去除某个用户已有的权限则使用REVOKE命令。之外还可以直接更新grant tables系统表。当给某个用户授权的时候,不仅需要指定用户名同时还要指定来访主机。如果在授权的时候仅指定用户名,则MySQL会自动认为是对'username'@'%'授权。要去除某个用户的的权限同样也需要指定来访主机。

查看某个用户目前拥有的权限,这可以通过两个方式实现:首先是通过执行“SHOW GRANTS FOR 'username'@'hostname'”命令来获取之前该用户身上的所有授权。另一种方法是查询grant tables里面的权限信息。

权限级别:Global Level

Global Level权限控制又称为全局权限控制,所有权限信息都保存在mysql.user表中。Global Level所有权限都是针对整个mysqld 的,对所有的数据库下的所有表及所有字段都有效。如果一个权限是以Global Level来授予的,则会覆盖其他所有级别的相同权限设置。

要授予Global Level的权限,则只需要在执行GRANT命令的时候,用“*.*”来指定适用范围是Global的即可,当有多个权限需要授予的时候,也并不需要多次重复执行GRANT命令,只需要一次将所有需要的权限名称通过逗号(“,”)分隔开即可。

权限级别:Database Level

Database Level是在Global Level 之下,其他三个Level 之上的权限级别,其作用域即为所指定整个数据库中的所有对象。与Global Level 的权限相比,Database Level 主要少了以下几个权限:CREATE USER,FILE,PROCESS,RELOAD,REPLICATION CLIENT,REPLICATION SLAVE,SHOW DATABASES,SHUTDOWN,SUPER 和USAGE 这几个权限,没有增加任何权限。之前我们说过Global Level的权限会覆盖底下其他四层的相同权限,Database Level 也一样,虽然他自己可能会被Global Level的权限设置所覆盖,但同时他也能覆盖比他更下层的Table,Column 和Routine 这三层的权限。

如果要授予Database Level的权限,则可以有两种实现方式:

扫描二维码关注公众号,回复: 4155465 查看本文章

①在执行GRANT命令的时候,通过“database.*”来限定权限作用域为database整个数据库。

②先通过USE命令选定需要授权的数据库,然后通过“*”来限定作用域,这样授权的作用域实际上就是当前选定的整个数据库。

在授予权限的时候,如果有相同的权限需要授予多个用户,我们也可以在授权语句中一次写上多个用户信息,通过逗号(,)分隔开。

权限级别:Table Level

Table Level权限可以被Global Level和Database Level权限所覆盖,同时也能覆盖Column Level和Routine Level的权限。Table Level权限作用范围是授权语句中所指定数据库的指定表。Table Level权限由于其作用域仅限于某个特定的表,所以权限种类也比较少,仅有ALTER,CREATE,DELETE,DROP,INDEX,INSERT,SELECT UPDATE 这八种权限。

权限级别:Column Level

Column Level的权限作用范围就更小了,仅仅是某个表的指定的某个(活某些)列。由于权限的覆盖原则,Column Level 的权限同样可以被Global,Database,Table 这三个级别的权限中的相同级别所覆盖,而且由于Column Level 所针对的权限和Routine Level的权限作用域没有重合部分,所以不会有覆盖与被覆盖的关系。针对Column Level 级别的权限仅有INSERT,SELECT 和UPDATE 这三种。Column Level 的权限授权语句语法基本和TableLevel 差不多,只是需要在权限名称后面将需要授权的列名列表通过括号括起来。

注意:当某个用户在向某个表插入(INSERT)数据的时候,如果该用户在该表中某列上面没有INSERT 权限,则该列的数据将以默认值填充。这一点和很多其他的数据库都有一些区别,是MySQL 自己在SQL 上面所做的扩展。

权限级别:Routine Level

Routine Level权限主要只有EXECUTE 和ALTER ROUTINE 两种,主要针对的对象是procedure和function这两种对象,在授予Routine Level 权限的时候,需要指定数据库和相关对象。

权限级别:GRANT

有一个非常特殊的权限GRANT,拥有GRANT权限的用户可以将自身所拥有的任何权限全部授予其他任何用户。GRANT权限的授予方式也和其他任何权限都不太一样,通常都是通过在执行GRANT授权语句的时候在最后添加WITH GRANT OPTION子句达到授予GRANT权限的目的。

此外,我们还可以通过GRANT ALL语句授予某个Level 的所有可用权限给某个用户。

MySQL访问控制实现原理:用户管理

所有授权用户都存放在一个系统表中:mysql.user,这个表不仅仅存放了授权用户的基本信息,还存放部分细化的权限信息。用户管理模块需要使用的信息很少,主要就是Host,User,Password 这三项都在mysql.user 表中。

但是这里有一个比较特殊的访问限制,如果要通过localhost访问的话,必须要有一条专门针对localhost的授权信息,即使不对任何主机做限制也不行。

如果你没有配置localhost访问的话,则在登录时使用-h参数来指定127.0.0.1也能登录成功,因为mysql在默认情况下会连接localhost。但如果你配置了localhost之后那么就无需再使用-h参数了,数据库此时默认连接localhost。

何时MySQL 存放于内存结构中的权限信息被更新??

答:FLUSH PRIVILEGES会强行让MySQL更新Load到内存中的权限信息、GRANT或者REVOKE或者CREATE USER或者DROP USER操作都能直接更新内存中权限信息、重启MySQL 会让MySQL完全从grant tables中读取权限信息。

内存结构中的权限信息更新之后对已经连接上的用户何时生效呢??????

答:

①对于Global Level的权限信息的修改,仅仅只有更改之后新建连接才会用到,对于已经连接上的session并不会受到影响。

②对于Database Level的权限信息的修改,只有当客户端请求执行了“USE database_name”命令之后,才会在重新校验中使用到新的权限信息。所以有些时候如果在做了比较紧急的Global和Database这两个Level 的权限变更之后,可能需要通过“KILL”命令将已经连接在MySQL 中的session 杀掉强迫他们重新连接以使用更新后的权限。

③对于Table Level 和Column Level 的权限,则会在下一次需要使用到该权限的Query 被请求的时候生效,也就是说,对于应用来讲,这两个Level 的权限,更新之后立刻就生效了,而不会需要执行“KILL”命令。

MySQL访问控制实现原理:访问控制

当MySQL接收到客户端的请求之后,访问控制模块是需要校验该用户是否满足提交的请求所需要的权限。权限校验过程是从最大范围的权限往最小范围的权限开始依次校验所涉及到的每个对象的每个权限。

查找流程如下:在验证所有所需权限的时候,MySQL首先会查找存储在内存结构中的权限数据,首先查找Global Level权限,如果所需权限在Global Level都有定义(GRANT 或者REVOKE),则完成权限校验(通过或者拒绝),如果没有找到所有权限的定义,则会继续往后查找Database Level 权限,进行Global Level未定义的所需权限的校验,如果仍然没有能够找到所有所需权限的定义,MySQL会继续往更小范围的权限定义域查找,也就是Table Level,最后则是Column Level或者Routine Level。

mysql.use/mysql.db/mysql.host/mysql.table_priv/mysql.column_priv每一个表针对MySQL 中的一种逻辑对象,存放某一特定Level 的权限,唯独mysql.host 稍有区别。我们现在就来看看mysql.host 权限表到底在MySQL 的访问控制中充当了一个什么样的角色呢???????

答:

首先是mysql.host 中的权限数据不是(也不能)通过GRANT 或者REVOKE 来授予或者去除,必须通过手工通过INSERT、UPDATE 和DELETE 命令来修改其中的数据。

其次是其中的权限数据无法单独生效,必须通过和mysql.db 权限表的数据一起才能生效。而且仅当mysql.db 中存在不完整(某些场景下的特殊设置)的时候,才会促使访问控制模块再结合mysql.host 中查找是否有相应的补充权限数据实现以达到权限校验的目的。

MySQL永远优先考虑更精确范围的权限。在MySQL内部会按照username和hostname作一个排序,对于相同username的权限,其host信息越接近访问者的来源host则排序位置越靠前则越早被校验使用到。而且MySQL在权限校验过程中只要找到匹配的权限之后就不会再继续往后查找是否还有匹配的权限信息而直接完成校验过程。

在mysql.user这个权限表中有max_questions,max_updates,max_connections,max_user_connections 这四列,前面三列是从MySQL4.0.2 版本才开始有的,其功能是对访问用户进行每小时所使用资源的限制,而最后的max_user_connections则是从MySQL5.0.3 版本才开始有的,他和max_connections 的区别是限制耽搁用户的连接总次数而不是每小时的连接次数。而要使这四项限制生效,需要在创建用户或者给用户授权的时候加上以下四种子句:

max_questions:WITH MAX_QUERIES_PER_HOUR n;

max_updates:WITH MAX_UPDATES_PER_HOUR n;

max_connections:WITH MAX_CONNECTIONS_PER_HOUR n;

max_user_connections:MAX_USER_CONNECTIONS。

猜你喜欢

转载自blog.csdn.net/attack_breast/article/details/84286595