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

dawn009發表於2015-06-26

5.3.3 表

表做為具體的物件,當我們談論到對某個物件授權時,已經進入到一個相對細粒度的許可權級別了,表物件的授權資訊儲存在mysql.tables_priv字典表中。

我知道很多初學者在學習MySQL許可權操作時,由於對許可權體系瞭解有限不夠熟悉,甚至可能不清楚究竟有哪些許可權可供授權。這個問題解決起來也很簡單,直接看官方文件中有相關內容,文件中有個表格羅列了所有可授予的許可權。當然啦看本書也靠譜,前面5.2.2小節中列的表格就是抄(提起這個字兒我臉就紅了)自官方文件的許可權列表,裡面各種許可權明細寫的清清楚楚明明白白,看完後記住就不會再迷茫啦。

還有些朋友文件也沒少看,可就是記不住,一方面由於許可權型別多(其實MySQL中的許可權相比ORACLE已經少太多了),再一個許可權還分了多個粒度,誰能記的清哪個粒度都能有哪些許可權哪。針對這種情況也很好解決,desc檢視相關表物件的結構即可。

比方說,現在我們們都不知道在表一級,究竟能夠授予使用者什麼樣的許可權(或者說使用者有什麼樣的選擇),那麼直接desc mysql.tables_priv檢視,例如:

(system@localhost) [(none)]> desc mysql.tables_priv;

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

| Field       | Type         | Null | Key | Default  | Extra      |

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

| Host        | char(60)     | NO   | PRI |          |            |

| Db          | char(64)     | NO   | PRI |          |            |

| User        | char(16)     | NO   | PRI |          |            |

| Table_name  | char(64)     | NO   | PRI |          |            |

| Grantor     | char(77)     | NO   | MUL |          |            |

| Timestamp   | timestamp    | NO   |     | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |

| Table_priv  | set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view','Trigger') | NO   |     |                   |                             |

| Column_priv | set('Select','Insert','Update','References')                                                                                      | NO   |     |                   |                             |

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

8 rows in set (0.00 sec)

直接輸出的資訊較長,這裡做了些刪減。簡要說一下tables_priv字典表的結構:

n Host:來源主機;

n Db:物件所屬資料庫;

n User:使用者名稱;

n Table_name:表物件名稱;

n Grantor:執行許可權授予的使用者;

n Timestamp:授予許可權的時間;

n Table_priv:能夠授予的表粒度的許可權,也就是我們最關注的資訊;

n Column_priv:能夠授予的列粒度的許可權;

Host+Db+User+Table_name四個緯度的共同作用成就一條許可權,粒度夠細。 

注意看Table_priv/Column_priv兩列對應的列值,這些列值就是表物件能夠授予的許可權。這下知道許可權關鍵字怎麼寫了吧,三思老早就表達過這樣一種觀點,學習是有技巧的,死記硬背(SJYB)是技巧之一,但不一定是最好的,隨機應變(SJYB)才是~~~

知道了關鍵字,就可以根據需求進行授權了。比如說,向jss_tables使用者授予users表的全部許可權,該怎麼寫GRANT語句呢:

(system@localhost) [(none)]> grant all on jssdb.users to jss_tbls;

Query OK, 0 rows affected (0.02 sec)

哎喲喲,咋沒寫前面desc裡看到的許可權關鍵字呢,這樣寫也能成功授權嗎,黑黑,三思都說了要SJYB的嘛,讓事實來說話吧:

(system@localhost) [(none)]> select * from mysql.tables_priv where user='jss_tbls' and table_name='users'\G

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

       Host: %

         Db: jssdb

       User: jss_tbls

 Table_name: users

    Grantor: system@localhost

  Timestamp: 0000-00-00 00:00:00

 Table_priv: Select,Insert,Update,Delete,Create,Drop,References,Index,Alter,Create View,Show view,Trigger

Column_priv: 

1 row in set (0.00 sec)

這下理解了吧,ALL就是所有許可權嘛。

