塗抹MySQL--第5章 MySQL資料庫中的許可權體系 - 5.3許可權級別(2)

dawn009發表於2015-06-26

5.3.2 資料庫

資料庫級別的許可權,主要用於控制帳戶('user'@'host')操作某個資料庫的許可權,在這一粒度對使用者做了授權後,使用者就擁有了該資料庫下[所有]物件的[所有]許可權。

資料庫級別的許可權資訊記錄在mysql.db。在介紹mysql.db表之前,這裡三思想先特別提一下mysql.host表,這個表也與資料庫粒度的許可權有關聯,它的功能相對奇特,是用於控制某些主機(host)是否擁有操作某個資料庫的許可權,在可設定的許可權方面跟mysql.db幾乎一模一樣。

mysql.host表在MySQL5.5及之前版本中的處境很特別,預設情況下GRANT/REVOKE語句並不觸發對該表資料的讀寫,因此多數情況下該表都沒啥用,極易被忽略。不過在應對某些特定場景下,DBA可以手動操作(insert/update/delete)該表來實現某些特殊的需求。比如說只希望某些主機擁有操作某個資料庫的許可權時,mysql.user完全派不上用場(它是針對全域性的嘛,管不到db這麼細的粒度),那麼使用mysql.host就可以輕鬆實現,因為該表對許可權的驗證正是使用host這個緯度。

當然啦,這個需求使用mysql.db表也可以實現,mysql.db表是透過user+host兩個緯度來驗證許可權,比mysql.host多了一個緯度,不過由於MySQL資料庫的許可權字典表能夠支援萬用字元,並且user列可以為空(代表所有使用者),透過靈活設定也可以實現mysql.host表的功能,我想也正是基於此,從5.6版本開始,mysql.host表已被明確廢棄。不過如果您在使用之前版本的資料庫,如果場景適當,倒是仍可以用用mysql.host表。

還是說回到mysql.db表吧,功能前頭已經說過了,不過出於加深印象的目的,我再重複說一遍大家沒什麼意見吧,有意見也不要緊,我的郵箱地址網上都寫著哪,有啥抱怨的話儘管發,GMAIL郵箱,空間有好個G哪。

我個人感覺將資料庫級許可權與全域性級許可權對比起來更好理解,全域性級許可權大家都知道了吧,用來控制使用者操作所有資料庫的許可權(以及管理MySQL服務的許可權),資料都是儲存在mysql.user字典表中。若只希望授予使用者操作某個資料庫的許可權,該怎麼辦呢,那就該mysql.db出馬啦,你要問mysql.usermysql.db差在哪,對比一下兩個字典表的表結構您就明白啦:

mysql.user表

mysql.db表

Host

Host

User

User

Password

 

 

Db

Select_priv

Select_priv

Insert_priv

Insert_priv

Update_priv

Update_priv

Delete_priv

Delete_priv

Create_priv

Create_priv

Drop_priv

Drop_priv

Reload_priv

Grant_priv

References_priv

References_priv

Index_priv

Index_priv

Alter_priv

Alter_priv

Create_tmp_table_priv

Create_tmp_table_priv

Lock_tables_priv

Lock_tables_priv

Create_view_priv

Create_view_priv

Show_view_priv

Show_view_priv

Create_routine_priv

Create_routine_priv

Alter_routine_priv

Alter_routine_priv

Execute_priv

Execute_priv

Event_priv

Event_priv

Trigger_priv

Trigger_priv

Shutdown_priv

 

Process_priv

..........

..........

..........

 

5-4 全域性和庫級許可權對應表

你看,mysql.db表中有的列,在mysql.user中幾乎全都有,而mysql.user中有的列則有一堆mysql.db表中都不存在呀,看看前面章節中介紹的許可權說明,多出的列正是MySQL服務級的管理許可權,說mysql.dbmysql.user表的子集都不為過。mysql.db相比mysql.user多出的"Db"列,不正是用來指定要管理的目標資料庫嘛。

授予使用者某個資料庫的管理許可權,執行GRANT語句時,相比全域性就得縮小授權範圍,把全域性時指定的*.*改成dbname.*就行啦。例如,建立jss_database使用者,並授予jssdb庫下建立物件的許可權,執行命令如下:

(system@localhost) [(none)]> grant create on jssdb.* to jss_db;

Query OK, 0 rows affected (0.00 sec)

建立成功,檢視jss_db使用者在各字典表的記錄明細,以便我們能夠更清晰的理解,許可權字典表在使用者許可權環境所起到的作用。

先來剛剛建立的使用者,在mysql.user全域性許可權表中的資訊:

(system@localhost) [(none)]> select * from mysql.user where user='jss_database'\G

*************************** 1. row ***************************

                  Host: %

                  User: jss_database

              Password: 

           Select_priv: N

           Insert_priv: N

           Update_priv: N

           Delete_priv: N

           Create_priv: N

             Drop_priv: N

           Reload_priv: N

         Shutdown_priv: N

.............

............

操作類許可權都是"N"(相當於僅擁有USAGE許可權),這就對了,允許該使用者登入MySQL資料庫。那麼操作jssdb資料庫的許可權寫在哪了呢,再看看mysql.db庫級許可權字典表吧:

(system@localhost) [(none)]> select * from mysql.db where user='jss_db'\G

*************************** 1. row ***************************

                 Host: %

                   Db: jssdb

                 User: jss_db

          Select_priv: N

          Insert_priv: N

          Update_priv: N

          Delete_priv: N

          Create_priv: Y

            Drop_priv: N

           Grant_priv: N

      References_priv: N

           Index_priv: N

           Alter_priv: N

