MySQL安全性指引(3)
2.4
不用GRANT設定使用者
如果你有一個早於3.22.11的MySQL版本,你不能使用GRANT(或REVOKE)語句來設定使用者及其存取權限,但你可以直接修改授權表的內容。如果你理解GRANT語句如何修改授權表,這很容易。那你透過手工發出INSERT語句就能自己做同樣的事情。
當你發出一條GRANT語句時,你指定一個使用者名稱和主機名,可能還有口令。對此使用者產生一個user表記錄,並且這些值會記錄在User、Host和PassWord欄位中。如果你在GRANT語句中指定全域權限,這些權限會記錄在記錄的權限列中。其中要留神的是GRANT語句為你加密口令,而INSERT不是,你需要在INSERT中使用PASSWORD()函數加密口令。
如果你指定資料庫層級權限,使用者名稱和主機名稱被記錄在db表的User和Host欄位。你為其授權的資料庫記錄在Db列中,你授予的權限記錄在權限列中。
對於表級和列級權限,效果是類似的。在tables_PRiv和columns_priv表中建立記錄以記錄使用者名稱、主機名稱和資料庫,以及相關的表和欄位。授予的權限記錄在權限列中。
如果你還記得前面的介紹,你應該可以即使不用GRANT語句也能做GRANT做的事情。記得當你直接修改授權表時,你會通知伺服器重載授權表,否則他不知道你的改變。你可以執行一個mysqladmin
flush-privileges或mysqladmin
reload指令強迫一個重載。如果你忘記做這個,你會疑惑為什麼伺服器不做你想做的事情。
下列GRANT語句建立一個擁有所有權的超級使用者。包括授權給別人的能力:
GRANT
ALL ON *.* TO anyname@localhost IDENTIFIED BY "passwd"
WITH GRANT
OPTION
該語句會在user表中為anyname@localhost建立一個記錄,開啟所有權限,因為這裡是超級使用者(全域)權限儲存的地方,要用INSERT語句做同樣的事情,語句是:
INSERT INTO
user VALUES("localhost","anyname",PASSWORD("passwd"),
"Y","Y","Y","Y","Y","Y","Y","Y" ,"Y","Y","Y","Y","Y","Y")
你可能發現它不工作,這要看你的MySQL版本。授權表的結構已經改變而且你在你的user表可能沒有14個權限列。使用SHOW
COLUMNS找出你的授權表包含的每個權限列,並相應地調整你的INSERT語句。 下列GRANT語句也會建立一個擁有超級用戶身分的用戶,但只有單一的權限:
GRANT RELOAD ON *.* TO flush@localhost IDENTIFIED BY
"flushpass"
本例的INSERT語句比前一個簡單,它很容易列出列名並且只指定一個權限列。所有其它列將設定為缺省的"N":
INSERT INTO user (Host,Password,Reload)
VALUES("localhost","flush",PASSWORD("flushpass"),"Y")
資料庫級權限用一個ON
db_name.*子句而不是ON *.*進行授權:
GRANT ALL ON sample.* TO boris@localhost
IDENTIFIED BY
"ruby"
這些權限不是全域的,所以它們不會儲存在user表中,我們仍然需要在user表中建立一條記錄(使得用戶能連接),但我們也需要建立一個db表記錄記錄資料庫集權限:
INSERT INTO user (Host,User,Password)
VALUES("localhost","boris",PASSWORD("ruby"))
INSERT INTO db
VALUES("localhost","sample_db","boris","Y","Y","Y","Y","Y","Y","N","Y","Y", "Y")
"N"列是為GRANT權限;對末尾的一個資料庫級具有WITH
GRANT
OPTION的GRANT語句,你要設定該列為"Y"。
要設定表級或列級權限,你對tables_priv或columns_priv使用INSERT語句。當然,如果你沒有GRANT語句,你將沒有這些表,因為它們在MySQL中同時出現。如果你確實有這些表並且為了某些原因想要手動操作它們,要知道你不能用單獨的列啟用權限。
你設定tables_priv.Table_priv或columns_priv.Column_priv欄來設定包含你想啟用的權限值。例如,要對一個表格啟用SELECT和INSERT權限,你要在相關的tables_priv的記錄中設定Table_priv為"Select,Insert"。
如果你想對一個擁有MySQL帳號的使用者修改權限,使用UPDATE而不是INSERT,不管你增加或撤銷權限都是這樣。要完全刪除一個用戶,從用戶使用的每個表中刪除記錄。
如果你願意避免發一個查詢來直接修改全權表,你可以看MySQL自帶的mysqlaccess和mysql_setpermissions腳本。
附錄1
小測驗
在你剛剛新安裝了一個MySQL伺服器,在你增加了一個允許連接MySQL的用戶,用下列語句:
GRANT ALL ON
samp_db.* TO fred@*.snake.net IDENTIFIED
"cocoa"
而fred碰巧在伺服器主機上有個帳號,所以他試著連接伺服器:
%mysql -u fred -pcocoa
samp_db
ERROR 1045: Access denied for user: 'fred@localhost' (Using password:
YES)
為什麼?
原因是:
先考慮一下mysql_install_db如何建立初始權限表和伺服器如何使用user表記錄來匹配客戶連線。當你用mysql_install_db初始化你的資料庫時,它會建立類似這樣的user表:
Host
User
localhost
pit.snake.net
localhost
pit.snake.net
root
root
頭兩個記錄允許root指定localhost或主機名稱連接本地伺服器,後兩個允許匿名用戶從本地連接。當增加fred用戶後,
Host
User
localhost
pit.snake.net
localhost
pit.snake.net
%.snake.net
root
root
fred
在伺服器啟動時,它會讀取記錄並排序它們(先按主機,然後按主機上的使用者),越具體越排在前面:
Host User
localhost
localhost
pit.snake.net
pit.snake.net
%.snake.net
root
root
fred
有localhost的兩個記錄排在一起,而對root的記錄排在第一,因為它比空值更具體。 pit.snake.net的記錄也類似。所有這些都是沒有任何通配符的字面上的Host值,所以它們排在對fred記錄的前面,特別是匿名用戶排在fred之前。
結果是在fred試圖從localhost連接時,Host列中的一個空用戶名的記錄在包含%.snake.net的記錄前匹配。該記錄的口令是空的,因為缺省的匿名用戶沒有口令。因為在fred連線時指定了一個口令,由一個錯配且連線失敗。
這裡要記住的是,雖然用通配符指定使用者可以從其連接的主機是很方便。但你從本機連線時會有問題,只要你在table表中保留匿名使用者記錄。
一般地,建議你刪除匿名使用者記錄:
mysql>
DELETE FROM user WHERE
User="";
更進一步,同時刪除其他授權表中的任何匿名用戶,有User列的表有db、tables_priv和columns_priv。
附錄2
讓一個新的MySQL安裝更安全
在你自己安裝了一個新的MySQL伺服器後,你需要為MySQL的root用戶指定一個目錄(缺省無口令),否則如果你忘記這點,你將你的MySQL處於極不安全的狀態(至少在一段時間內)。
在Unix(linux)上,在依照手冊的指令安裝好MySQL後,你必須執行mysql_install_db腳本建立包含授權表的mysql資料庫和初始權限。在Windows上,執行分發中的Setup程式初始化資料目錄和mysql資料庫。假定伺服器也在運作。
當你第一次在機器上安裝MySQL時,mysql資料庫中的授權表是這樣初始化的:
你可以從本機(localhost)上以root連線而不指定口令。 root使用者擁有所有權限(包括管理權限)並可做任何事情。 (順便說明,MySQL超級用戶與Unix超級用戶有相同的名字,他們彼此毫無關係。)
匿名存取被授予使用者可從本地連接名為test和任何名字以test_開始的資料庫。匿名使用者可對資料庫做任何事情,但無管理權限。
從本機多伺服器的連線是允許的,不管連線的使用者使用一個localhost主機名稱或真實主機名稱。如:
% mysql -h
localhost test
% mysql -h pit.snake.net
test
你以root連接MySQL甚至不指定口令的事實只是意味著初始安裝不安全,所以作為管理員的你首先要做的應該是設定root口令,然後根據你設定口令使用的方法,你也可以告訴伺服器重載授權表是它知道這個改變。 (在伺服器啟動時,它重載表到記憶體中而可能不知道你已經修改了它們。)
對MySQL
3.22以上版本,你可以用mysqladmin設定口令:
% mysqladmin -u root password
yourpassword
對於MySQL的任何版本,你可以用mysql程式並直接修改mysql資料庫中的user授權表:
%
mysql -u root mysql
mysql>UPDATE user SET
password=PASSWORD("yourpassword") WHERE
User="root";
如果你有MySQL的舊版本,使用mysql和UPDATE。
在你設定完口令後,透過執行下列指令檢查你是否需要告訴伺服器重載授權表:
%
mysqladmin -u root status
如果伺服器仍然讓你以root而不指定口令而連接伺服器,重載授權表:
%
mysqladmin -u root
reload
在你設定了root的口令後(並且如果需要重載了授權表),你將需要在任何時候以root連接伺服器時指定口令。
以上就是MySQL安全性指南(3)(轉)的內容,更多相關文章請關注PHP中文網(www.php.cn)!