MySQL服务器的安全基础是:用户应该对他们需要的数据具有适当的访问权,既不能多也不能少。换句话说,普通用户不能对过多的数据具有过多的访问权。
最佳实践:
在生产环境中,不要使用root。应该创建一系列的账号,分别用于管理、供用户使用、供开发人员使用等。
用户管理
当MySQL安装完成后,MySQL用户账号信息存储在mysql数据库中。mysql数据库中有一个名为user的表,它包含所有的用户账号。用户管理就是围绕这个表开始的,当然还有一些表,例如:tables_priv,procs_priv,clumns_priv,information_schema数据库里面的USER_PRIVILEGES等。
1、创建用户账号
Syntax:
CREATE USER user_specification
[, user_specification] ...
user_specification:
user [IDENTIFIED BY [PASSWORD] 'password']
-- For each account, CREATE USER creates a new row in
-- the mysql.user table and assigns the account no privileges.
假设我想创建一个skype用户:
mysql> CREATE USER 'skype'@'localhost' IDENTIFIED BY '123456';
Query OK, 0 rows affected (0.07 sec)
但是请注意,CREATE USER虽然可以创建用户,但是它也仅仅是创建用户,并没有给用户账号分配权限,它们能登录MySQL,但是不能执行任何数据库操作。所以我们还得单独使用GRANT命令为用户授权。
使用GRANT或INSERT
GRANT语句和INSERT语句也可以创建用户账号,因为它们涉及直接操作mysql.user表,不建议这样操作。而使用CREATE USER更简单和清晰,推荐使用。
2、删除用户账号
Syntax:
DROP USER user [, user] ...
-- The DROP USER statement removes one or more MySQL accounts and their
-- privileges.
DROP USER 会删除用户账号和所有该账号相关的权限。
实例:删除我们刚才创建的账号
mysql> DROP USER 'skype'@'localhost';
Query OK, 0 rows affected (0.00 sec)
在这里为什么要用'skype'@'localhost'当用户名,而不是直接skype呢,因为mysql.user这张表,是通过用户名和host共同决定一个用户,你可查看一下表结构就知道了。如果不指定host,则使用默认的主机名 % 通配符。
用户的构成: uesrname@host
host可以是下面几种类型:
- hostname
- IP
- 网络地址, 如 192.168.%.%
账号:仅仅用于认证
权限:对资源的访问控制
show create table mysql.user \G;
你会发现有这个东西PRIMARY KEY (`Host`,`User`),表示联合主键
设置访问权限
创建用户账号之后,必须接着分配访问权限。新创建的用户账号没有访问权限。它们能登录MySQL,但是不能看到数据,不能执行任何数据库操作。
1、查看授予用户的权限
mysql> CREATE USER 'test1'@'localhost' IDENTIFIED BY '123456';
Query OK, 0 rows affected (0.00 sec)
mysql> SHOW GRANTS FOR 'test1'@'localhost';
+---------------------------------------------------------------------------+
| Grants for test1@localhost |
+---------------------------------------------------------------------------+
| GRANT USAGE ON *.* TO 'test1'@'localhost' IDENTIFIED BY PASSWORD '*6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9' |
+---------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
USAGE表示没有权限,仅能够连接登陆mysql,能做一些简单的操作。所以,test1用户在任意数据库的任意表上对任何东西都没有权限。
Syntax:
GRANT
priv_type [(column_list)]
[, priv_type [(column_list)]] ...
ON [object_type] priv_level
TO user_specification [, user_specification] ...
[REQUIRE {NONE | ssl_option [[AND] ssl_option] ...}]
[WITH with_option ...]
object_type:
TABLE
| FUNCTION
| PROCEDURE
priv_level:
*
| *.*
| db_name.*
| db_name.tbl_name
| tbl_name
| db_name.routine_name
user_specification:
user [IDENTIFIED BY [PASSWORD] 'password']
ssl_option:
SSL -- SSL 加密
| X509 -- x509证书
| CIPHER 'cipher' -- 加密算法
| ISSUER 'issuer' -- 证书颁发机构
| SUBJECT 'subject' -- 主题
with_option:
GRANT OPTION
| MAX_QUERIES_PER_HOUR count -- 每小时最多执行多少条SQL
| MAX_UPDATES_PER_HOUR count -- 每小时最多更新多少条数据
| MAX_CONNECTIONS_PER_HOUR count -- 每小时最大的连接数是多少
| MAX_USER_CONNECTIONS count -- 最大用户连接数
看着这一大堆语法头就晕了,那么只要根据上述那个图,就很好理解了:
GRANT
ON
TO
IDENTITIED BY
REQUIRE
WITH
假设,我为test1账号授予对study库中所有表有SELECT权限:
-- test1用户对study库中的所有表可SELECT
mysql> GRANT SELECT ON study.* TO 'test1'@'localhost';
Query OK, 0 rows affected (0.00 sec)
GRANT SELECT, UPDATE ON study.orders TO 'test1'@'localhost';
--对study.orders表有SELECT, UPDATE 权限
GRANT SELECT(order_num), update(order_num, order_date) ON study.orders TO 'test1'@'localhost';
-- 对orders表的order_num字段可SELECT,对order_num, order_date有UPDATE权限
相反, 我要取消test1用户的SELECT权限:
mysql> REVOKE SELECT ON study.* FROM 'test1'@'localhost';
Query OK, 0 rows affected (0.00 sec)
这个是去掉一个权限,如果我要全部去掉怎么办呢,一个一个写太麻烦了,看下面的一个例子
mysql> REVOKE ALL, GRANT OPTION FROM 'test1'@'localhost'; -- 这玩意儿很好用哦
Query OK, 0 rows affected (0.00 sec)
mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)
注意, 添加完用户账号和授予权限后,别忘了: FLUSH PRIVILEGES; 重新载入权限表
GRANT是授予用户权限 TO, 而REVOKE是从用户那儿拿走权限 FROM。
GRANT和REVOKE可以在几个层次上控制访问权限:
- 整个服务器, 使用GRANT ALL 和 REVOKE ALL
- 整个数据库, 使用ON database.*
- 特定的表, 使用 ON database.table
- 特定的列
- 特定的存储过程
下面列出各种权限:
Syntax:
SET PASSWORD [FOR user] =
{
PASSWORD('cleartext password')
| OLD_PASSWORD('cleartext password')
| 'encrypted password'
}
把test1的密码改为'helloworld':
mysql> SET PASSWORD FOR 'test1'@'localhost' = PASSWORD('helloworld');
Query OK, 0 rows affected (0.04 sec)
查看更多实例:http://dihuo.blog.51cto.com/1657091/1576377
转载于:https://blog.51cto.com/skypegnu1/1438840