mysql的权限系统通过两个阶段的认证来保证系统的安全。
首先,对连接的用户进行身份认证,合法的用户才能登录系统。
然后都用户的所拥有的权限进行认证,只有具有相应的权限才能执行相应的操作。
mysql数据库有三个权限表,分别是位于mysql库下面的user、host、db。
mysql数据库对用户权限的认证顺序是;user---》db---》表---》列
其中user是最重要的,这个表包含用户名和密码,已经可以通过哪些客户端登录。下面这些权限如果是用户拥有权限为Y,否则为N。而且这些权限是对所有数据库的。即如果是Y,就是对数据库中的所有库中的表都有权限。
具体表结构如下:
+------------------------+-----------------------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------------------+-----------------------------------+------+-----+---------+-------+
| Host | char(60) | NO | PRI | | |
| User | char(16) | NO | PRI | | |
| Password | char(41) | NO | | | |
| Select_priv | enum('N','Y') | NO | | N | |
| Insert_priv | enum('N','Y') | NO | | N | |
| Update_priv | enum('N','Y') | NO | | N | |
| Delete_priv | enum('N','Y') | NO | | N | |
| Create_priv | enum('N','Y') | NO | | N | |
| Drop_priv | enum('N','Y') | NO | | N | |
| Reload_priv | enum('N','Y') | NO | | N | |
| Shutdown_priv | enum('N','Y') | NO | | N | |
| Process_priv | enum('N','Y') | NO | | N | |
| File_priv | enum('N','Y') | NO | | N | |
| Grant_priv | enum('N','Y') | NO | | N | |
| References_priv | enum('N','Y') | NO | | N | |
| Index_priv | enum('N','Y') | NO | | N | |
| Alter_priv | enum('N','Y') | NO | | N | |
| Show_db_priv | enum('N','Y') | NO | | N | |
| Super_priv | enum('N','Y') | NO | | N | |
| Create_tmp_table_priv | enum('N','Y') | NO | | N | |
| Lock_tables_priv | enum('N','Y') | NO | | N | |
| Execute_priv | enum('N','Y') | NO | | N | |
| Repl_slave_priv | enum('N','Y') | NO | | N | |
| Repl_client_priv | enum('N','Y') | NO | | N | |
| Create_view_priv | enum('N','Y') | NO | | N | |
| Show_view_priv | enum('N','Y') | NO | | N | |
| Create_routine_priv | enum('N','Y') | NO | | N | |
| Alter_routine_priv | enum('N','Y') | NO | | N | |
| Create_user_priv | enum('N','Y') | NO | | N | |
| Event_priv | enum('N','Y') | NO | | N | |
| Trigger_priv | enum('N','Y') | NO | | N | |
| Create_tablespace_priv | enum('N','Y') | NO | | N | |
| ssl_type | enum('','ANY','X509','SPECIFIED') | NO | | | |
| ssl_cipher | blob | NO | | NULL | |
| x509_issuer | blob | NO | | NULL | |
| x509_subject | blob | NO | | NULL | |
| max_questions | int(11) unsigned | NO | | 0 | |
| max_updates | int(11) unsigned | NO | | 0 | |
| max_connections | int(11) unsigned | NO | | 0 | |
| max_user_connections | int(11) unsigned | NO | | 0 | |
| plugin | char(64) | YES | | | |
| authentication_string | text | YES | | NULL | |
+------------------------+-----------------------------------+------+-----+---------+-------+
42 rows in set (0.00 sec)
其次是db表,这个如果用户的权限在user表中为Y,在db表中也为Y。如果在user表中为N,在db表中为Y,该用户就对相应的库具有权限,而不是所有库。
host表一般很少使用到。
mysql新创建用户不止一种方式:
可以使用create user语句
也可以使用grant语句,如果用户不存在就创建用户,并授权,如果用户存在就授予相应权限。
也可以直接修改用户权限user表
mysql> create user test1 identified by '123';
Query OK, 0 rows affected (0.00 sec)
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| intopay |
| mysql |
| performance_schema |
| test |
+--------------------+
5 rows in set (0.00 sec)
mysql> create database test1;
Query OK, 1 row affected (0.00 sec)
mysql> select * from user where user='test1'\G;
*************************** 1. row ***************************
Host: %
User: test1
Password: *23AE809DDACAF96AF0FD78ED04B6A265E05AA257
Select_priv: N
Insert_priv: N
Update_priv: N
Delete_priv: N
Create_priv: N
Drop_priv: N
Reload_priv: N
Shutdown_priv: N
Process_priv: N
File_priv: N
Grant_priv: N
References_priv: N
Index_priv: N
Alter_priv: N
Show_db_priv: N
Super_priv: N
Create_tmp_table_priv: N
Lock_tables_priv: N
Execute_priv: N
Repl_slave_priv: N
Repl_client_priv: N
Create_view_priv: N
Show_view_priv: N
Create_routine_priv: N
Alter_routine_priv: N
Create_user_priv: N
Event_priv: N
Trigger_priv: N
Create_tablespace_priv: N
ssl_type:
ssl_cipher:
x509_issuer:
x509_subject:
max_questions: 0
max_updates: 0
max_connections: 0
max_user_connections: 0
plugin:
authentication_string: NULL
1 row in set (0.00 sec)
ERROR:
No query specified
mysql> select * from db where user='test1'\G;
Empty set (0.00 sec)
ERROR:
No query specified
mysql>
创建了一个test1用户,密码是123,创建用户或者在对用户授权是如果没有指定主机名或者IP地址,默认是所有客户端,可以通过user表的查询结果等到验证。
还有一点就是如果对用户登录的客户端指定了%,即所有客户端时,这个所有是不包括localhost的。如果也希望通过localhost登录,必须重新授权并明确指定客户端的ip或主机名是127.0.0.1或者localhost
新创建的用户还没有授权,所有user表全部为N,而db表位空。
mysql> grant select,insert on test1.* to 'test1'@'localhost' identified by ‘123’;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from db where user='test1'\G;
*************************** 1. row ***************************
Host: localhost
Db: test1
User: test1
Select_priv: Y
Insert_priv: Y
Update_priv: N
Delete_priv: N
Create_priv: N
Drop_priv: N
Grant_priv: N
References_priv: N
Index_priv: N
Alter_priv: N
Create_tmp_table_priv: N
Lock_tables_priv: N
Create_view_priv: N
Show_view_priv: N
Create_routine_priv: N
Alter_routine_priv: N
Execute_priv: N
Event_priv: N
Trigger_priv: N
1 row in set (0.00 sec)
ERROR:
No query specified
mysql>
对用户test1授予select和insert权限对test1数据库,这是可以看到db表的变化。host字段是localhost,
其实现在我们不是在为之前用create语句创建的用户授权,而是新建了一个用户,mysql用户是包含两部分的:’username‘@’client‘
我现在grant的对象是'test1'@'localhost',而不是'test1'@'%',
mysql> select user,host from user where user='test1';
+-------+-----------+
| user | host |
+-------+-----------+
| test1 | % |
| test1 | localhost |
+-------+-----------+
2 rows in set (0.00 sec)
mysql>
现在用户test1已经可以登录数据库了。
root@redhat62 ~]# mysql -u test1 -p123
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 15
Server version: 5.5.18-log MySQL Community Server (GPL)
Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| test |
| test1 |
+--------------------+
3 rows in set (0.00 sec)
mysql>
如果一个数据库中一个用户组user表中用多条记录,数据库是如果判断该使用哪一条记录的呢?
当用户连接数据库是认证的顺序是先匹配最精确的技术,如host为具体IP或主机名的记录,然后再匹配不精确的记录,如192.168.163.%、%
现在再添加一个用户,用户名也是test1,不过指定只能通过192.168.163.160连接。
mysql> grant select,insert on test1.* to 'test1'@'192.168.163.160' identified by '123';
Query OK, 0 rows affected (0.00 sec)
mysql> select user,host,password from user where user='test1';
+-------+-----------------+-------------------------------------------+
| user | host | password |
+-------+-----------------+-------------------------------------------+
| test1 | % | *23AE809DDACAF96AF0FD78ED04B6A265E05AA257 |
| test1 | localhost | *23AE809DDACAF96AF0FD78ED04B6A265E05AA257 |
| test1 | 192.168.163.160 | *23AE809DDACAF96AF0FD78ED04B6A265E05AA257 |
+-------+-----------------+-------------------------------------------+
3 rows in set (0.00 sec)
现在我们拥有3个同名的用户,但是他们能数据库的客户端是不同的。但是现在密码相同了,没法验证。host为192.168.163.160的密码修改一下。
mysql用户修改密码很好几种方法:
1、mysqladmin -u username -h host password ‘pasword’
2,set password for 'username'@'host' = password('password'); 如果是自己改自己的密码可以set password=password('password');
3、grant usage on *.* to 'username'@'host' identified by 'password';
4、update user set password=password('password') where user='username' and host='host';
我们使用update更改。
mysql> update user set password=password('password123') where user='test1' and host='192.168.163.160';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)
mysql> select user,host,password from user where user='test1';
+-------+-----------------+-------------------------------------------+
| user | host | password |
+-------+-----------------+-------------------------------------------+
| test1 | % | *23AE809DDACAF96AF0FD78ED04B6A265E05AA257 |
| test1 | localhost | *23AE809DDACAF96AF0FD78ED04B6A265E05AA257 |
| test1 | 192.168.163.160 | *A0F874BC7F54EE086FCE60A37CE7887D8B31086B |
+-------+-----------------+-------------------------------------------+
3 rows in set (0.00 sec)
mysql>
现在我们在192.168.163.160这台机器上登录mysql使用test1用户,密码应该使用123,还是password123呢?
root@vmhost06 ~]# mysql -u test1 -p123 -h 192.168.163.150
ERROR 1045 (28000): Access denied for user 'test1'@'192.168.163.160' (using password: YES)
[root@vmhost06 ~]# mysql -u test1 -ppassword123 -h 192.168.163.150
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 18
Server version: 5.5.18-log MySQL Community Server (GPL)
Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
很显然password123代表的更精确的host内容战胜了123代表的不精确的host内容。
用户权限的授予是grant,而回收使用的revoke。
而revoke有一个权限是不能回收的,那就是usage权限,这个权限是当用户建立好就具有的。
mysql> show grants for 'test1'@'%';
+------------------------------------------------------------------------------------------------------+
| Grants for test1@% |
+------------------------------------------------------------------------------------------------------+
| GRANT USAGE ON *.* TO 'test1'@'%' IDENTIFIED BY PASSWORD '*23AE809DDACAF96AF0FD78ED04B6A265E05AA257' |
+------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
mysql> revoke usage on *.* from 'test1'@'%';
Query OK, 0 rows affected (0.00 sec)
mysql> show grants for 'test1'@'%';
+------------------------------------------------------------------------------------------------------+
| Grants for test1@% |
+------------------------------------------------------------------------------------------------------+
| GRANT USAGE ON *.* TO 'test1'@'%' IDENTIFIED BY PASSWORD '*23AE809DDACAF96AF0FD78ED04B6A265E05AA257' |
+------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
我们使用create创建了一个用户,而且没有授予任何的权限,但是当我们查询到时候却看到上面的内容。这个伴随用户诞生的权限。有了这个权限用户就能登录数据库,但是什么都干不了。
mysql> select * from db where user='test1' and host='localhost'\G;
*************************** 1. row ***************************
Host: localhost
Db: test1
User: test1
Select_priv: Y
Insert_priv: Y
Update_priv: N
Delete_priv: N
Create_priv: N
Drop_priv: N
Grant_priv: N
References_priv: N
Index_priv: N
Alter_priv: N
Create_tmp_table_priv: N
Lock_tables_priv: N
Create_view_priv: N
Show_view_priv: N
Create_routine_priv: N
Alter_routine_priv: N
Execute_priv: N
Event_priv: N
Trigger_priv: N
1 rows in set (0.00 sec)
ERROR:
No query specified
mysql> revoke select on test1.* from 'test1'@'localhost';
Query OK, 0 rows affected (0.00 sec)
mysql> select * from db where user='test1' and host='localhost'\G;
*************************** 1. row ***************************
Host: localhost
Db: test1
User: test1
Select_priv: N
Insert_priv: Y
Update_priv: N
Delete_priv: N
Create_priv: N
Drop_priv: N
Grant_priv: N
References_priv: N
Index_priv: N
Alter_priv: N
Create_tmp_table_priv: N
Lock_tables_priv: N
Create_view_priv: N
Show_view_priv: N
Create_routine_priv: N
Alter_routine_priv: N
Execute_priv: N
Event_priv: N
Trigger_priv: N
1 row in set (0.00 sec)
ERROR:
No query specified
mysql>
select_priv由原来的Y变成了N,表示权限已经回收。
删除用户就是drop user 'username'@'host'语句
我们来删除'test1'@'%'
mysql> drop user 'test1'@'%';
Query OK, 0 rows affected (0.00 sec)
mysql> select user,host from user where user='test1';
+-------+-----------------+
| user | host |
+-------+-----------------+
| test1 | 192.168.163.160 |
| test1 | localhost |
+-------+-----------------+
2 rows in set (0.00 sec)
用户已经在user表中不存在了。
用户的创建和删除可以通过直接对user表操作来完成。授予权限和回收权限也都可以通过直接修改权限表来完成。