塗抹MySQL--第5章 MySQL資料庫中的許可權體系 - 5.2許可權授予與回收(3)

dawn009發表於2015-06-26

5.2.3 檢視和收回使用者許可權

不管是授予還是想收回使用者的許可權,通常我們首先需要知道使用者當前都擁有什麼許可權。查詢使用者許可權可以使用SHOW GRANTS語句,SHOW GRANTS的語法比較簡單,就一行:

SHOW GRANTS [FOR user]

其中FOR user還是個可選項,用於指定要查詢的目標使用者,如果不指定的話,則預設顯示當前使用者擁有的許可權,效果等同於SHOW GRANTS FOR CURRENT_USER()

如果之前從未用過,那麼SHOW GRANTS語句顯示的結果可能會出乎意料,它返回的結果並不是某個許可權型別的關鍵字,而是授權語句。

例如,檢視使用者jss_grant@192.168.30.203都擁有哪些許可權,執行語句如下:

(system@localhost) [(none)]> show grants for jss_grant@192.168.30.203;

+-----------------------------------------------------------------------------------------------------------------------+

| Grants for jss_grant@192.168.30.203                                                                                   |

+-----------------------------------------------------------------------------------------------------------------------+

| GRANT USAGE ON *.* TO 'jss_grant'@'192.168.30.203' IDENTIFIED BY PASSWORD '*284578888014774CC4EF4C5C292F694CEDBB5457' |

| GRANT SELECT ON `jssdb`.* TO 'jss_grant'@'192.168.30.203'                                                             |

| GRANT SELECT ON `mysql`.`user` TO 'jss_grant'@'192.168.30.203'                                                        |

+-----------------------------------------------------------------------------------------------------------------------+

3 rows in set (0.00 sec)

從上述返回的結果可以看到,使用者jss_grant@192.168.30.203擁有三項個許可權:查詢mysql.user表的查詢,查詢jssdb資料庫下所有物件的許可權,以及登入MySQL資料庫的許可權。要我說,MySQL資料庫SHOW GRANTS語法最喜人之處在於,建立使用者和授權語法都列出來了。

儘管前面我已經無數次提到過,直接查詢mysql庫中的資料字典表,來修改或檢視使用者的許可權資訊,但我覺著如果是要檢視某個使用者的許可權,那麼使用SHOW GRANTS語句才是最好的方式,功能超強而且易用。

 

要收回使用者許可權,與之對應的命令是REVOKE,它的語法從定義上分為兩種:

l REVOKE priv_type [(column_list)] [, priv_type [(column_list)]] ...

    ON [object_type] priv_level FROM user [, user] ...

 

l REVOKE ALL PRIVILEGES, GRANT OPTION FROM user [, user] ...

前者用來處理指定的許可權,有很多選項,這些選項的定義與GRANT中同名選項定義一模一樣,這裡不再複述。後者功能較為獨立,可以理解成專用於清除使用者許可權。

我們先來嘗試收回jss_grant@'192.168.30.203'使用者,擁有的mysql.user表物件的select許可權,執行revoke命令如下:

(system@localhost) [(none)]> revoke select on mysql.user from jss_grant@192.168.30.203;

Query OK, 0 rows affected (0.00 sec)

 

(system@localhost) [(none)]> show grants for jss_grant@192.168.30.203;

+-----------------------------------------------------------------------------------------------------------------------+

| Grants for jss_grant@192.168.30.203                                                                                   |

+-----------------------------------------------------------------------------------------------------------------------+

| GRANT USAGE ON *.* TO 'jss_grant'@'192.168.30.203' IDENTIFIED BY PASSWORD '*284578888014774CC4EF4C5C292F694CEDBB5457' |

| GRANT SELECT ON `jssdb`.* TO 'jss_grant'@'192.168.30.203'                                                             |

+-----------------------------------------------------------------------------------------------------------------------+

2 rows in set (0.00 sec)

收回某個普通的指定許可權立竿見影。注意,我說的是普通許可權。有哪些許可權不普通呢,如果此刻你的內心浮現出這個問題,說明看書不認真啊小盆友,在前面介紹GRANT語句時就曾提到過的,比如說USAGE許可權,這個許可權使用者一經建立就會擁有,並且無法透過REVOKE 語句收回。你要不相信哪,我們們來看一看:

(system@localhost) [(none)]> revoke usage on *.* from 'jss_grant'@'192.168.30.203';

Query OK, 0 rows affected (0.00 sec)

操作提示成功,但是這是個假象,可以透過檢視jss_grant使用者擁有的許可權來驗證:

(system@localhost) [(none)]> show grants for jss_grant@192.168.30.203;

+-----------------------------------------------------------------------------------------------------------------------+

| Grants for jss_grant@192.168.30.203                                                                                   |

+-----------------------------------------------------------------------------------------------------------------------+

