Mysql權(quán)限系統(tǒng)工作理
發(fā)布時(shí)間:2008-08-13 閱讀數(shù): 次 來源:網(wǎng)樂原科技
暫無廣告MySQL權(quán)限系統(tǒng)保證所有的用戶可以嚴(yán)格地做他們假定被允許做的事情。當(dāng)你連接一個(gè)MySQL服務(wù)器時(shí), 你的身份由你從那連接的主機(jī)和你指定的用戶名來決定,系統(tǒng)根據(jù)你的身份和你想做什么來授予權(quán)限?!?br>
MySQL在認(rèn)定身份中考慮你的主機(jī)名和用戶名字,是因?yàn)橛泻苄〉脑蚣俣ㄒ粋€(gè)給定的用戶在因特網(wǎng)上屬于同一個(gè)人。例如,用戶從whitehouse.gov連接的bill不必和從mosoft.com連接bill是同一個(gè)人?!ySQL通過允許你區(qū)分在不同的主機(jī)上碰巧有同樣名字用戶來處理它:你可以對(duì)從whitehouse.gov連接授與bill一個(gè)權(quán)限集,而為從microsoft.com的連接授予一個(gè)不同的權(quán)限集?!?br>
MySQL存取控制包含2個(gè)階段:
階段1:服務(wù)器檢查你是否允許連接。
階段2:假定你能連接,服務(wù)器檢查你發(fā)出的每個(gè)請(qǐng)求。看你是否有足夠的權(quán)限實(shí)施它。例如,如果你從數(shù)據(jù)庫(kù)中一個(gè)表精選(select)行或從數(shù)據(jù)庫(kù)拋棄一個(gè)表,服務(wù)器確定你對(duì)表有select權(quán)限或?qū)?shù)據(jù)庫(kù)有drop權(quán)限?!?br>
服務(wù)器在存取控制的兩個(gè)階段使用在mysql的數(shù)據(jù)庫(kù)中的user、db和host表,在這些授權(quán)表中字段如下:
表名稱 user db host
范圍字段 Host Host Host
User Db Db
Password User
權(quán)限字段 Select_priv Select_priv Select_priv
Insert_priv Insert_priv Insert_priv
Update_priv Update_priv Update_priv
Delete_priv Delete_priv Delete_priv
Index_priv Index_priv Index_priv
Alter_priv Alter_priv Alter_priv
Create_priv Create_priv Create_priv
Drop_priv Drop_priv Drop_priv
Grant_priv Grant_priv Grant_priv
Reload_priv
Shutdown_priv
Process_priv
File_priv
對(duì)存取控制的第二階段(請(qǐng)求證實(shí)),如果請(qǐng)求涉及表,服務(wù)器可以另外參考tables_priv和columns_priv表。這些表的字段如下:
表名稱 tables_priv columns_priv
范圍字段 Host Host
Db Db
User User
Table_name Table_name
Column_name
權(quán)限字段 Table_priv Column_priv
Column_priv
其他字段 Timestamp Timestamp
Grantor
每個(gè)授權(quán)表包含范圍字段和權(quán)限字段。
范圍字段決定表中每個(gè)條目的范圍,即,條目適用的上下文。例如, 一個(gè)user表?xiàng)l目的Host和User值為'thomas.loc.gov'和'bob'將被用于證實(shí)來自主機(jī)thomas.loc.gov的bob對(duì)服務(wù)器的連接。同樣,一個(gè)db表?xiàng)l目的Host、User和Db字段的值是'thomas.loc.gov'、'bob'和'reports'將用在bob從主機(jī)聯(lián)接thomas.loc.gov存取reports數(shù)據(jù)庫(kù)的時(shí)候?!ables_priv和columns_priv表包含范圍字段,指出每個(gè)條目適用的表或表/列的組合?!?br>
對(duì)于檢查存取的用途,比較Host值是忽略大小寫的。User、Password、Db和Table_name值是區(qū)分大小寫的。Column_name值在MySQL3.22.12或以后版本是忽略大小寫的?!?br>
權(quán)限字段指出由一個(gè)表?xiàng)l目授予的權(quán)限,即,可實(shí)施什么!?。 ∽鳌7?wù)器組合各種的授權(quán)表的信息形成一個(gè)用戶權(quán)限的完整描述。為此使用的規(guī)則在6.8 存取控制, 階段2:請(qǐng)求證實(shí)描述?!?br>
范圍字段是字符串,如下所述;每個(gè)字段的缺省值是空字符串:
字段名 類型
Host CHAR(60)
User CHAR(16)
Password CHAR(16)
Db CHAR(64) (tables_priv和columns_priv表為CHAR(60))
在user、db和host表中,所有權(quán)限字段被聲明為ENUM('N','Y')--每一個(gè)都可有值'N'或'Y',并且缺省值是'N'.
在tables_priv和columns_priv表中,權(quán)限字段被聲明為SET字段:
表名 字段名 可能的集合成員
tables_priv Table_priv 'Select', 'Insert', 'Update', 'Delete', 'Create', 'Drop', 'Grant', 'References', 'Index', 'Alter'
tables_priv Column_priv 'Select', 'Insert', 'Update', 'References'
columns_priv Column_priv 'Select', 'Insert', 'Update', 'References'
簡(jiǎn)單地說,服務(wù)器使用這樣的授權(quán)表:
user表范圍字段決定是否允許或拒絕到來的連接。對(duì)于允許的連接,權(quán)限字段指出用戶的全局(超級(jí)用戶)權(quán)限?!?br>
db和host表一起使用:
db表范圍字段決定用戶能從哪個(gè)主機(jī)存取哪個(gè)數(shù)據(jù)庫(kù)。權(quán)限字段決定允許哪個(gè)!?。 ∽??!?br>
當(dāng)你想要一個(gè)給定的db條目應(yīng)用于若干主機(jī)時(shí),host表作為db表的擴(kuò)展被使用。例如,如果你想要一個(gè)用戶能在你的網(wǎng)絡(luò)從若干主機(jī)使用一個(gè)數(shù)據(jù)庫(kù),在用戶的db表的Host條目設(shè)為空值,然后將那些主機(jī)的每一個(gè)移入host表。這個(gè)機(jī)制詳細(xì)描述在6.8 存取控制, 階段2:請(qǐng)求證實(shí)?!?br>
tables_priv和columns_priv表類似于db表,但是更精致:他們?cè)诒砗土屑?jí)應(yīng)用而非在數(shù)據(jù)庫(kù)級(jí)?!?br>
注意管理權(quán)限(reload, shutdown, 等等)僅在user表中被指定。這是因?yàn)楣芾硇?!??! 作是服?wù)器本身的!?。 ∽鞑⑶也皇翘囟〝?shù)據(jù)庫(kù),因此沒有理由在其他授權(quán)表中列出這樣的權(quán)限。事實(shí)上,只需要請(qǐng)教user表來決定你是否執(zhí)行一個(gè)管理!??! 作?!?br>
file權(quán)限也僅在user表中指定。它不是管理性權(quán)限,但你讀或謝在服務(wù)器主機(jī)上的文件的的能力獨(dú)立于你正在存取的數(shù)據(jù)庫(kù)。
當(dāng)mysqld服務(wù)器啟動(dòng)時(shí),讀取一次授權(quán)表內(nèi)容。對(duì)授權(quán)表的更改生效在6.9 權(quán)限更改何時(shí)生效描述?!?br>
當(dāng)你修改授權(quán)表的內(nèi)容時(shí),確保你按你想要的方式更改權(quán)限設(shè)置是一個(gè)好主意。為幫助診斷問題,見6.13 “存取拒絕引起”錯(cuò)誤的原因。對(duì)于安全問題上的忠告,見6.14 怎么對(duì)使MySQL安全對(duì)抗解密高手?!?br>
一個(gè)有用的診斷工具是mysqlaccess腳本,由Carlier Yves 提供給MySQL分發(fā)。使用--help選項(xiàng)調(diào)用mysqlaccess查明它怎樣工作。注意:mysqlaccess僅用user、db和host表僅檢查存取。它不檢查表或列級(jí)權(quán)限。
6.7 存取控制, 階段1:連接證實(shí)
當(dāng)你試圖聯(lián)接一個(gè)MySQL服務(wù)器時(shí),服務(wù)器基于你的身份和你是否能通過供應(yīng)正確的口令驗(yàn)證身份來接受或拒絕連接。如果不是,服務(wù)器完全具結(jié)你的存取,否則,服務(wù)器接受連接,然后進(jìn)入階段2并且等待請(qǐng)求?!?br>
你的身份基于2個(gè)信息:
你從那個(gè)主機(jī)連接
你的MySQL用戶名
身份檢查使用3個(gè)user表(Host, User和Password)范圍字段執(zhí)行。服務(wù)器只有在一個(gè)user表?xiàng)l目匹配你的主機(jī)名和用戶名并且你提供了正確的口令時(shí)才接受連接?!?br>
在user表范圍字段可以如下被指定:
一個(gè)Host值可以是主機(jī)名或一個(gè)IP數(shù)字,或'localhost'指出本地主機(jī)?!?br>
你可以在Host字段里使用通配符字符“%”和“_”。
一個(gè)Host值'%'匹配任何主機(jī)名,一個(gè)空白Host值等價(jià)于'%'。注意這些值匹配能創(chuàng)建一個(gè)連接到你的服務(wù)器的任何主機(jī)!
通配符字符在User字段中不允許,但是你能指定空白的值,它匹配任何名字。如果user表匹配到來的連接的條目有一個(gè)空白的用戶名,用戶被認(rèn)為是匿名用戶(沒有名字的用戶),而非客戶實(shí)際指定的名字。這意味著一個(gè)空白的用戶名被用于在連接期間的進(jìn)一步的存取檢查(即,在階段2期間)?!?br>
Password字段可以是空白的。這不意味著匹配任何口令,它意味著用戶必須不指定一個(gè)口令進(jìn)行連接?!?br>
非空白Password值代表加密的口令?!ySQL不以任何人可以看的純文本格式存儲(chǔ)口令,相反,正在試圖聯(lián)接的一個(gè)用戶提供的口令被加密(使用PASSWORD()函數(shù)),并且與存儲(chǔ)了user表中的已經(jīng)加密的版本比較。如果他們匹配,口令是正確的?!?br>
下面的例子顯示出各種user表中Host和User條目的值的組合如何應(yīng)用于到來的連接:
Host 值 User 值 被條目匹配的連接
'thomas.loc.gov' 'fred' fred, 從thomas.loc.gov 連接
'thomas.loc.gov' '' 任何用戶, 從thomas.loc.gov連接
'%' 'fred' fred, 從任何主機(jī)連接
'%' '' 任何用戶, 從任何主機(jī)連接
'%.loc.gov' 'fred' fred, 從在loc.gov域的任何主機(jī)連接
'x.y.%' 'fred' fred, 從x.y.net、x.y.com,x.y.edu等聯(lián)接。(這或許無用)
'144.155.166.177' 'fred' fred, 從有144.155.166.177 IP 地址的主機(jī)連接
'144.155.166.%' 'fred' fred, 從144.155.166 C類子網(wǎng)的任何主機(jī)連接
既然你能在Host字段使用IP通配符值(例如,'144.155.166.%'匹配在一個(gè)子網(wǎng)上的每臺(tái)主機(jī)),有可能某人可能企圖探究這種能力,通過命名一臺(tái)主機(jī)為144.155.166.somewhere.com。為了阻止這樣的企圖,MySQL不允許匹配以數(shù)字和一個(gè)點(diǎn)起始的主機(jī)名,這樣,如果你用一個(gè)命名為類似1.2.foo.com的主機(jī),它的名字決不會(huì)匹配授權(quán)表中Host列。只有一個(gè)IP數(shù)字能匹配IP通配符值?!?br>
一個(gè)到來的連接可以被在user表中的超過一個(gè)條目匹配。例如,一個(gè)由fred從thomas.loc.gov的連接匹配多個(gè)條目如上所述。如果超過一個(gè)匹配,服務(wù)器怎么選擇使用哪個(gè)條目呢?服務(wù)器在啟動(dòng)時(shí)讀入user表后通過排序來解決這個(gè)問題,然后當(dāng)一個(gè)用戶試圖連接時(shí),以排序的順序?yàn)g覽條目,第一個(gè)匹配的條目被使用。
user表排序工作如下,假定user表看起來像這樣:
+-----------+----------+-
| Host | User | ...
+-----------+----------+-
| % | root | ...
| % | jeffrey | ...
| localhost | root | ...
| localhost | | ...
+-----------+----------+-
當(dāng)服務(wù)器在表中讀取時(shí),它以最特定的Host值為先的次序排列('%'在Host列里意味著“任何主機(jī)”并且是最不特定的)。有相同Host值的條目以最特定的User值為先的次序排列(一個(gè)空白User值意味著“任何用戶”并且是最不特定的)。最終排序的user表看起來像這樣:
+-----------+----------+-
| Host | User | ...
+-----------+----------+-
| localhost | root | ...
| localhost | | ...
| % | jeffrey | ...
| % | root | ...
+-----------+----------+-
當(dāng)一個(gè)連接被嘗試時(shí),服務(wù)器瀏覽排序的條目并使用找到的第一個(gè)匹配。對(duì)于由jeffrey從localhost的一個(gè)連接,在Host列的'localhost'條目首先匹配。那些有空白用戶名的條目匹配連接的主機(jī)名和用戶名。('%'/'jeffrey'條目也將匹配,但是它不是在表中的第一匹配。)
這是另外一個(gè)例子。假定user桌子看起來像這樣:
+----------------+----------+-
| Host | User | ...
+----------------+----------+-
| % | jeffrey | ...
| thomas.loc.gov | | ...
+----------------+----------+-
排序后的表看起來像這樣:
+----------------+----------+-
| Host | User | ...
+----------------+----------+-
| thomas.loc.gov | | ...
| % | jeffrey | ...
+----------------+----------+-
一個(gè)由jeffrey從thomas.loc.gov的連接被第一個(gè)條目匹配,而一個(gè)由jeffrey從whitehouse.gov的連接被第二個(gè)匹配。
普遍的誤解是認(rèn)為,對(duì)一個(gè)給定的用戶名,當(dāng)服務(wù)器試圖對(duì)連接尋找匹配時(shí),明確命名那個(gè)用戶的所有條目將首先被使用。這明顯不是事實(shí)。先前的例子說明了這點(diǎn),在那里一個(gè)由jeffrey從thomas.loc.gov的連接沒被包含'jeffrey'作為User字段值的條目匹配,但是由沒有用戶名的題目匹配!
如果你有服務(wù)器連接的問題,打印出user表并且手工排序它看看第一個(gè)匹配在哪兒進(jìn)行。
6.8 存取控制,階段2:請(qǐng)求證實(shí)
一旦你建立了一個(gè)連接,服務(wù)器進(jìn)入階段2。對(duì)在此連接上進(jìn)來的每個(gè)請(qǐng)求,服務(wù)器檢查你是否有足夠的權(quán)限來執(zhí)行它,它基于你希望執(zhí)行的!?。 ∽黝愋?。這正是在授權(quán)表中的權(quán)限字段發(fā)揮作用的地方。這些權(quán)限可以來子user、db、host、tables_priv或columns_priv表的任何一個(gè)。授權(quán)表用GRANT和REVOKE命令!?。 ∽?。見7.26 GRANT和REVOKE 句法。(你可以發(fā)覺參考6.6 權(quán)限系統(tǒng)怎樣工作很有幫助,它列出了在每個(gè)權(quán)限表中呈現(xiàn)的字段。)
user表在一個(gè)全局基礎(chǔ)上授予賦予你的權(quán)限,該權(quán)限不管當(dāng)前的數(shù)據(jù)庫(kù)是什么均適用。例如,如果user表授予你delete權(quán)限, 你可以刪除在服務(wù)器主機(jī)上從任何數(shù)據(jù)庫(kù)刪除行!換句話說,user表權(quán)限是超級(jí)用戶權(quán)限。只把user表的權(quán)限授予超級(jí)用戶如服務(wù)器或數(shù)據(jù)庫(kù)主管是明智的。對(duì)其他用戶,你應(yīng)該把在user表中的權(quán)限設(shè)成'N'并且僅在一個(gè)特定數(shù)據(jù)庫(kù)的基礎(chǔ)上授權(quán), 使用db和host表?!?br>
db和host表授予數(shù)據(jù)庫(kù)特定的權(quán)限。在范圍字段的值可以如下被指定:
通配符字符“%”和“_”可被用于兩個(gè)表的Host和Db字段?!?br>
在db表的'%'Host值意味著“任何主機(jī)”,在db表中一個(gè)空白Host值意味著“對(duì)進(jìn)一步的信息咨詢host表”。
在host表的一個(gè)'%'或空白Host值意味著“任何主機(jī)”?!?br>
在兩個(gè)表中的一個(gè)'%'或空白Db值意味著“任何數(shù)據(jù)庫(kù)”?!?br>
在兩個(gè)表中的一個(gè)空白User值匹配匿名用戶。
db和host表在服務(wù)器啟動(dòng)時(shí)被讀取和排序(同時(shí)它讀user表)。db表在Host、Db和User范圍字段上排序,并且host表在Host和Db范圍字段上排序。對(duì)于user表,排序首先放置最特定的值然后最后最不特定的值,并且當(dāng)服務(wù)器尋找匹配入條目時(shí),它使用它找到的第一個(gè)匹配?!?br>
tables_priv和columns_priv表授予表和列特定的權(quán)限。在范圍字段的值可以如下被指定:
通配符“%”和“_”可用在使用在兩個(gè)表的Host字段。
在兩個(gè)表中的一個(gè)'%'或空白Host意味著“任何主機(jī)”。
在兩個(gè)表中的Db、Table_name和Column_name字段不能包含通配符或空白。
tables_priv和columns_priv表在Host、Db和User字段上被排序。這類似于db表的排序,盡管因?yàn)橹挥蠬ost字段可以包含通配符,但排序更簡(jiǎn)單。
請(qǐng)求證實(shí)進(jìn)程在下面描述。(如果你熟悉存取檢查的源代碼,你會(huì)注意到這里的描述與在代碼使用的算法略有不同。描述等價(jià)于代碼實(shí)際做的東西;它只是不同于使解釋更簡(jiǎn)單。)
對(duì)管理請(qǐng)求(shutdown、reload等等),服務(wù)器僅檢查user表?xiàng)l目,因?yàn)槟鞘俏ㄒ恢付ü芾頇?quán)限的表。如果條目許可請(qǐng)求的!??! 作,存取被授權(quán)了,否則拒絕。例如,如果你想要執(zhí)行mysqladmin shutdown,但是你的user表?xiàng)l目沒有為你授予shutdown權(quán)限,存取甚至不用檢查db或host表就被拒絕。(因?yàn)樗麄儾话琒hutdown_priv行列,沒有這樣做的必要。)
對(duì)數(shù)據(jù)庫(kù)有關(guān)的請(qǐng)求(insert、update等等),服務(wù)器首先通過查找user表?xiàng)l目來檢查用戶的全局(超級(jí)用戶)權(quán)限。如果條目允許請(qǐng)求的!?。 ∽?,存取被授權(quán)。如果在user表中全局權(quán)限不夠,服務(wù)器通過檢查db和host表確定特定的用戶數(shù)據(jù)庫(kù)權(quán)限:
服務(wù)器在db表的Host、Db和User字段上查找一個(gè)匹配。 Host和User對(duì)應(yīng)連接用戶的主機(jī)名和MySQL用戶名。Db字段對(duì)應(yīng)用戶想要存取的數(shù)據(jù)庫(kù)。如果沒有Host和User的條目,存取被拒絕?!?br>
如果db表中的條目有一個(gè)匹配而且它的Host字段不是空白的,該條目定義用戶的數(shù)據(jù)庫(kù)特定的權(quán)限?!?br>
如果匹配的db表的條目的Host字段是空白的,它表示host表列舉主機(jī)應(yīng)該被允許存取數(shù)據(jù)庫(kù)的主機(jī)。在這種情況下,在host表中作進(jìn)一步查找以發(fā)現(xiàn)Host和Db字段上的匹配。如果沒有host表?xiàng)l目匹配,存取被拒絕。如果有匹配,用戶數(shù)據(jù)庫(kù)特定的權(quán)限以在db和host表的條目的權(quán)限,即在兩個(gè)條目都是'Y'的權(quán)限的交集(而不是并集!)計(jì)算。(這樣你可以授予在db表?xiàng)l目中的一般權(quán)限,然后用host表?xiàng)l目按一個(gè)主機(jī)一個(gè)主機(jī)為基礎(chǔ)地有選擇地限制它們。)
在確定了由db和host表?xiàng)l目授予的數(shù)據(jù)庫(kù)特定的權(quán)限后,服務(wù)器把他們加到由user表授予的全局權(quán)限中。如果結(jié)果允許請(qǐng)求的!??! 作,存取被授權(quán)。否則,服務(wù)器檢查在tables_priv和columns_priv表中的用戶的表和列權(quán)限并把它們加到用戶權(quán)限中?;诖私Y(jié)果允許或拒絕存取。
用布爾術(shù)語表示,前面關(guān)于一個(gè)用戶權(quán)限如何計(jì)算的描述可以這樣總結(jié):
global privileges
OR (database privileges AND host privileges)
OR table privileges
OR column privileges
它可能不明顯,為什么呢,如果全局user條目的權(quán)限最初發(fā)現(xiàn)對(duì)請(qǐng)求的!??! 作不夠,服務(wù)器以后把這些權(quán)限加到數(shù)據(jù)庫(kù)、表和列的特定權(quán)限。原因是一個(gè)請(qǐng)求可能要求超過一種類型的權(quán)限。例如,如果你執(zhí)行一個(gè)INSERT ... SELECT語句,你就都要insert和select權(quán)限。你的權(quán)限必須如此以便user表?xiàng)l目授予一個(gè)權(quán)限而db表?xiàng)l目授予另一個(gè)。在這種情況下,你有必要的權(quán)限執(zhí)行請(qǐng)求,但是服務(wù)器不能自己把兩個(gè)表區(qū)別開來;兩個(gè)條目授予的權(quán)限必須組合起來。
host表能被用來維護(hù)一個(gè)“安全”服務(wù)器列表。在TcX,host表包含一個(gè)在本地的網(wǎng)絡(luò)上所有的機(jī)器的表,這些被授予所有的權(quán)限?!?br>
你也可以使用host表指定不安全的主機(jī)。假定你有一臺(tái)機(jī)器public.your.domain,它位于你不認(rèn)為是安全的一個(gè)公共區(qū)域,你可以用下列的host表?xiàng)l目子允許除了那臺(tái)機(jī)器外的網(wǎng)絡(luò)上所有主機(jī)的存?。骸?br>
+--------------------+----+-
| Host | Db | ...
+--------------------+----+-
| public.your.domain | % | ... (所有權(quán)限設(shè)為 'N')
| %.your.domain | % | ... (所有權(quán)限設(shè)為 'Y')
+--------------------+----+-
當(dāng)然,你應(yīng)該總是測(cè)試你在授權(quán)表中的條目(例如,使用mysqlaccess)讓你確保你的存取權(quán)限實(shí)際上以你認(rèn)為的方式被設(shè)置?!?br>