MySQL用戶帳號和信息存儲在名爲 mysql
的數據庫中。通常不須要直接訪問 mysql
數據庫和表,但有時須要直接訪問。例如,查看數據庫全部用戶帳號列表時。mysql
USE mysql; SELECT DISTINCT(`user`) FROM user;
mysql
有一個名爲 user
的表,它包含全部用戶帳號。 user
表有一個名爲 user
的字段,它存儲帳號名。mysql
,查看 user
表中的 user
列,因爲有些帳號會分多行記錄,DISTINCT
用於去重。mysql> USE mysql; Database changed mysql> SELECT DISTINCT(`user`) FROM user; +-----------+ | user | +-----------+ | root | | mysql.sys | +-----------+ 2 rows in set (0.07 sec)
root
和 mysql.sys
兩個帳號。可使用 CREATE USER
語句建立一個新用戶帳號。sql
CREATE USER account_name IDENTIFIED BY 'password';
IDENTIFIED BY
用於設定密碼,MySQL 會先將密碼進行加密,在將其保存到 user 表。使用GRANT
或INSERT GRANT
語句也能夠建立用戶帳號,但通常來講CREATE USER
是最清楚和最簡單的句子。
使用CREATE USER
建立用戶帳號,必須接着分配訪問權限。新建立的用戶帳號沒有訪問權限。它們能登陸MySQL,但不能看到數據,不能執行任何數據庫操做。
可使用GRANT
語句建立用戶帳號並受權,該語句會在文章受權部分講解。用於帳號都存儲在數據庫
mysql
的user
表中,理論上也能夠經過直接插入行到 user 表來增長用戶,不過爲安全起見,通常不建議這樣作。MySQL用來存儲用戶帳號信息的表(以及表模式等)極爲重要,對它們的任何毀壞均可能嚴重地傷害到MySQL服務器。所以,最好不要直接修改數據庫mysql
中表的數據。數據庫
zhangsan
密碼爲 123456
mysql> CREATE USER zhangsan IDENTIFIED BY '123456'; Query OK, 0 rows affected (0.06 sec) mysql> SELECT DISTINCT(`user`) FROM user; +-----------+ | user | +-----------+ | root | | zhangsan | | mysql.sys | +-----------+ 3 rows in set (0.07 sec)
[vagrant~] ]$mysql -uzhangsan -p Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. ...... Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql>
注意,不要直接在命令行中輸入密碼,由於命令行的輸入歷史都會被記錄下來,很贊成致使密碼泄露。
可使用 RENAME USER
語句爲帳號重命名。安全
RENAME USER old_name TO new_name;
僅 MySQL 5及以後的版本支持RENAME USER
。
MySQL 5之前的版本,要重命名一個用戶,可以使用 UPDATE 直接更新 user 表( 謹慎操做)。
zhangsan
重命名爲 lisi
mysql> RENAME USER zhangsan TO lisi; Query OK, 0 rows affected (0.34 sec) mysql> SELECT DISTINCT(`user`) FROM user; +-----------+ | user | +-----------+ | lisi | | root | | mysql.sys | +-----------+ 3 rows in set (0.08 sec)
可使用 SET PASSWORD
語句重置帳號密碼。服務器
SET PASSWORD FOR account_name = Password('password');
使用
SET PASSWORD
重置帳號密碼。新密碼必須經過 Password() 函數進行加密。
當不指定用戶名時, SET PASSWORD
會重置當前登陸用戶的密碼。架構
SET PASSWORD = Password('password');
lisi
的密碼改成 abcdef
mysql> SET PASSWORD FOR lisi = Password('abcdef'); Query OK, 0 rows affected (0.03 sec)
[vagrant~] ]$mysql -ulisi -p Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. ...... Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql>
mysql> SET PASSWORD = Password('10086'); Query OK, 0 rows affected (0.00 sec)
可使用 DROP USER
語句刪除帳號(以及相關的權限)。函數
DROP USER account_name;
MySQL 5及以後的版本,DROP USER
刪除用戶帳號時會自動刪除全部相關的帳號權限。
在MySQL 5之前,DROP USER
只能用來刪除用戶帳號,不能刪除相關的權限。所以,若是使用舊版本的MySQL,須要先用REVOKE
刪除與帳號相關的權限,而後再用DROP USER
刪除帳號。
lisi
mysql> DROP USER lisi; Query OK, 0 rows affected (0.00 sec) mysql> SELECT DISTINCT(`user`) FROM user; +-----------+ | user | +-----------+ | root | | mysql.sys | +-----------+ 2 rows in set (0.07 sec)
MySQL服務器的安全基礎是:用戶應該對他們須要的數據具備適當的訪問權,既不能多也不能少。性能
考慮如下狀況:加密
這些都只是例子,但有助於說明一個重要的事實,即你須要給用戶提供他們所需的訪問權,且僅提供他們所需的訪問權。這就是所謂的訪問控制,管理訪問控制須要建立和管理用戶帳號。spa
MySQL 會默認建立一個名爲 root
的用戶帳號,它對整個 MySQL 服務器具備徹底的控制。不過在平常的 MySQL 操做中(特別是生產環境),決不能使用 root 帳號登陸。應該建立一系列的帳號,有的用於管理,有的供用戶使用,有的供開發人員使用,等等。應該嚴肅對待 root 帳號的使用,僅在絕對須要時使用它。
經過保證用戶不能執行他們不該該執行的語句,訪問控制有助於避免這些狀況的發生。
SHOW GRANTS[ FOR account_name][@host];
FOR
指定用戶時,默認是查看本身的帳號權限。SHOW GRANTS FOR account_name@host
時,可查看指定帳號在指定主機下的權限。能夠在數據庫 mysql
中使用 SELECT user,host FROM user;
查看帳號的主機列表。mysql> USE mysql; Database changed mysql> SELECT user,host FROM user; +-----------+-----------+ | user | host | +-----------+-----------+ | root | % | | mysql.sys | localhost | | root | localhost | +-----------+-----------+ 3 rows in set (0.06 sec)
host字段: 表示帳號能夠在哪些主機或IP地址登陸。%
表明任何IP地址均可以登陸(生產環境中這樣作是很是危險的),localhost
表示只容許本機登陸。
將host
設爲%
,就表明任何IP地址均可以訪問該數據庫,在生產環境中這樣作是很是危險的。
也可使用其餘手段來提升數據庫安全性:好比設置防火牆、iptable;若是是雲平臺的數據庫還能夠經過安全組等方式提升安全性。
mysql> SHOW GRANTS; +-------------------------------------------------------------+ | Grants for root@% | +-------------------------------------------------------------+ | GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION | +-------------------------------------------------------------+ 1 row in set (0.00 sec)
mysql> SHOW GRANTS FOR root@localhost; +---------------------------------------------------------------------+ | Grants for root@localhost | +---------------------------------------------------------------------+ | GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION | +---------------------------------------------------------------------+ 1 row in set (0.00 sec)
輸出結果顯示帳號root
有一個權限ALL PRIVILEGES ON *.*
,表示root
帳號能夠操做全部數據庫和全部表。
CREATE USER
建立一個帳號 zhangsan
,並查看 zhangsan
的帳號權限。mysql> CREATE USER zhangsan IDENTIFIED BY '123456'; Query OK, 0 rows affected (0.00 sec) mysql> SHOW GRANTS FOR zhangsan; +---------------------------------------------------------------------------------------------------------+ | Grants for zhangsan@% | +---------------------------------------------------------------------------------------------------------+ | GRANT USAGE ON *.* TO 'zhangsan'@'%' IDENTIFIED BY PASSWORD '*6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9' | +---------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec)
輸出結果顯示帳號zhangsan
有一個權限USAGE ON *.*
。 USAGE 表示根本沒有權限,因此,此結果表示zhangsan
對任意數據庫和任意表上對任何東西都沒有操做權限。
zhangsan
,並嘗試進入 test
數據庫,被拒絕。[vagrant~] ]$mysql -uzhangsan -p Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. ...... Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> use test; ERROR 1044 (42000): Access denied for user 'zhangsan'@'%' to database 'test'
使用
CREATE USER
建立的用戶帳號默認沒有訪問權限。它們能登陸MySQL,但不能看到數據,不能執行任何數據庫操做。
可使用 GRANT
語句爲帳號設置權限。至少給出如下信息:
GRANT <權限> ON <數據庫名>.<表名> TO <帳戶名>;
zhangsan
賦予在 test
數據庫內的任意表查找和添加數據的權限。mysql> GRANT SELECT, INSERT ON test.* TO 'zhangsan'; Query OK, 0 rows affected (0.00 sec) mysql> FLUSH PRIVILEGES; Query OK, 0 rows affected (0.00 sec) mysql> SHOW GRANTS FOR zhangsan; +---------------------------------------------------------------------------------------------------------+ | Grants for zhangsan@% | +---------------------------------------------------------------------------------------------------------+ | GRANT USAGE ON *.* TO 'zhangsan'@'%' IDENTIFIED BY PASSWORD '*6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9' | | GRANT SELECT, INSERT ON `test`.* TO 'zhangsan'@'%' | +---------------------------------------------------------------------------------------------------------+ 2 rows in set (0.00 sec)
受權後必須FLUSH PRIVILEGES,不然沒法當即生效。
zhangsan
,能夠成功進入到數據庫 test
,在 user
表中插入一條數據,並從 user
表查找數據。mysql> USE test; Database changed mysql> SHOW TABLES; +----------------+ | Tables_in_test | +----------------+ | user | +----------------+ 1 row in set (0.00 sec) mysql> INSERT INTO user (username, email) VALUES ('zhangsan', 'zhangsan@gmail.com'); Query OK, 1 row affected, 1 warning (0.00 sec) mysql> SELECT * FROM user; +----+----------+--------------------+----------+--------+------------+ | id | username | email | password | status | created_at | +----+----------+--------------------+----------+--------+------------+ | 1 | zhangsan | zhangsan@gmail.com | NULL | 0 | 0 | +----+----------+--------------------+----------+--------+------------+ 1 row in set (0.00 sec)
zhangsan
想要使用 UPDATE
和 DELETE
命令修改和刪除這條數據時,被提示沒有權限。mysql> UPDATE user SET email='zhangsanfeng@gmail.com' WHERE username='zhangsan'; ERROR 1142 (42000): UPDATE command denied to user 'zhangsan'@'localhost' for table 'user' mysql> DELETE FROM user WHERE username='zhangsan'; ERROR 1142 (42000): DELETE command denied to user 'zhangsan'@'localhost' for table 'user'
GRANT <權限> ON <數據庫名>.<表名> TO <帳戶名>@<主機名/IP> IDENTIFIED BY '<密碼>'[ WITH GRANT OPTION];
WITH GRANT OPTION
用於賦予帳號使用GRANT
和REVOKE
命令的權限,用於給帳號受權和取消受權。此權限級別極高,通常只會將此權限授予數據庫管理員帳號。
lisi
密碼爲 abcdef
,在任何IP地址均可以登陸,同時賦予 lisi
在 test
數據庫內的任意表數據的增刪改查權限。mysql> GRANT SELECT, INSERT, UPDATE, DELETE ON test.* TO 'lisi'@'%' IDENTIFIED BY 'abcdef'; Query OK, 0 rows affected (0.00 sec)
將host
設爲%
,就表明任何IP地址均可以訪問該數據庫,在生產環境中這樣作是很是危險的。
也可使用其餘手段來提升數據庫安全性:好比設置防火牆、iptable;若是是雲平臺的數據庫還能夠經過安全組等方式提升安全性。
lisi
,能夠成功進入到數據庫 test
,並對 user
表數據進行增刪改查。[vagrant~] ]$mysql -ulisi -p Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. ...... Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> use test; Database changed mysql> INSERT INTO user (username, email) VALUES ('lisi', 'lisi@gmail.com'); Query OK, 1 row affected, 1 warning (0.01 sec) mysql> SELECT * FROM user; +----+----------+--------------------+----------+--------+------------+ | id | username | email | password | status | created_at | +----+----------+--------------------+----------+--------+------------+ | 1 | zhangsan | zhangsan@gmail.com | NULL | 0 | 0 | | 2 | lisi | lisi@gmail.com | NULL | 0 | 0 | +----+----------+--------------------+----------+--------+------------+ 2 rows in set (0.00 sec) mysql> UPDATE user SET email='lisiguang@gmail.com' WHERE username='lisi'; Query OK, 1 row affected (0.01 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> DELETE FROM user WHERE username='zhangsan'; Query OK, 1 row affected (0.00 sec) mysql> SELECT * FROM user; +----+----------+---------------------+----------+--------+------------+ | id | username | email | password | status | created_at | +----+----------+---------------------+----------+--------+------------+ | 2 | lisi | lisiguang@gmail.com | NULL | 0 | 0 | +----+----------+---------------------+----------+--------+------------+ 1 row in set (0.00 sec)
可使用 REVOKE
語句撤銷帳號指定權限。REVOKE
是 GRANT
的反操做。
REVOKE <權限> ON <數據庫名>.<表名> FROM <帳戶名>;
lisi
的 DELETE 權限。mysql> REVOKE DELETE ON test.* FROM lisi; Query OK, 0 rows affected (0.00 sec) mysql> FLUSH PRIVILEGES; Query OK, 0 rows affected (0.00 sec) mysql> SHOW GRANTS FOR lisi; +-----------------------------------------------------------------------------------------------------+ | Grants for lisi@% | +-----------------------------------------------------------------------------------------------------+ | GRANT USAGE ON *.* TO 'lisi'@'%' IDENTIFIED BY PASSWORD '*C2D24DCA38E9E862098B85BF0AB35CAA52803797' | | GRANT SELECT, INSERT, UPDATE ON `test`.* TO 'lisi'@'%' | +-----------------------------------------------------------------------------------------------------+ 2 rows in set (0.04 sec)
lisi
想要使用 DELETE
命令刪除數據時,被提示沒有權限。mysql> DELETE FROM user WHERE username='lisi'; ERROR 1142 (42000): DELETE command denied to user 'lisi'@'localhost' for table 'user'
GRANT
和 REVOKE
可在幾個層次上控制訪問權限:
GRANT ALL
和 REVOKE ALL
;ON database.*
;ON database.table
;權 限 | 說 明 |
---|---|
ALL | 除 GRANT OPTION 外的全部權限 |
ALTER | 使用 ALTER TABLE |
ALTER ROUTINE | 使用 ALTER PROCEDURE 和 DROP PROCEDURE |
CREATE | 使用 CREATE TABLE |
CREATE ROUTINE | 使用 CREATE PROCEDURE |
CREATE TEMPORARY TABLES | 使用 CREATE TEMPORARY TABLE |
CREATE USER | 使用 CREATE USER 、DROP USER 、RENAME USER 和 REVOKE ALL PRIVILEGES |
CREATE VIEW | 使用 CREATE VIEW |
DELETE | 使用 DELETE |
DROP | 使用 DROP TABLE |
EXECUTE | 使用 CALL 和存儲過程 |
FILE | 使用 SELECT INTO OUTFILE 和 LOAD DATA INFILE |
GRANT OPTION | 使用 GRANT 和 REVOKE |
INDEX | 使用 CREATE INDEX 和 DROP INDEX |
INSERT | 使用 INSERT |
LOCK TABLES | 使用 LOCK TABLES |
PROCESS | 使用 SHOW FULL PROCESSLIST |
RELOAD | 使用 FLUSH |
REPLICATION CLIENT | 服務器位置的訪問 |
REPLICATION SLAVE | 由複製從屬使用 |
SELECT | 使用 SELECT |
SHOW DATABASES | 使用 SHOW DATABASES |
SHOW VIEW | 使用 SHOW CREATE VIEW |
SHUTDOWN | 使用 mysqladmin shutdown (用來關閉MySQL) |
SUPER | 使用 CHANGE MASTER 、KILL 、LOGS 、PURGE 、MASTER 和 SET GLOBAL 。還容許 mysqladmin 調試登陸 |
UPDATE | 使用 UPDATE |
USAGE | 無訪問權限 |
最後附一張《MySQL性能調優與架構設計》中的權限控制流程圖。
以 SELECT id,name FROM test.t4 where status = 'deleted';
爲例。