不過細心的朋友想必早已注意到tables_priv表中的Columns_priv列了吧,你說表粒度的許可權怎麼會出現對列級許可權的指定呢,這點在我看來其實就是體現MySQL細節設計上的特點,做為一款開源軟體,它在整體設計上有時確實讓人感覺摸不著頭腦,說的更直白些就是它自己都沒想清楚啊,這一點不僅僅體現在許可權設計上,在其它設計比較初始化引數,管理功能等等都有體現。

總之就是Column_priv列在宣告表級許可權時沒用,但在授予列級許可權時就有反映了,繼續往下看吧。

5.3.4 列

列級許可權,是MySQL許可權體系中的最細粒度,屬於許可權認證體系中的高精尖武器。透過對錶中列的授權,可以實現只允許從某主機來的某使用者訪問某庫的某表的某列。

列級許可權儲存在mysql.columns_priv字典中,該字典結構如下:

(system@localhost) [(none)]> desc mysql.columns_priv;

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

| Field       | Type          | Null | Key | Default  | Extra     |

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

| Host        | char(60)      | NO   | PRI |          |           |

| Db          | char(64)      | NO   | PRI |          |           |

| User        | char(16)      | NO   | PRI |          |           |

| Table_name  | char(64)      | NO   | PRI |          |           |

| Column_name | char(64)      | NO   | PRI |          |           |

| Timestamp   | timestamp     | NO   |     | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |

| Column_priv | set('Select','Insert','Update','References') | NO   |     |                   |                             |

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

7 rows in set (0.00 sec)

列級許可權需要Host+Db+User+Table_name+Column_name五個粒度,另外從上面的物件結構可以看出,對於列級許可權可授予的共有4項,其中只有前3項有實際意義

l Select:查詢許可權

l Insert:插入許可權

l Update:修改許可權

l References尚未應用,直接無視;

 

授予列級許可權,在執行GRANT語句時,語法上稍有不同,主要體現在指定列級的粒度語法並不在ON子句,而是在指定priv_type時順道附帶列名的方式,例如,授予jss_cols使用者查詢jssdb.usersphoneno列的許可權,執行語句如下

(system@localhost) [(none)]> grant select (phoneno) on jssdb.users to jss_cols;

Query OK, 0 rows affected (0.00 sec)

檢視字典表中儲存的資訊:

(system@localhost) [(none)]> select * from mysql.columns_priv;

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

| Host | Db    | User     | Table_name | Column_name | Timestamp           | Column_priv |

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

| %    | jssdb | jss_cols | users      | phoneno     | 0000-00-00 00:00:00 | Select      |

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

1 row in set (0.00 sec)

 

(system@localhost) [(none)]> select * from mysql.tables_priv where user='jss_cols';

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

| Host | Db    | User     | Table_name | Grantor          | Timestamp           | Table_priv | Column_priv |

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

| %    | jssdb | jss_cols | users      | system@localhost | 0000-00-00 00:00:00 |            | Select      |

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

1 row in set (0.00 sec)

列級字典表中是有資料的,表級字典表中也有記錄存在的,就目前的實際情況來看,columns_priv表控制具體的許可權,tables_priv中的資料則是用來標記該條授權的一些基礎資訊,比如授予者,操作時間等。

對同一個表物件再授權另一個許可權,看看字典表中如何儲存就更加明確了:

(system@localhost) [(none)]> grant insert (address) on jssdb.users to jss_cols;

Query OK, 0 rows affected (0.00 sec)

 

(system@localhost) [(none)]> select * from mysql.columns_priv;

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

| Host | Db    | User     | Table_name | Column_name | Timestamp           | Column_priv |

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

| %    | jssdb | jss_cols | users      | phoneno     | 0000-00-00 00:00:00 | Select      |

| %    | jssdb | jss_cols | users      | address     | 0000-00-00 00:00:00 | Insert      |

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

2 rows in set (0.00 sec)

 

(system@localhost) [(none)]> select * from mysql.tables_priv where user='jss_cols';

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

