- LAMP網站開發黃金組合Linux+Apache+MySQL+PHP
- 楊明華等編著
- 3020字
- 2018-12-29 19:23:43
6.6 MySQL的外部安全性
上一節介紹了如何保證MySQL數據文件的安全,本節繼續討論另一個方面:通過網絡訪問數據庫的安全性,也稱為MySQL的外部安全性。
6.6.1 通過授權表確認訪客
MySQL授權表用于控制客戶機對服務器的訪問權限。MySQL允許多種方法來設置授權表,授權機制非常靈活。如圖6-5所示。

圖6-5 MySQL授權表確認訪客機制
通常,可以通過GRANT和REVOKE語句來實現用戶權限控制。另外,在了解了授權表的結構,以及如何使用它們控制權限后,也可以通過直接修改授權表來實現權限控制,還可以進一步在檢查表時診斷權限的問題。
授權表在MySQL數據庫中,主要包括user、db、host、table_priv和columns_priv五個表,在首次安裝MySQL的時候初始化,通過下面命令可以查看到這些表:
mysql> use mysql mysql> show tables; +---------------------- + |Tables_in_mysql | +---------------------- + |columns_priv | |db | |func | |host | |tables_priv | |user | +---------------------- +
其中,func表管理MySQL可以執行的函數庫,與權限系統無關。
其余5個表都與MySQL的外部安全性相關。當一個用戶提交GRANT語句時,MySQL會在user表中為該用戶創建一條用戶記錄。如果語句指定全局權限(管理權限或適用于所有數據庫的權限),也將記錄在user表中;如果指定數據庫、表和列級權限,則會分別記錄在db、tables_priv和columns_priv表中。
6.6.2 檢查訪問用戶合法性
user表記錄所有合法用戶,以及他們的口令和全局權限信息。注意:在user表啟用的權限都是全局權限,可以在所有的數據庫上進行操作。例如,如果在user表中為一個用戶啟用了SELECT權限,那么該用戶可以從任何表中查詢任何記錄。
user表的結構如表6-3所示。
表6-3 user授權表

說明,在user表及下面所介紹的db和host表中,每個數據庫(表)的操作權限都作為單獨的列,用ENUM(“N”、“Y”)類型聲明,所有權限的默認值為“N”(off)。
下面詳細介紹user表的幾個列,這些列的含義及使用情況可能在下面所介紹的幾個表中都通用:
1.Host
該列可以是一個主機名或一個IP地址。特別地,localhost代表本地主機,僅當使用localhost而不是主機名連接時才匹配。例如,假定本地主機名為host.domian.net,且在user表中有兩項,一個Host值為localhost,而另一個為host.domian.net。帶有localhost值的項僅當連接到localhost時才進行匹配,而另一項僅當連接到host.domian.net時才匹配。簡言之,在Host中,localhost不等于主機名。
可以用通配符指定Host的值,可以使用SQL中的‘%’和‘_’,并與SQL查詢中具有相同的含義。
2.User
user表示用戶名,必須是常量或空值,空值表示任何用戶。user列不支持通配符。在user表中,當MySQL找到與登錄用戶相配的項后,發現包含user為空值時,這個用戶將被認為是匿名用戶。
3.Password
Password代表用戶口令,其值可以為空,不允許通配符,并以加密形式存儲。空口令并非與任何口令相配,而是表示用戶不必指定口令。
GRANT語句和mysqladmin password命令自動對口令進行加密,但使用INSERT、REPLACE、UPDATE或SETPASSWORD這樣的語句來直接操作權限表時,則必須用PASSWORD(“NEW_PASSWORD”)來對輸入的口令進行加密,而不能簡單地使用“new_password”。
例如,下面使用GRANT命令創建賬戶super_user、db_user和tbl_user,分別在全局級、數據庫級,以及表級上賦予查詢數據的權利:
mysql> GRANT SELECT ON *.* TO super_user@localhost IDENTIFIED BY "my_password"; mysql> GRANT SELECT ON student_course.* TO db_user@localhost IDENTIFIED BY "my_password"; mysql> GRANT SELECT ON student_course.students TO tbl_user @localhost IDENTIFIED BY "my_password";
user表中相應添加的記錄:
mysql>SELECT Host, User, password, Select_priv, Insert_priv FROM user WHERE user = 'super_user' OR user ='db_user' OR user = 'tbl_user'; +------------------- +------------------- +-------------------------- +-------------------+------------------- + |Host |User |password | Select_priv |Insert_priv | +------------------- +------------------- +-------------------------- +-------------------+------------------- + |localhost |super_user |4bec313a33935fce |Y |N | |localhost |db_user |4bec313a33935fce |N |N | |localhost |tbl_user |4bec313a33935fce |N |N | +------------------- +------------------- +-------------------------- +-------------------+------------------- +
可以發現,對于db_user和tbl_user,其Select_priv值仍舊是N,而不是Y。這是因為,所授的權限限定于某個數據庫或某個表,而user表中記錄控制所有數據庫的全局權限。User表只有同下面所介紹的授權表一起,才能實現庫級和表級權限。
★ 注意 ★
授權表中的記錄是區分大小寫的,如果把“super_user”寫成了“Super_user”,則不會找到用戶信息。
6.6.3 控制庫級訪問
MySQL使用db授權表控制數據庫級別的訪問權限。db表列出所有的數據庫以及用戶擁有訪問這些數據庫的權限,并且指定的權限適用于數據庫中所有的表。db表的內容如表6-4所示。
表6-4 db授權表