| GRANT USAGE ON *.* TO 'jss_grant'@'192.168.30.203' IDENTIFIED BY PASSWORD '*284578888014774CC4EF4C5C292F694CEDBB5457' |

| GRANT SELECT ON `jssdb`.* TO 'jss_grant'@'192.168.30.203'                                                             |

+-----------------------------------------------------------------------------------------------------------------------+

2 rows in set (0.00 sec)

毫無變化。前面revoke之所以沒有報錯,也跟MySQL在語句執行上的設定有關係,比方說,您可以嘗試revoke任意許可權 from user,它都不會報錯的,我們之前提到過,MySQL的返回就是這個德性:Query OK, 0 rows affected。

此外前面三思還提到過特殊的ALL PRIVILEGES,這個許可權也不像字面意義那麼簡單,所謂“所有許可權”指的不是所有喲。你要不相信呀,我們們再來看一看,對jss_grant@'192.168.30.203'使用者執行revoke ALL PRIVILEGES

(system@localhost) [(none)]> revoke all privileges on *.* from jss_grant@'192.168.30.203';

Query OK, 0 rows affected (0.00 sec)

提示資訊總是這樣,我們能猜的到開頭,不過能猜的對結局不,還是實際驗證一下吧:

(system@localhost) [(none)]> show grants for jss_grant@192.168.30.203;

+-----------------------------------------------------------------------------------------------------------------------+

| Grants for jss_grant@192.168.30.203                                                                                   |

+-----------------------------------------------------------------------------------------------------------------------+

| GRANT USAGE ON *.* TO 'jss_grant'@'192.168.10.203' IDENTIFIED BY PASSWORD '*284578888014774CC4EF4C5C292F694CEDBB5457' |

| GRANT SELECT ON `jssdb`.* TO 'jss_grant'@'192.168.30.203'                                                             |

+-----------------------------------------------------------------------------------------------------------------------+

2 rows in set (0.00 sec)

又是毫無作用。那個特殊的USAGE許可權就不說了,可是ALL PRIVILEGES居然連小小的普通的SELECT許可權都沒能收回,這還稱得上ALL嗎?呃,這個,稱得上,它只是功能的設計並不像我們想像的那樣而已。這幾個知識點是MySQL資料庫的許可權體系設計上的細節,如不注意就有可能錯誤理解這些設計。

前後兩個操作儘管看起來結果相同,但結論是完全不同的,前者是由於USAGEMySQL許可權體系中,對於使用者的特殊意義,後者是由於系統設計層的因素。MySQL資料庫中的許可權,操作時授予和收回的許可權級別(priv_level)必須對應,否則無法成功回收。

就上面這個例子中,授予jss_grant@'192.168.30.203'使用者SELECT許可權時,是基於jssdb這樣一個庫級授予的,那麼回收時,也必須明確指定是基於庫級回收,如果指定all on *.*,則無法收回jssdb.*的許可權,這也正是MySQL資料庫許可權粒度分級的特點。

因此,如果要讓REVOKE ALL PRIVILEGES語句正確有效執行,就應該明確指定on jssdb.*,例如:

(system@localhost) [(none)]> revoke all privileges on jssdb.* from jss_grant@'192.168.30.203';

Query OK, 0 rows affected (0.00 sec)

 

(system@localhost) [(none)]> show grants for jss_grant@192.168.30.203;

+-----------------------------------------------------------------------------------------------------------------------+

| Grants for jss_grant@192.168.30.203                                                                                   |

+-----------------------------------------------------------------------------------------------------------------------+

| GRANT USAGE ON *.* TO 'jss_grant'@'192.168.30.203' IDENTIFIED BY PASSWORD '*284578888014774CC4EF4C5C292F694CEDBB5457' |

+-----------------------------------------------------------------------------------------------------------------------+

1 row in set (0.00 sec)

這下終於成功將許可權收回了。

 

三思有過多年的ORACLE資料庫使用經驗,在嘗試使用和學習MySQL資料庫期間感觸很深,MySQL資料庫設計的確實很有特點,我想對於初學者,只要小腦袋瓜沒有停止思考,一定會持續不斷冒出各種各樣的問題。對於使用者的許可權回收,經過前面一些演示,想必朋友會又會有新的疑問:若使用者擁有各種不同級別不同粒度不同的許可權,回收時難道也必須一一指定回收嗎,這豈不太過繁瑣了。關於這點,我可以負責任的說,把心踏踏實實擱肚子裡頭吧,MySQL資料庫就跟繁瑣倆字不沾邊,做為一款開源的輕量級資料庫,MySQL就沒有什麼複雜的特性,自然也不會有繁瑣的操作。

對於前面這個疑問,如果確定要乾淨利索的清除某個使用者的所有許可權,並且還要保留這個使用者(這是什麼變態需求),那麼,REVOKE語句的第二種語法派上用場了:REVOKE ALL PRIVILEGES, GRANT OPTION FROM user。

