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表操作来完成。授予权限和回收权限也都可以通过直接修改权限表来完成。