其中,數據庫(表)操作權限同user表的內容相同,指定來自客戶端Host的用戶User在Db數據庫上所擁有的權限。
db表示所要控制權限的數據庫,在columns_priv和tables_priv表中,db值必須是直接的數據庫名,不允許通配符和空值。而在db和host表中,Db值可以用間接量,通過通配符‘%’或‘_’來指定%值或空值與任何數據庫相配。
同樣,在執行了上面的授權語句:
mysql> GRANT SELECT ON *.* TO super_user@localhost IDENTIFIED BY "my_password"; mysql> GRANT SELECT ON student_course.* TO db_user@localhost IDENTIFIED BY "my_password"; mysql> GRANT SELECT ON student_course.students TO tbl_user @localhost IDENTIFIED BY "my_password";
后,db表中所添加的相應信息:
mysql> SELECT Host, db, User, Select_priv, Insert_priv FROM db WHERE user = 'super_user' OR user ='db_user' OR user = 'tbl_user'; +------------------- +------------------- +------------------- +-------------------+------------------- + |Host |db | User |Select_priv |Insert_priv | +------------------- +------------------- +------------------- +-------------------+------------------- + |localhost |student_course| db_user |Y |N | +------------------- +------------------- +------------------- +-------------------+------------------- +
結果顯示了具有庫級權限的用戶db_user的權限信息,與之對應的用戶有:
(1)對于超級用戶suer_user,因為其查詢功能凌駕于所有數據庫之上,在db表中并沒有其信息;
(2)對于表級用戶tbl_user,其查詢功能僅僅限于某個表,其信息也未在db表中表現,而是需要使用到下面的table_priv表。
除db表之外,還有一個授權表host表,可以與db表結合使用,在更細的級別上控制對特定主機數據庫的訪問權限。但是,host表不受GRANT和REVOKE語句的影響,因此很少使用。
6.6.4 控制表級訪問
table_priv表指定用戶表級操作的權限,在其中所指定的權限適用于某個表。其結構信息如表6-5所示。
表6-5 table_priv授權表

