MySQL修炼二、权限与安全
权限
MySQL管理员不仅仅是运行查询,还必须采取预防措施来保护数据,并且管理有权限访问这些数据的用户。
数据库权限与安全是最后一道防线。
所以我们不能授予所有用户root访问权限,这样就使每个用户都可以完全控制MySQL服务器,我们应该为每个用户都赋予自己独特的权限。当客户端连接到MySQL服务器时,MySQL的授权系统会先经过身份验证,并且将这个用户和数据库上的权限相关联,例如 SELECT、INSERT、UPDATE 和 DELETE,这样就可以确保用户只能执行已被授予权限的操作。
权限可以分为两类,系统权限和对象权限。
系统权限可以执行一些特定的操作,比如关闭数据库、终止进程、显示数据库列表等,对象权限是指对一些特殊的对象,如表、列、视图的访问权限,例如是否允许访问某张表,或者是允许在某库中创建表。
关于权限的信息也是一张表,但一般不允许直接更改,而是通过GRANT和REVOKE语句进行赋予权限和收回。
授权的基本语法:
GRANT [权限类型] ON [数据库名].[表名] to '[用户名]'@'localhost';
权限类型是要授予用户的权限,例如 SELECT、INSERT、CREATE、UPDATE 或 DELETE。数据库名称是用户具有权访问的MySQL数据库。表名是表对象名称,也可以使用通配符授予用户访问所有表的权限如*.*
代表所有数据库下的所有表。
常见的权限包括:
-
ALL PRIVILEGES:允许用户完全访问指定的数据库,或者如果不指定数据库,则允许整个系统的全局访问。 -
CREATE:允许用户创建新表或数据库。 -
DROP:允许用户删除表或数据库。 -
DELETE:允许用户从表中删除行。 -
INSERT:允许用户向表中插入行。 -
SELECT:授予用户对指定数据库的只读权限。 -
UPDATE:允许用户更新表行。 -
LOCK TABLES:允许用户锁定表。 -
SHOW DATABASES:允许用户列出所有数据库。 -
GRANT OPTION:允许用户授予或删除其他用户的权限。必须明确授予此权限。
例子
1.创建用户user_1
1. create user user_1@'localhost' identified by '12345';create user user_1@'localhost' identified by '12345';
2.使用user_1登录,并创建数据库
1. sudo mysql -h localhost -u user_1 -p
2.create database database_1;
ERROR 1044 (42000): Access denied for user 'user_1'@'localhost' to database 'database_1'
可以看到上面因为没有权限而报错,下面来赋予user_1用户创建数据库能力。
1. grant create on *.* to 'user_1'@'localhost';
3. 重新创建数据
1. create database database_1;
Query OK, 0 rows affected (0.022 sec)
4. 授予用户user_1在database_1数据库中创建、插入、查询的权限。
1. grant create,select,insert on database_1.* to 'user_1'@'localhost';
5. user_1试图删除
会因没有权限而被拒绝,除非进行授权。
1. delete from users where 1 and 1;
ERROR 1142 (42000): DELETE command denied to user 'user_1'@'localhost' for table 'users'
6.授予用户所有权限
grant all privileges on *.* to '<username>'@'localhost';
7.撤销user_1插入数据能力
revoke insert on database_1.* to 'user_1'@'localhost';
8.查看user_1所有权限
show grants for 'user_1'@'localhost';
9.允许远程连接
GRANT ALL PRIVILEGES ON *.* TO 'user_1'@'%' IDENTIFIED BY '12345' WITH GRANT OPTION;
安全
关于MySQL安全问题有以下几点建议
-
除了 MySQL 的
root
帐户之外,不允许任何用户访问MySQL数据库中的用户表。 -
使用 GRANT 和 REVOKE 语句来控制对 MySQL 的访问。不要授予不必要的权限。
-
不要在数据库中存储简单的文本密码。要使用使用 SHA2()、SHA1()、MD5()函数或其他散列函数存储散列值 。
-
客户端访问MySQL时候,不要相信客户端输入的这些输入数据,并且必须在访问数据库之前进行验证。
-
关闭不必要的守护进程和服务,这样使得攻击者可以访问的组件变少,访问系统的漏洞的机会也越少。
-
删除所有匿名账户,MySQL默认创建几个匿名用户,安装后基本上没有任何用途。因此,应删除这些帐户,因为他们可能为攻击者提供了数据库中的入口点。
-
更改默认端口,MySQL默认在端口3306上运行,安装后应该修改此端口,可以混淆MySQL在哪些端口上运行,因为攻击者最初会尝试利用默认值。
-
更改哪些主机可以访问MySQL。
-
删除并禁用MySQL历史文件。
-
确保"log_error"不为空,错误日志包含服务器操作期间发生的严重错误、表损坏、启动和停止信息的记录。
-
如果要限制单个帐户允许的连接数,可以通过在 mysqld 中设置 max_user_connections 变量来实现。
-
永远不要以root用户身份运行 MySQL 服务器。
-
如果只使用本地连接并且不需要远程主机连接到MySQL,可以通过–skip-networking选项禁用TCP/IP连接。
-
如果要限制单个帐户允许的连接数,可以通过在 mysqld 中设置 max_user_connections 变量来实现。
防止SQL注入
SQL注入是指一些恶意者在我们不知情的情况下插入要在数据库上运行的MySQL语句的行为。比如我们在查询用户姓名时,他们会输入一个MySQL语句而不是姓名,这将在不知不觉中在数据库上运行该语句。
比如下面的例子。
SELECT * FROM Users WHERE UserId = 105;
如果105是由用户输入,那么假如用户输入一个SQL语句,如下。这个SQL是有效的,将返回“用户”表中的所有行,因为 OR 1=1始终为 TRUE。
SELECT * FROM Users WHERE UserId = 105 OR 1=1;
那如何防止SQL注入呢,如果用框架的话,其实很简单,比如MyBatis框架,轻量级,功能强大,在MyBatis中,如果写${变量名},则为直接把传入的值填充到SQL语句中,如果写#{变量名},则为传入的值只能作为值,放到SQL语句中。比如下面语句。
DELETE FROM Users WHERE name=${stu_name}
如果这样写,假如用户恶意传入这样一个字符串:abc OR 1=1,那么整个SQL就变成了DELETE FROM Users WHERE name=abc OR 1=1
,结果就是全部数据都被删掉了。
如果把${stu_name}换成#{stu_name},那么同样传入上面的字符串,最终SQL是这样的:
DELETE FROM student WHERE name=`张三 OR 1=1`
这样会删除名字为张三 OR 1=1的学生,这样就防止了SQL注入。
- END -
原文始发于微信公众号(十四个字节):MySQL修炼二、权限与安全