Create_tmp_table_priv: N

     Lock_tables_priv: N

     Create_view_priv: N

       Show_view_priv: N

  Create_routine_priv: N

   Alter_routine_priv: N

         Execute_priv: N

           Event_priv: N

         Trigger_priv: N

1 row in set (0.00 sec)

這下就比較清晰了,"Db"表顯示了可操作的庫名,"Create_priv"列值顯示"Y",表示這個使用者擁有指定庫中物件的建立許可權。

下面再透過該使用者連線到MySQL資料庫中看一下吧。使用jss_db使用者登入,檢視當前可訪問的資料庫:

(jss_db@192.168.30.243) [(none)]> show databases;

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

| Database           |

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

| information_schema |

| jssdb              |

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

2 rows in set (0.00 sec)

jssdb庫倒是列出來了,但是,好奇怪呀,不是說只授予了jssdb庫的許可權嗎,怎麼還能看到information_schema庫呢,別急,我們們馬上就會提到這一點。

5.3.2.1 並不存在的INFORMATION_SCHEMA

熟悉ORACLE資料庫的朋友想必知道,在ORACLE資料庫中有一堆v$*檢視、user_*all_*等字典表,所有能夠成功連線資料庫的使用者都可以訪問這些物件(無須額外授權)MySQL資料庫中也存在一系列這樣的物件,比如TABLESVIEWSCOLUMNS等等,所有能夠成功登入到MySQL資料庫的使用者都能訪問。

想一想,這些物件在哪呢,沒錯,正是在INFORMATION_SCHEMA資料庫下。即然這類物件能夠被訪問,那麼INFORMATION_SCHEMA庫自然也就能被所有使用者看到啦,這樣才符合邏輯。

需要注意的是,MySQL中的INFORMATION_SCHEMA並不是真正的資料庫,在作業系統層並沒有與之對應的物理檔案,這個資料庫及庫中的物件,全是由MySQL自動維護的一系列虛擬物件,這些物件使用者能看卻不能改(不能直接改),並且與ORACLE資料庫中的資料字典表類似,使用者查詢這些物件中的記錄時,看到的都是自己有許可權看到的物件。比如說擁有jssdb庫建立許可權的jss_db使用者,能夠在INFORMATION_SCHEMA資料庫的TABLES/COLUMNS等物件中,檢視jssdb庫中所有表和列的資訊,但是因為沒有檢視/過程這類物件的操作許可權,那麼訪問VIEWS字典表時,就檢視不到記錄啦。

INFORMATION_SCHEMA庫中物件的另一特殊之處在於,使用者不能對INFORMATION_SCHEMA資料庫中的物件做授權。比如將information_schema.tables表物件的select許可權授予某個使用者,這樣操作肯定會失敗,即使是管理員使用者也不行。

5.3.2.2 有趣的test

除了INFORMATION_SCHEMA這樣的虛擬庫外,MySQL資料庫中的test庫的預設許可權也需要引起DBA們注意。

新建MySQL資料庫後,預設建立的test資料庫許可權比較怪異,所有可連線的使用者都能夠擁有許可權訪問該庫,並操作其中的物件。這是怎麼實現的呢,其實很簡單,檢視庫級許可權字典表,mysql.db您就明白了:

mysql> select * from mysql.db where db like 'test%'\G;

*************************** 1. row ***************************

                 Host: %

                   Db: test

                 User: 

          Select_priv: Y

          Insert_priv: Y

          Update_priv: Y

          Delete_priv: Y

          Create_priv: Y

            Drop_priv: Y

           Grant_priv: N

      References_priv: Y

           Index_priv: Y

           Alter_priv: Y

Create_tmp_table_priv: Y

     Lock_tables_priv: Y

     Create_view_priv: Y

       Show_view_priv: Y

  Create_routine_priv: Y

   Alter_routine_priv: N

         Execute_priv: N

           Event_priv: Y

         Trigger_priv: Y

*************************** 2. row ***************************

                 Host: %

                   Db: test\_%

                 User: 

          Select_priv: Y

          Insert_priv: Y

          Update_priv: Y

          Delete_priv: Y

          Create_priv: Y

            Drop_priv: Y

           Grant_priv: N

      References_priv: Y

           Index_priv: Y

           Alter_priv: Y

Create_tmp_table_priv: Y

     Lock_tables_priv: Y

     Create_view_priv: Y

       Show_view_priv: Y

  Create_routine_priv: Y

   Alter_routine_priv: N

         Execute_priv: N

           Event_priv: Y

         Trigger_priv: Y

2 rows in set (0.00 sec)

你看,從許可權上來看,host%user為空,這就說明了不限制的,所有能連線到MySQL的使用者,全都擁有testtest開頭的資料庫的幾乎所有許可權。

這無異存在安全上的隱患,先不說在其中建立的重要物件可被任何人訪問,就算該庫中沒有任何物件,假如有人想惡意破壞DB服務,只要登入資料庫後,在該庫建立一個超大物件,把空閒空間全部佔滿,就相當於變相達到了破壞DB服務的目地。對於這類許可權沒啥好客氣的,該咋處理就咋處理吧。

不過如果讀者朋友是按照三思在本書中介紹的步驟建立資料庫,那就不會存在這種隱患了,還記的第三章中,配置資料庫環境時我們做過的操作嗎:

(root@localhost) [(none)]> truncate table mysql.db;

Query OK, 0 rows affected (0.00 sec)

直接清空mysql.db表中記錄,這兩個許可權已被刪除,隱患早已經被排除啦。

順便提出一個問題,如果想讓所有使用者都擁有訪問jssdb庫中物件的許可權,GRANT語句應該怎麼寫呢,有興趣的朋友不妨在自己的測試環境中模擬一下吧。

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

相關文章