這是個固定語法,功能正是用於收回使用者的所有許可權,不管授予使用者的是什麼許可權級別什麼物件的什麼許可權,一條語句執行下去,直接將使用者恢復至裸身(USAGE)狀態。

當前,jss_grant@'192.168.30.203'使用者有各類許可權如下:

(system@localhost) [(none)]> show grants for jss_grant@'192.168.30.203';                                          

+-------------------------------------------------------------------------------------------------------------------+

| Grants for jss_grant@192.168.30.203                                                                                   |

+-------------------------------------------------------------------------------------------------------------------+

| GRANT USAGE ON *.* TO 'jss_grant'@'192.168.30.203' IDENTIFIED BY PASSWORD '*284578888014774CC4EF4C5C292F694CEDBB5457' |

| GRANT UPDATE, DELETE ON `jssdb`.* TO 'jss_grant'@'192.168.30.203'                                                     |

| GRANT ALTER ON `jssdb_mc`.* TO 'jss_grant'@'192.168.30.203'                                                           |

| GRANT SELECT ON `mysql`.`user` TO 'jss_grant'@'192.168.30.203'                                                        |

+-------------------------------------------------------------------------------------------------------------------+

4 rows in set (0.00 sec)

怎麼一次性收回所有許可權呢,執行REVOKE語句如下:

(system@localhost) [(none)]> revoke all,grant option from jss_grant@'192.168.30.203';

Query OK, 0 rows affected (0.00 sec)

 

(system@localhost) [(none)]> show grants for jss_grant@192.168.30.203;

+-----------------------------------------------------------------------------------------------------------------------+

| Grants for jss_grant@192.168.30.203                                                                                   |

+-----------------------------------------------------------------------------------------------------------------------+

| GRANT USAGE ON *.* TO 'jss_grant'@'192.168.30.203' IDENTIFIED BY PASSWORD '*284578888014774CC4EF4C5C292F694CEDBB5457' |

+-----------------------------------------------------------------------------------------------------------------------+

1 row in set (0.00 sec)

你看,你看,使用者的許可權悄悄地在改變。

5.2.4 刪除使用者

我想不出一個僅擁有"USAGE"許可權的使用者存在的意義,乾脆,刪了它吧。怎麼,您擔心會丟失資料,影響系統穩定,放心吧,一個失勢的人對組織是沒什麼危險的,甭管它是誰,甭管它之前多紅歌聲多麼嘹亮,也甭管它之前手握多少資源,只要權利被收回,它就立刻什麼都不是,這是由當前的制度所決定的。

很多人之所以擔心刪使用者會丟資料,主要是受其它資料庫產品的影響,比如說ORACLE中刪除使用者(或其它物件比如表空間),如果該使用者下有很多的物件,那麼刪除使用者的同時也會把這些物件及關聯的資料統統刪除,儘管ORACLE會人性化地提醒你刪除的使用者下仍然存在資料,但如果強制級聯刪除(附加CASCADE選項),那麼該刪就還是刪了。

MySQL的刪除使用者語法中就不存在CASCADE的選項,為什麼不存在呢,並不是MySQL對資料的保護不如ORACLE那麼上心,而是由於最重要的一條與ORACLE不同的機制決定,MySQL資料庫中的物件儲存並不是依賴於使用者,而是依賴於庫(database),使用者被刪除沒有任何關係,物件仍在,好好的儲存在儲存它的資料庫中。

因此,MySQL資料庫中的使用者刪了就刪了,如果外部應用不使用該使用者的話,那麼我們可以認為該使用者被刪除無影響。即使發現真的刪錯了,該使用者其實早就立志將一生奉獻給鐮刀斧頭幫,並且作風過硬,對party和國家無限忠誠,party讓咬誰就咬誰。想給它恢復身份的話也很簡單,這不就是組織上一句話的事兒嘛,只要重新向mysql.user表重新插入記錄(註冊建檔),並授予所需許可權即可(授予官階),至於底層資料的意見那是完全可以忽視的。

看我說的這麼篤定,下面就實際冊個試試吧。MySQL刪除使用者的語法非常簡單:

DROP USER user [, user] ...

從語法上大家想必也都看出來了,也可以一次性刪除多個使用者,這裡三思就準備一步刪除之前建立的jss_grantjss_insertjss_ip幾個使用者,執行drop user命令如下:

(system@localhost) [(none)]> drop user jss_grant@192.168.30.203, jss_insert@192.168.30.203, jss_ip@192.168.30.203;

Query OK, 0 rows affected (0.00 sec)

需要說明的一點是,DROP USER不會自動中止已連線的使用者會話,也就是說被刪的使用者如果在刪前已經連線上了伺服器,並且連線尚未中斷,那它此時還能繼續執行一定的操作,只是,它的身份已經變成了黑戶。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29119536/viewspace-1712842/,如需轉載,請註明出處,否則將追究法律責任。

相關文章