| Host | Db    | User     | Table_name | Grantor          | Timestamp           | Table_priv | Column_priv   |

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

| %    | jssdb | jss_cols | users      | system@localhost | 0000-00-00 00:00:00 |            | Select,Insert |

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

1 row in set (0.00 sec)

注意到差別了吧,tables_priv只是表級粗粒度的記錄,columns_priv才是決定列級許可權粒度的核心。

 

下面使用剛剛建立的jss_cols使用者連線到資料庫檢視一下:

[mysql@mysqldb02 ~]$ mysql -ujss_cols -h 192.168.30.243  

Welcome to the MySQL monitor.  Commands end with ; or \g.

..........

..........

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

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

| Database           |

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

| information_schema |

| jssdb              |

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

2 rows in set (0.00 sec)

 

(jss_cols@192.168.30.243) [(none)]> use jssdb;

Database changed

(jss_cols@192.168.30.243) [jssdb]> show tables;

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

| Tables_in_jssdb |

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

| users           |

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

1 row in set (0.00 sec)

 

(jss_cols@192.168.30.243) [jssdb]> desc users;

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

| Field   | Type        | Null | Key | Default | Extra |

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

| address | varchar(50) | YES  |     | NULL    |       |

| phoneno | varchar(15) | YES  |     | NULL    |       |

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

2 rows in set (0.02 sec)

能,且僅能檢視授權了的表的指定列,看起來該表似乎只有這兩個列,其實是因為它只能看到這兩列,實際操作這兩珍時也將發現,這兩列的許可權都是不一樣的。

問:怎麼檢視當前使用者擁有的許可權呢?

答:盆友,可還記的5.2.3小節講過的SHOW GRANTS命令嗎。

這裡需要注意的一點是,儘管透過DESC檢視錶結構,或者是使用SELECT語句查詢表資料時只能查到被授予許可權的列,但是,該使用者查詢information_schema.tables或其它相關字典表時,看到的表的資訊,仍然是完整的,比如表的大小、索引大小、平均列長度等等資訊,這也是INFORMATION_SCHEMA庫比較特殊的另一個體現吧。

5.3.5 程式

MySQL中的程式(ROUTINE)主要是指ProcedureFunction兩類物件,這兩類物件的許可權與前面描述的4種基本無關聯(如果說有的話,也只是使用者是否擁有連線資料庫的許可權),相對比較獨立。

對於已存在的Procedure/FunctionDBA可以對使用者授予執行(execute)、修改(alter routine)、授予(grant)許可權,這部分許可權體現在mysql.procs_priv表中,例如:

(system@localhost) [(none)]> desc mysql.procs_priv;

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

| Field        | Type                                   | Null | Key | Default           | Extra                       |

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

| Host         | char(60)                               | NO   | PRI |                   |                             |

| Db           | char(64)                               | NO   | PRI |                   |                             |

| User         | char(16)                               | NO   | PRI |                   |                             |

| Routine_name | char(64)                               | NO   | PRI |                   |                             |

| Routine_type | enum('FUNCTION','PROCEDURE')           | NO   | PRI | NULL              |                             |

| Grantor      | char(77)                               | NO   | MUL |                   |                             |

| Proc_priv    | set('Execute','Alter Routine','Grant') | NO   |     |                   |                             |

| Timestamp    | timestamp                              | NO   |     | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |

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

8 rows in set (0.00 sec)

除此之後,還可以授予使用者建立(create routine)許可權,這個許可權在user/db/host幾個表中都有體現。擁有create routine許可權的使用者能夠建立procedure/function物件。這個許可權是使用者/庫一級許可權,而execute/alter routine/grant這三個許可權則是物件極,都是針對某個指定的procedure/function做授權。

關於"程式"物件的許可權操作就不演示了,實在是跟之前的許可權授予/收回操作沒啥區別,重複的事情做起來實在沒意思,還浪費紙張,很不低碳,我們們還是接著做點對全人類有益的事情,少說點兒廢話,多做點兒實事兒吧。

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

相關文章