這些列中的值必須是直接的表名或列名,不允許通配符和空白值。
對于表中的某些列,MySQL區分大小寫,另一些則不然。但Table_name列始終是區分大小寫的,即使SQL查詢中的表名是取決于服務器運行的文件系統,MySQL也區分其大小(在UNIX文件系統區分大小寫,而在Windows中不區分)。
在執行了授權語句:
mysql> GRANT SELECT ON student_course.students TO tbl_user @localhost IDENTIFIED BY "my_password";
后,tables_priv表中所添加的相應信息為:
mysql>SELECT * FROM tables_priv WHERE user='tbl_user'; Host Db User Table_name Grantor Timestamp Table_priv Column_priv Local Student tbl students ODBC@l 2006030214 Select Host _course _user ocalhost 3
可以看到,tbl_user用戶在數據庫student_course的students表上具有select權限,由于沒有進一步限定其權限于某一列上,因此column_priv為空。
6.6.5 控制列級訪問
columns_priv表指定用戶列級的操作權限,在這里所指定的權限適用于表中特定的列。其屬性信息如tables_priv基本一致,不同之處在于沒有table_priv屬性。
例如,使用下面的GRANT命令創建一個col_user,并指定其在students表的sname列上具有查詢的權限:
mysql> GRANT SELECT(sname) ON student_course.students TO col_user @localhost;
columns_priv表的結果如:
mysql> SELECT * FROM columns_priv WHERE user = 'col_user'; +------------ +---------------+---------+-------------------+-------------------- +------------------- +---------------+ |Host |Db |User |Table_name |Column_name|Timestamp |Column_priv| +------------ +---------------+---------+-------------------+-------------------- +------------------- +---------------+ |localhost |student_course |col_user |students |sname |20060302153856 |Select| +------------ +---------------+---------+-------------------+-------------------- +------------------- +---------------+
6.6.6 一個應用示例
本節將通過示例,來說明如何手動使用授權表來完成GRANT和REVOKE所實現的用戶及權限管理,實現思路如下。
(1)當提交GRANT語句時,需要指定用戶名和主機號,可能還指定口令。此時,user表建立該用戶,這些登錄信息分別記錄在其User、Host和Password列中,通過INSERT語句來實現。
(2)如果GRANT指定了數據庫級的權限,用戶名和主機名將記錄在db表項的User和Host列中,所授權的數據庫記錄在Db列中,而所授予的權限記錄在權限列中,同樣可以使用INSERT語句來實現。表級和列級權限是類似的。
(3)當使用UPDATE直接修改授權表時,需要重新加載授權表,否則MySQL將不會知道權限的變化。可以通過執行mysqladmin flush-privileges或mysqladmin reload命令重新加載。如果忘記這步操作,服務器將不會刷新授權表。
示例1:建立超級用戶
下面的grant語句將創建一個擁有全部權限的超級用戶,其中包括向其他用戶授權的能力:
GRANT ALL ON *.* TO super_user@localhost IDENTIFIED BY "my_password" WITH GRANT OPTION
該語句將創建user表的super_user@localhost的項,并開啟所有的操作權限。用INSERT進行同樣工作的語句是:
INSERT INTO user VALUES
('localhost','super_user',PASSWORD('my_password')),'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y',' Y','Y','Y','Y')
這個INSERT語句可不好寫,這也就是GRANT語句存在的原因之一。
示例2:建立數據庫級用戶
下面的grant語句將創建一個擁有在數據庫student_course上全部權限的用戶,包括向其他用戶授權的能力:
GRANT ALL ON student_course.* TO db_user@localhost IDENTIFIED BY "my_password" WITH GRANT OPTION
這些權限不是全局的,因此不能存儲在user表中。但仍需要在user表中創建一項以保存該用戶的登錄信息,同時還需要創建一個db表中的項來記錄數據庫級的權限:
INSERT INTO user(host,user,password) VALUES('localhost','db_user',PASSWORD('my_password')); INSERT INTO db VALUES ('localhost','student_course','db_user','Y','Y','Y','Y','Y','Y','N','Y','Y','Y')
這個INSERT語句也不好寫。
為了設置表級或列級權限,需要對tables_priv或columns_priv表使用INSERT語句即可,在些不再贅述。如果要想修改某個已經存在的用戶的權限,無論是增加還是取消權限,應使用UPDATE而非INSERT語句。為刪除一個用戶,使用DELETE從該用戶所在的每個授權表中刪除其值。
- 機器學習實戰:基于Sophon平臺的機器學習理論與實踐
- 亮劍.NET:.NET深入體驗與實戰精要
- 構建高質量的C#代碼
- 輕松學C語言
- Mastering Spark for Data Science
- Div+CSS 3.0網頁布局案例精粹
- 城市道路交通主動控制技術
- 現代機械運動控制技術
- Windows環境下32位匯編語言程序設計
- Machine Learning with Apache Spark Quick Start Guide
- 網絡布線與小型局域網搭建
- Grome Terrain Modeling with Ogre3D,UDK,and Unity3D
- 突破,Objective-C開發速學手冊
- 筆記本電腦維修90個精選實例
- 傳感器與自動檢測