MySQL 的權限表在數據庫啓動的時候就載入內存,當用戶經過身份認證後,就在內存中進行相應權限的存取,這樣,此用戶就能夠在數據庫中作權限範圍內的各類操做了。mysql
1、權限表的存取sql
在權限存取的兩個過程當中,系統會用到 「mysql」 數據庫(安裝 MySQL 時被建立,數據庫名稱叫「mysql」) 中 user、host 和 db 這3個最重要的權限表。shell
在這 3 個表中,最重要的表示 user 表,其次是 db 表,host 表在大多數狀況下並不使用。數據庫
user 中的列主要分爲 4 個部分:用戶列、權限列、安全列和資源控制列。安全
一般用的最多的是用戶列和權限列,其中權限列又分爲普通權限和管理權限。普通權限用於數據庫的操做,好比 select_priv、super_priv 等。服務器
當用戶進行鏈接時,權限表的存取過程有如下兩個過程:併發
- 先從 user 表中的 host、user 和 password 這 3 個字段中判斷鏈接的 IP、用戶名、和密碼是否存在於表中,若是存在,則經過身份驗證,不然拒絕鏈接。
- 若是經過身份驗證、則按照如下權限表的順序獲得數據庫權限:user -> db -> tables_priv -> columns_priv。
在這幾個權限表中,權限範圍依次遞減,全局權限覆蓋局部權限。上面的第一階段好理解,下面以一個例子來詳細解釋一下第二階段。ide
爲了方便測試,須要修改變量 sql_mode測試
- // sql_mode 默認值中有 NO_AUTO_CREATE_USER (防止GRANT自動建立新用戶,除非還指定了密碼)
-
- SET SESSION sql_mode='STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION';
1. 建立用戶 zj@localhost,並賦予全部數據庫上的全部表的 select 權限加密
- MySQL [mysql]> grant select on *.* to zj@localhost;
- Query OK, 0 rows affected, 2 warnings (0.00 sec)
-
- MySQL [mysql]> select * from user where user="zj" and host='localhost' \G;
- *************************** 1. row ***************************
- Host: localhost
- User: zj
- Select_priv: Y
- Insert_priv: N
- Update_priv: N
- Delete_priv: N
- Create_priv: N
- Drop_priv: N
- Reload_priv: N
- ...
2. 查看 db 表
- MySQL [mysql]> select * from db where user='zj' \G ;
-
- Empty set (0.00 sec)
能夠發現,user 表的 select_priv 列是 「Y」,而 db 表中並無記錄,也就是說,對全部數據庫都具備相同的權限的用戶並不須要記錄到 db 表,而僅僅須要將 user 表中的 select_priv 改成 「Y」 便可。換句話說,user 表中的每一個權限都表明了對全部數據庫都有權限。
3. 將 zj@localhost 上的權限改成只對 t2 數據庫上全部表的 select 權限。
- MySQL [mysql]> revoke select on *.* from zj@localhost;
- Query OK, 0 rows affected, 1 warning (0.02 sec)
-
- MySQL [mysql]> grant select on t2.* to zj@localhost;
- Query OK, 0 rows affected, 1 warning (0.04 sec)
-
- MySQL [mysql]> select * from user where user='zj' \G;
- *************************** 1. row ***************************
- Host: localhost
- User: zj
- Select_priv: N
- Insert_priv: N
- Update_priv: N
- Delete_priv: N
- Create_priv: N
- Drop_priv: N
- Reload_priv: N
- ...
-
- MySQL [mysql]> select * from db where user='zj' \G;
- *************************** 1. row ***************************
- Host: localhost
- Db: t2
- User: zj
- Select_priv: Y
- Insert_priv: N
- Update_priv: N
- Delete_priv: N
- Create_priv: N
- Drop_priv: N
- Grant_priv: N
這時候發現,user 表中的 select_priv 變爲 「N」 ,而 db 表中增長了 db 爲 t2 的一條記錄。也就是說,當只授予部分數據庫某些權限時,user 表中的相應權限列保持 「N」,而將具體的數據庫權限寫入 db 表。table 和 column 的權限機制和 db 相似。
從上例能夠看出,當用戶經過權限認證,進行權限分配時,將按照 user -> db -> tables_priv -> columns_priv 的順序進行權限分配,即先檢查全局權限表 user,若是 user 中對應 權限爲 「Y」,則此用戶對全部數據庫的權限都爲「Y」,將再也不檢查 db、tables_priv 和 columns_priv;若是爲「N」,則到 db 表中檢查此用戶對應的具體數據庫,並獲得 db 中爲 「Y」的權限;若是 db 中相應權限爲 「N」,則再依次檢查tables_priv 和 columns_priv 中的權限,若是全部的都爲「N」,則判斷爲不具有權限。
2、帳號管理
主要包括帳號的建立,權限的更改和帳號的刪除。
1. 建立帳號
使用 grant 語法建立,示例:
(1) 建立用戶 zj ,權限爲能夠在全部數據庫上執行全部權限,只能從本地進行鏈接。
- MySQL [mysql]> grant all privileges on *.* to zj@localhost;
- Query OK, 0 rows affected, 2 warnings (0.00 sec)
-
- MySQL [mysql]> select * from user where user="zj" and host="localhost" \G;
- *************************** 1. row ***************************
- Host: localhost
- User: zj
- Select_priv: Y
- Insert_priv: Y
- Update_priv: Y
- Delete_priv: Y
- Create_priv: Y
- Drop_priv: Y
- Reload_priv: Y
- Shutdown_priv: Y
能夠發現,除了 grant_priv 權限外,全部權限在 user 表裏面都是 「Y」。
(2) 在 (1) 基礎上,增長對 zj 的 grant 權限
- MySQL [(none)]> grant all privileges on *.* to zj@localhost with grant option;
- Query OK, 0 rows affected, 1 warning (0.01 sec)
-
- MySQL [mysql]> select * from user where user="zj" and host='localhost' \G ;
- *************************** 1. row ***************************
- Host: localhost
- User: zj
- Select_priv: Y
- Insert_priv: Y
- Update_priv: Y
- Delete_priv: Y
- Create_priv: Y
- Drop_priv: Y
- Reload_priv: Y
- Shutdown_priv: Y
- Process_priv: Y
- File_priv: Y
- Grant_priv: Y
- ...
(3) 在 (2) 基礎上,設置密碼爲 「123」
- MySQL [mysql]> grant all privileges on *.* to zj@localhost identified by '123' with grant option;
- Query OK, 0 rows affected, 2 warnings (0.01 sec)
-
- MySQL [mysql]> select * from user where user="zj" and host="localhost" \G ;
- *************************** 1. row ***************************
- Host: localhost
- User: zj
- Select_priv: Y
- Insert_priv: Y
- Update_priv: Y
- Delete_priv: Y
- Create_priv: Y
- Drop_priv: Y
- Reload_priv: Y
- ......
- authentication_string: *23AE809DDACAF96AF0FD78ED04B6A265E05AA257
- password_expired: N
- password_last_changed: 2017-09-25 20:29:42
- password_lifetime: NULL
能夠發現,密碼變成了一堆加密後的字符串。
(4) 建立新用戶 zj2,能夠從任何 IP 鏈接,權限爲對 t2 數據庫裏的全部表進行 select 、update、insert 和 delete 操做,初始密碼爲「123」
- MySQL [mysql]> grant select ,insert, update,delete on t2.* to 'zj2'@'%' identified by '123';
- Query OK, 0 rows affected, 1 warning (0.00 sec)
-
- MySQL [mysql]> select * from user where user='zj2' and host="%" \G;
- *************************** 1. row ***************************
- Host: %
- User: zj2
- Select_priv: N
- Insert_priv: N
- Update_priv: N
- Delete_priv: N
- Create_priv: N
- Drop_priv: N
- ......
- authentication_string: *23AE809DDACAF96AF0FD78ED04B6A265E05AA257
- password_expired: N
- password_last_changed: 2017-09-25 20:37:49
- password_lifetime: NULL
-
- MySQL [mysql]> select * from db where user="zj2" and host='%' \G;
- *************************** 1. row ***************************
- Host: %
- Db: t2
- User: zj2
- Select_priv: Y
- Insert_priv: Y
- Update_priv: Y
- Delete_priv: Y
- Create_priv: N
- Drop_priv: N
- ......
user 表中的權限都是「N」,db 表中增長的記錄權限則都是「Y」。通常的,只授予用戶適當的權限,而不會授予過多的權限。
本例中的 IP 限制爲全部 IP 均可以鏈接,所以設置爲 「*」,mysql 數據庫中是經過 user 表的 host 字段來進行控制,host 能夠是如下類型的賦值。
- Host 值能夠是主機名或IP號,或 「localhost」 指出本地主機。
- 能夠在 Host 列值使用通配符字符 「%」 和 「_」
- Host 值 「%」 匹配任何主機名,空 Host 值等價於 「%」,它們的含義與 like 操做符的模式匹配操做相同。
注意: mysql 數據庫的 user 表中 host 的值爲 「*」 或者空,表示全部外部 IP 均可以鏈接,可是不包括本地服務器 localhost,所以,若是要包括本地服務器,必須單獨爲 localhost 賦予權限。
(5) 授予 super、process、file 權限給用戶 zj3@%
- MySQL [mysql]> grant super,process,file on *.* to 'zj3'@'%';
-
- Query OK, 0 rows affected, 1 warning (0.00 sec)
由於這幾個權限都是屬於管理權限,所以不可以指定某個數據庫,on 後面必須跟 「.」,下面語法將提示錯誤
- MySQL [mysql]> grant super,process,file on t2.* to 'zj3'@'%';
-
- ERROR 1221 (HY000): Incorrect usage of DB GRANT and GLOBAL PRIVILEGES
(6) 只授予登陸權限給 zj4@localhost
- MySQL [mysql]> grant usage on *.* to 'zj4'@'localhost';
- Query OK, 0 rows affected, 2 warnings (0.01 sec)
-
- MySQL [mysql]> exit
- Bye
-
- zj@bogon:~$ mysql -uzj4 -p
- Enter password:
- Welcome to the MySQL monitor. Commands end with ; or \g.
- Your MySQL connection id is 78
- Server version: 5.7.18-log Source distribution
-
- Copyright (c) 2000, 2017, 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 [(none)]> show databases;
- +--------------------+
- | Database |
- +--------------------+
- | information_schema |
- +--------------------+
- 1 row in set (0.02 sec)
usage 權限只能用於數據庫登陸,不能執行任何操做
2. 查看帳號權限
帳號建立好後,能夠經過以下命令查看權限:
- show grants for user@host;
示例:
- MySQL [(none)]> show grants for zj@localhost;
- +-------------------------------------------------------------------+
- | Grants for zj@localhost |
- +-------------------------------------------------------------------+
- | GRANT ALL PRIVILEGES ON *.* TO 'zj'@'localhost' WITH GRANT OPTION |
- +-------------------------------------------------------------------+
- 1 row in set (0.01 sec)
3. 更改帳號權限
能夠進行權限的新增和回收。和建立帳號同樣,權限變動也有兩種方法:使用 grant(新增) 和 revoke (回收) 語句,或者更改權限表。
示例:
(1) zj4@localhost 目前只有登陸權限
- MySQL [(none)]> show grants for zj4@localhost;
- +-----------------------------------------+
- | Grants for zj4@localhost |
- +-----------------------------------------+
- | GRANT USAGE ON *.* TO 'zj4'@'localhost' |
- +-----------------------------------------+
- 1 row in set (0.00 sec)
(2) 賦予 zj4@localhost 全部數據庫上的全部表的 select 權限
- MySQL [(none)]> grant select on *.* to 'zj4'@'localhost';
- Query OK, 0 rows affected, 1 warning (0.00 sec)
-
- MySQL [(none)]> show grants for zj4@localhost;
- +------------------------------------------+
- | Grants for zj4@localhost |
- +------------------------------------------+
- | GRANT SELECT ON *.* TO 'zj4'@'localhost' |
- +------------------------------------------+
- 1 row in set (0.00 sec)
(3) 繼續給 zj4@localhost 賦予 select 和 insert 權限,和已有的 select 權限進行合併
- MySQL [(none)]> show grants for 'zj4'@'localhost';
- +--------------------------------------------------+
- | Grants for zj4@localhost |
- +--------------------------------------------------+
- | GRANT SELECT, INSERT ON *.* TO 'zj4'@'localhost' |
- +--------------------------------------------------+
- 1 row in set (0.00 sec)
revoke 語句能夠回收已經賦予的權限,對於上面的例子,這裏決定要收回 zj4@localhost 上的 insert 和 select 權限:
- MySQL [(none)]> revoke select,insert on *.* from zj4@localhost;
- Query OK, 0 rows affected, 1 warning (0.00 sec)
-
- MySQL [(none)]> show grants for zj4@localhost;
- +-----------------------------------------+
- | Grants for zj4@localhost |
- +-----------------------------------------+
- | GRANT USAGE ON *.* TO 'zj4'@'localhost' |
- +-----------------------------------------+
- 1 row in set (0.00 sec)
usage 權限不能被回收,也就是說,revoke 用戶並不能刪除用戶。
4. 修改帳號密碼
(1) 能夠用 mysqladmin 命令在命令行指定密碼。
- shell> mysqladmin -u user_name -h host_name password "123456"
(2) 執行 set password 語句。
- mysql> set password for 'username'@'%' = password('pwd');
若是是更改本身的密碼,能夠省略 for 語句
- mysql> set password=password('pwd');
(3) 能夠在全局級別使用 grant usage 語句(在「.」)來指定某個帳戶的密碼而不影響帳戶當前的權限。
- mysql> grant usage on *.* to 'username'@'%' identified by 'pwd';
5. 刪除帳號
要完全的刪除帳號,可使用 drop user :
- drop user zj@localhost;
6. 帳號資源限制
建立 MySQL 帳號時,還有一類選項稱爲帳號資源限制,這類選項的做用是限制每一個帳號實際具備的資源限制,這裏的「資源」主要包括:
- max_queries_per_hour count : 單個帳號每小時執行的查詢次數
- max_upodates_per_hour count : 單個帳號每小時執行的更新次數
- max_connections_per_hour count : 單個帳號每小時鏈接服務器的次數
- max_user_connections count : 單個帳號併發鏈接服務器的次數