mysql-logo.gif (3082 bytes)MySQL中文參考手冊

譯者:晏子 (clyan@sohu.com
GB 碼主頁:http://linuxdb.yeah.net

Big5 轉碼者:statue (statue@bbs.yzu.edu.tw
詞彙轉換:彭武興 (wilson@mailbox.com.tw)
Big5 碼主頁: http://cnpa.yzu.edu.tw/~cfc/docs/mysqldoc_big5/manual_toc.html
Big5 碼分站: http://php.wilson.gs/mysqldoc/big5/manual_toc.html


第一章, 前一章, 下一章, 最後一章目錄.


6 MySQL 存取權限系統

MySQL有一個先進但非標準的安全/權限系統。本節描述它的工作原理。

6.1 權限系統做什麼

MySQL權限系統的主要功能是証實連接到一台給定主機的一個用戶,並且賦予該用戶在一個資料庫上selectinsertupdatedelete的權限。

附加的功能包括有一個匿名的用戶和對於MySQL特定的功能例如LOAD DATA INFILE進行授權及管理操作的能力。

6.2 MySQL 用戶名和密碼

MySQL使用用戶名和密碼的方法與Unix或Windows使用的方式有很多不同之處:

6.3 與MySQL伺服器連接

當你想要存取一個MySQL伺服器時,MySQL客戶程式一般要求你指定連接參數:你想要聯接的主機、你的用戶名和你的密碼。例如,mysql客戶可以像這樣啟動(可選的參數被包括在“[”“]”之間):

shell> mysql [-h host_name][-u user_name][-pyour_pass ]

-h, -u-p選項的另一種形式是--host=host_name--user=user_name--password=your_pass。注意在-p--password=與跟隨它後面的密碼之間沒有空格

注意:在命令行上指定一個密碼是不安全的!隨後在你系統上的任何用戶可以通過打類似這樣的命令發現你的密碼:ps auxww。見4.15.4 選項文件

對於命令行沒有的聯接參數,mysql使用內定值:

這樣, 對一個Unix用戶joe,下列命令是等價的:

shell>mysql -h localhost -u joe 
shell>mysql -h localhost 
shell>mysql -u joe 
shell>mysql

其它MySQL客戶程式有同樣表現。

在Unix系統上,當你進行一個連接時,你可以指定要使用的不同的內定值,這樣你不必每次在你調用一個客戶程式是在命令行上輸入他們。這可以有很多方法做到:

如果連接參數以多種方法被指定,在命令行上被指定的值優先於在配置文件和環境變數中指定的值,而在配置文件指定的值優先於在環境變數指定的值。

6.4 使你的密碼安全

以一種暴露的可被其他用戶發現的方式指定你的密碼是不妥當的。當你運行客戶程式時,你可以使用下列方法指定你的密碼,還有每個方法的風險評估:

總之,最安全的方法是讓客戶程式提示密碼或在一個適當保護的“.my.cnf”文件中指定密碼。

6.5   MySQL提供的權限

權限資訊用userdbhosttables_privcolumns_priv表被儲存在mysql資料庫中(即在名為mysql的資料庫中)。在MySQL啟動時和在6.9 權限修改何時生效所說的情況時,伺服器讀入這些資料庫表內容。

本手冊所用的涉及由MySQL提供的權限名稱顯示在下表,還有在授權表中每個權限的表列名稱和每個權限有關的上下文:

權限 上下文
select Select_priv
insert Insert_priv
update Update_priv
delete Delete_priv
index Index_priv
alter Alter_priv
create Create_priv 資料庫、表或索引
drop Drop_priv 資料庫或表
grant Grant_priv 資料庫或表
references References_priv 資料庫或表
reload Reload_priv 伺服器管理
shutdown Shutdown_priv 伺服器管理
process Process_priv 伺服器管理
file File_priv 在伺服器上的文件存取

selectinsertupdatedelete權限允許你在一個資料庫現有的表上實施操作。

SELECT語句只有在他們真正從一個表中檢索行是才需要select權限,你可以執行某個SELECT語句,甚至沒有任何到伺服器上的資料庫裡的存取任何東西的許可。例如,你可使用mysql客戶作為一個簡單的計算器:

mysql> SELECT 1+1;
mysql> SELECT PI()*2;

index權限允許你創建或拋棄(刪除)索引。

alter權限允許你使用ALTER TABLE

createdrop權限允許你創建新的資料庫和表,或拋棄(刪除)現存的資料庫和表。

注意:如果你將mysql資料庫的drop權限授予一個用戶,該用戶能拋棄儲存了MySQL存取權限的資料庫!

grant權限允許你把你自己擁有的那些權限授給其他的用戶。

file權限給予你用LOAD DATA INFILESELECT ... INTO OUTFILE語句讀和寫伺服器上的文件,任何被授予這個權限的用戶都能讀或寫MySQL伺服器能讀或寫的任何文件。

其餘的權限用於管理性操作,它使用mysqladmin程式實施。下表顯示mysqladmin支配每個管理性權限允許你執行的命令:

優惠 權限擁有者允許執行的命令
reload reload, refresh, flush-privileges, flush-hosts, flush-logs, flush-tables
shutdown shutdown
precess processlist, kill

reload命令告訴伺服器再讀入授權表,refresh命令清洗所有表並打開和關閉記錄文件,flush-privilegesreload的一個同義詞,其它flush-*命令執行類似refresh的功能,但是範圍更有限,並且在某些情況下可能更好用。例如,如果你只是想清洗記錄文件,flush-logsrefresh是更好的選擇。

shutdown命令關掉伺服器。

processlist命令顯示在伺服器內執行的執行緒的資訊。kill命令殺死伺服器執行緒。你總是能顯示或殺死你自己的執行緒,但是你需要process權限來顯示或殺死其他用戶啟動的執行緒。

總的說來,只授予權限給需要他們的那些用戶是一個好主意,但是你應該在授予某個權限時試驗特定的警告:

有一些事情你不能用MySQL權限系統做到:

6.6 權限系統工作原理

MySQL權限系統保証所有的用戶可以嚴格地做他們假定被允許做的事情。當你連接一個MySQL伺服器時, 你的身份由你從那連接的主機你指定的用戶名來決定,系統根據你的身份和你想做什麼來授予權限。

MySQL在認定身份中考慮你的主機名和用戶名字,是因為有很小的原因假定一個給定的用戶在網際網路上屬於同一個人。例如,用戶從whitehouse.gov連接的bill不必和從mosoft.com連接bill是同一個人。 MySQL通過允許你區分在不同的主機上碰巧有同樣名字用戶來處理它:你可以對從whitehouse.gov連接授與bill一個權限集,而為從microsoft.com的連接授予一個不同的權限集。

MySQL存取控制包含2個階段:

伺服器在存取控制的兩個階段使用在mysql的資料庫中的userdbhost表,在這些授權表中字段如下:

表名稱 user db host
範圍字段 Host Host Host
User Db Db
Password User
權限字段 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

對存取控制的第二階段(請求証實),如果請求涉及表,伺服器可以另外參考tables_privcolumns_priv表。這些表的字段如下:

表名稱 tables_priv columns_priv
範圍字段 Host Host
Db Db
User User
Table_name Table_name
Column_name
權限字段 Table_priv Column_priv
Column_priv
其他字段 Timestamp Timestamp
Grantor

每個授權表包含範圍字段和權限字段。

範圍字段決定表中每個條目的範圍,即,條目適用的上下文。例如, 一個user表條目的HostUser值為'thomas.loc.gov''bob'將被用於証實來自主機thomas.loc.govbob對伺服器的連接。同樣,一個db表條目的HostUserDb字段的值是'thomas.loc.gov''bob''reports'將用在bob從主機聯接thomas.loc.gov存取reports資料庫的時候。 tables_privcolumns_priv表包含範圍字段,指出每個條目適用的表或表/列的組合。

對於檢查存取的用途,比較Host值是忽略大小寫的。UserPassword、DbTable_name值是區分大小寫的。Column_name值在MySQL3.22.12或以後版本是忽略大小寫的。

權限字段指出由一個表條目授予的權限,即,可實施什麼操作。伺服器組合各種的授權表的資訊形成一個用戶權限的完整描述。為此使用的規則在6.8 存取控制, 階段2:請求証實描述。

範圍字段是字符串,如下所述﹔每個字段的內定值是空字符串:

字段名 類型
Host CHAR(60)
User CHAR(16)
Password CHAR(16)
Db CHAR(64) (tables_privcolumns_priv表為CHAR(60)

userdbhost表中,所有權限字段被聲明為ENUM('N','Y')--每一個都可有值'N''Y',並且內定值是'N'.

tables_privcolumns_priv表中,權限字段被聲明為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'

簡單地說,伺服器使用這樣的授權表:

注意管理權限(reload, shutdown, 等等)僅在user表中被指定。這是因為管理性操作是伺服器本身的操作並且不是特定資料庫,因此沒有理由在其他授權表中列出這樣的權限。事實上,只需要請教user表來決定你是否執行一個管理操作。

file權限也僅在user表中指定。它不是管理性權限,但你讀或謝在伺服器主機上的文件的的能力獨立於你正在存取的資料庫。

mysqld伺服器啟動時,讀取一次授權表內容。對授權表的更改生效在6.9 權限更改何時生效描述。

當你修改授權表的內容時,確保你按你想要的方式更改權限設置是一個好主意。為幫助診斷問題,見6.13 “存取拒絕引起錯誤的原因。對於安全問題上的忠告,見6.14 怎麼對使MySQL安全對抗解密高手

一個有用的診斷工具是mysqlaccess腳本,由Carlier Yves 提供給MySQL分發。使用--help選項調用mysqlaccess查明它怎樣工作。注意:mysqlaccess僅用userdbhost表僅檢查存取。它不檢查表或列級權限。

6.7 存取控制, 階段1:連接証實

當你試圖聯接一個MySQL伺服器時,伺服器基於你的身份和你是否能通過供應正確的密碼驗証身份來接受或拒絕連接。如果不是,伺服器完全具結你的存取,否則,伺服器接受連接,然後進入階段2並且等待請求。

你的身份基於2個資訊:

身份檢查使用3個user表(Host, UserPassword)範圍字段執行。伺服器只有在一個user表條目匹配你的主機名和用戶名並且你提供了正確的密碼時才接受連接。

user表範圍字段可以如下被指定:

非空白Password值代表加密的密碼。 MySQL不以任何人可以看的純文本格式儲存密碼,相反,正在試圖聯接的一個用戶提供的密碼被加密(使用PASSWORD()函數),並且與儲存了user表中的已經加密的版本比較。如果他們匹配,密碼是正確的。

下面的例子顯示出各種user表中HostUser條目的值的組合如何應用於到來的連接:

Host User 被條目匹配的連接
'thomas.loc.gov' 'fred' fred, 從thomas.loc.gov 連接
'thomas.loc.gov' '' 任何用戶, 從thomas.loc.gov連接
'%' 'fred' fred, 從任何主機連接
'%' '' 任何用戶, 從任何主機連接
'%.loc.gov' 'fred' fred, 從在loc.gov域的任何主機連接
'x.y.%' 'fred' fred, 從x.y.netx.y.com,x.y.edu等聯接。(這或許無用)
'144.155.166.177' 'fred' fred, 從有144.155.166.177 IP 地址的主機連接
'144.155.166.%' 'fred' fred, 從144.155.166 C類子網的任何主機連接

既然你能在Host字段使用IP通配符值(例如,'144.155.166.%'匹配在一個子網上的每台主機),有可能某人可能企圖探究這種能力,通過命名一台主機為144.155.166.somewhere.com。為了阻止這樣的企圖,MySQL不允許匹配以數字和一個點起始的主機名,這樣,如果你用一個命名為類似1.2.foo.com的主機,它的名字決不會匹配授權表中Host列。只有一個IP數字能匹配IP通配符值。

一個到來的連接可以被在user表中的超過一個條目匹配。例如,一個由fredthomas.loc.gov的連接匹配多個條目如上所述。如果超過一個匹配,伺服器怎麼選擇使用哪個條目呢?伺服器在啟動時讀入user表後通過排序來解決這個問題,然後當一個用戶試圖連接時,以排序的順序瀏覽條目,第一個匹配的條目被使用。

user表排序工作如下,假定user表看起來像這樣:

+-----------+----------+-
| Host      | User     | ...
+-----------+----------+-
| %         | root     | ...
| %         | jeffrey  | ...
| localhost | root     | ...
| localhost |          | ...
+-----------+----------+-

當伺服器在表中讀取時,它以最特定的Host值為先的次序排列('%'Host列裡意味著“任何主機”並且是最不特定的)。有相同Host值的條目以最特定的User值為先的次序排列(一個空白User值意味著“任何用戶”並且是最不特定的)。最終排序的user表看起來像這樣:

+-----------+----------+-
| Host      | User     | ...
+-----------+----------+-
| localhost | root     | ...
| localhost |          | ...
| %         | jeffrey  | ...
| %         | root     | ...
+-----------+----------+-

當一個連接被嘗試時,伺服器瀏覽排序的條目並使用找到的第一個匹配。對於由jeffreylocalhost的一個連接,在Host列的'localhost'條目首先匹配。那些有空白用戶名的條目匹配連接的主機名和用戶名。('%'/'jeffrey'條目也將匹配,但是它不是在表中的第一匹配。)

這是另外一個例子。假定user桌子看起來像這樣:

+----------------+----------+-
| Host           | User     | ...
+----------------+----------+-
| %              | jeffrey  | ...
| thomas.loc.gov |          | ...
+----------------+----------+-

排序後的表看起來像這樣:

+----------------+----------+-
| Host           | User     | ...
+----------------+----------+-
| thomas.loc.gov |          | ...
| %              | jeffrey  | ...
+----------------+----------+-

一個由jeffreythomas.loc.gov的連接被第一個條目匹配,而一個由jeffreywhitehouse.gov的連接被第二個匹配。

普遍的誤解是認為,對一個給定的用戶名,當伺服器試圖對連接尋找匹配時,明確命名那個用戶的所有條目將首先被使用。這明顯不是事實。先前的例子說明了這點,在那裡一個由jeffreythomas.loc.gov的連接沒被包含'jeffrey'作為User字段值的條目匹配,但是由沒有用戶名的題目匹配!

如果你有伺服器連接的問題,列印出user表並且手工排序它看看第一個匹配在哪兒進行。

6.8 存取控制,階段2:請求証實

一旦你建立了一個連接,伺服器進入階段2。對在此連接上進來的每個請求,伺服器檢查你是否有足夠的權限來執行它,它基於你希望執行的操作類型。這正是在授權表中的權限字段發揮作用的地方。這些權限可以來子userdbhosttables_privcolumns_priv表的任何一個。授權表用GRANTREVOKE命令操作。見7.26 GRANTREVOKE 句法。(你可以發覺參考6.6 權限系統怎樣工作很有幫助,它列出了在每個權限表中呈現的字段。)

user表在一個全局基礎上授予賦予你的權限,該權限不管當前的資料庫是什麼均適用。例如,如果user表授予你delete權限, 你可以刪除在伺服器主機上從任何資料庫刪除行!換句話說,user表權限是超級用戶權限。只把user表的權限授予超級用戶如伺服器或資料庫主管是明智的。對其他用戶,你應該把在user表中的權限設成'N'並且僅在一個特定資料庫的基礎上授權, 使用dbhost表。

dbhost表授予資料庫特定的權限。在範圍字段的值可以如下被指定:

dbhost表在伺服器啟動時被讀取和排序(同時它讀user表)。db表在HostDbUser範圍字段上排序,並且host表在HostDb範圍字段上排序。對於user表,排序首先放置最特定的值然後最後最不特定的值,並且當伺服器尋找匹配入條目時,它使用它找到的第一個匹配。

tables_privcolumns_priv表授予表和列特定的權限。在範圍字段的值可以如下被指定:

tables_privcolumns_priv表在HostDbUser字段上被排序。這類似於db表的排序,盡管因為只有Host字段可以包含通配符,但排序更簡單。

請求証實進程在下面描述。(如果你熟悉存取檢查的原始程式,你會注意到這裡的描述與在代碼使用的算法略有不同。描述等價於代碼實際做的東西﹔它只是不同於使解釋更簡單。)

對管理請求(shutdownreload等等),伺服器僅檢查user表條目,因為那是唯一指定管理權限的表。如果條目許可請求的操作,存取被授權了,否則拒絕。例如,如果你想要執行mysqladmin shutdown,但是你的user表條目沒有為你授予shutdown權限,存取甚至不用檢查dbhost表就被拒絕。(因為他們不包含Shutdown_priv行列,沒有這樣做的必要。)

對資料庫有關的請求(insertupdate等等),伺服器首先通過查找user表條目來檢查用戶的全局(超級用戶)權限。如果條目允許請求的操作,存取被授權。如果在user表刈釪局權限不夠,伺服器通過檢查dbhost表確定特定的用戶資料庫權限:

  1. 伺服器在db表的HostDbUser字段上查找一個匹配。 HostUser對應連接用戶的主機名和MySQL用戶名。Db字段對應用戶想要存取的資料庫。如果沒有HostUser的條目,存取被拒絕。
  2. 如果db表中的條目有一個匹配而且它的Host字段不是空白的,該條目定義用戶的資料庫特定的權限。
  3. 如果匹配的db表的條目的Host字段是空白的,它表示host表列舉主機應該被允許存取資料庫的主機。在這種情況下,在host表中作進一步查找以發現HostDb字段上的匹配。如果沒有host表條目匹配,存取被拒絕。如果有匹配,用戶資料庫特定的權限以在dbhost表的條目的權限,即在兩個條目都是'Y'的權限的交集(而不是並集!)計算。(這樣你可以授予在db表條目中的一般權限,然後用host表條目按一個主機一個主機為基礎地有選擇地限制它們。)

在確定了由dbhost表條目授予的資料庫特定的權限後,伺服器把他們加到由user表授予的全局權限中。如果結果允許請求的操作,存取被授權。否則,伺服器檢查在tables_privcolumns_priv表中的用戶的表和列權限並把它們加到用戶權限中。基於此結果允許或拒絕存取。

用布爾術語表示,前面關於一個用戶權限如何計算的描述可以這樣總結:

global privileges
OR (database privileges AND host privileges)
OR table privileges
OR column privileges

它可能不明顯,為什麼呢,如果全局user條目的權限最初發現對請求的操作不夠,伺服器以後把這些權限加到資料庫、表和列的特定權限。原因是一個請求可能要求超過一種類型的權限。例如,如果你執行一個INSERT ... SELECT語句,你就都要insertselect權限。你的權限必須如此以便user表條目授予一個權限而db表條目授予另一個。在這種情況下,你有必要的權限執行請求,但是伺服器不能自己把兩個表區別開來﹔兩個條目授予的權限必須組合起來。

host表能被用來維護一個“安全”伺服器列表。在TcX,host表包含一個在本地的網路上所有的機器的表,這些被授予所有的權限。

你也可以使用host表指定安全的主機。假定你有一台機器public.your.domain,它位於你不認為是安全的一個公共區域,你可以用下列的host表條目子允許除了那台機器外的網路上所有主機的存取:

+--------------------+----+-
| Host               | Db | ...
+--------------------+----+-
| public.your.domain | %  | ... (所有權限設為 'N')
| %.your.domain      | %  | ... (所有權限設為 'Y')
+--------------------+----+-

當然,你應該總是測試你在授權表中的條目(例如,使用mysqlaccess)讓你確保你的存取權限實際上以你認為的方式被設置。

6.9 權限更改何時生效

mysqld啟動時,所有的授權表內容被讀進儲存器並且從那點生效。

GRANT、REVOKE或SET PASSWORD對授權表施行的修改會立即被伺服器注意到。

如果你手工地修改授權表(使用INSERT、UPDATE等等),你應該執行一個FLUSH PRIVILEGES語句或運行mysqladmin flush-privileges告訴伺服器再裝載授權表,否則你的改變將不生效,除非你重啟伺服器。

當伺服器注意到授權表被改變了時,現存的客戶連接有如下影響:

全局權限的改變和密碼改變在下一次客戶連接時生效。

6.10 建立初始的MySQL權限

在安裝MySQL後,你通過運行scripts/mysql_install_db安裝初始的存取權限。見4.7.1 快速安裝概述scripts/mysql_install_db腳本啟動mysqld伺服器,然後初始化授權表,包含下列權限集合:

注意:對Win32的初始權限是不同的。見4.12.4 在Win32上運行MySQL

既然你的安裝初始時廣開大門,你首先應該做的事情之一是為MySQL root用戶指定一個密碼。你可以做如下(注意,你使用PASSWORD()函數指定密碼):

shell> mysql -u root mysql
mysql> UPDATE user SET Password=PASSWORD('new_password')
           WHERE user='root';
mysql> FLUSH PRIVILEGES;

MySQL 3.22和以上版本中,你可以使用SET PASSWORD語句:

shell> mysql -u root mysql
mysql> SET PASSWORD FOR root=PASSWORD('new_password');

設置密碼的另一種方法是使用mysqladmin命令:

shell> mysqladmin -u root password new_password 

注意:如果你使用第一種方法在user表裡直接更新密碼,你必須告訴伺服器再次讀入授權表(用FLUSH PRIVILEGES),因為否則改變將不被注意到。

一旦root密碼被設置,此後當你作為root與伺服器連接時,你必須供應那個密碼。

你可能希望讓root密碼為空白以便當你施行附加的安裝時,你不需要指定它或測試,但是保証在任何真實的生產工作中使用你的安裝之前,設置它。

看看scripts/mysql_install_db腳本,看它如何安裝內定的權限。你可用它作為一個研究如何增加其他用戶的基礎。

如果你想要初始的權限不同於上面描述的那些,在你運行mysql_install_db之前,你可以修改它。

為了完全重建權限表,刪除在包含mysql資料庫的目錄下所有“*.frm”,“*.MYI”“*.MYD”文件。(這是在資料庫目錄下面命名為“mysql”的目錄,當你運行mysqld --help時,它被列出。)然後運行mysql_install_db腳本,可能在首先編輯它擁有你想要的權限之後。

注意:對於比MySQL 3.22.10舊的版本,你不應該刪除“*.frm”文件。如果你偶然做了,你應該在運行mysql_install_db之前你的MySQL分發中拷回它們。

6.11 向MySQL增加新用戶權限

你可以有2個不同的方法增加用戶:通過使用GRANT語句或通過直接操作MySQL授權表。比較好的方法是使用GRANT語句,因為他們是更簡明並且好像錯誤少些。

下面的例子顯示出如何使用mysql客戶安裝新用戶。這些例子假定權限根據以前的章節描述的內定被安裝。這意味著為了改變,你必須在mysqld正在運行同一台機器上,你必須作為MySQL root用戶連接,並且root用戶必須對mysql資料庫有insert權限和reload管理權限。另外,如果你改變了root用戶密碼,你必須如下的mysql命令指定它。

你可以通過發出GRANT語句增加新用戶:

shell> mysql --user=root mysql
mysql> GRANT ALL PRIVILEGES ON *.* TO monty@localhost
           IDENTIFIED BY 'something' WITH GRANT OPTION;
mysql> GRANT ALL PRIVILEGES ON *.* TO monty@"%"
           IDENTIFIED BY 'something' WITH GRANT OPTION;
mysql> GRANT RELOAD,PROCESS ON *.* TO admin@localhost;
mysql> GRANT USAGE ON *.* TO dummy@localhost;

這些GRANT語句安裝3個新用戶:

monty
可以從任何地方連接伺服器的一個完全的超級用戶,但是必須使用一個密碼('something'做這個。注意,我們必須對monty@localhostmonty@"%"發出GRANT語句。如果我們增加localhost條目,對localhost的匿名用戶條目在我們從本地主機連接接時由mysql_install_db創建的條目將優先考慮,因為它有更特定的Host字段值,所以以user表排列順序看更早到來。
admin
可以從localhost沒有一個密碼進行連接並且被授予reloadprocess管理權限的用戶。這允許用戶執行mysqladmin reloadmysqladmin refreshmysqladmin flush-*命令,還有mysqladmin processlist。沒有授予資料庫有關的權限。他們能在以後通過發出另一個GRANT語句授權。
dummy
可以不用一個密碼連接的一個用戶,但是只能從本地主機。全局權限被設置為'N'--USAGE權限類型允許你無需權限就可設置一個用戶。它假定你將在以後授予資料庫相關的權限。

你也可以直接通過發出INSERT語句增加同樣的用戶存取資訊,然後告訴伺服器再次裝入授權表:

shell> mysql --user=root mysql
mysql> INSERT INTO user VALUES('localhost','monty',PASSWORD('something'),
                'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y')
mysql> INSERT INTO user VALUES('%','monty',PASSWORD('something'),
                'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y')
mysql> INSERT INTO user SET Host='localhost',User='admin',
                 Reload_priv='Y', Process_priv='Y';
mysql> INSERT INTO user (Host,User,Password)
                        VALUES('localhost','dummy','');
mysql> FLUSH PRIVILEGES;

取決於你的MySQL版本,對上述,你可能必須使用一個不同數目'Y'值(在3.22.11以前的版本有更少的權限列)。對admin用戶,只用在3.22.11開始的版本具有的更加可讀的INSERT擴充的語法。

注意,為了設置一個超級用戶,你只需創造一個user表條目,其權限字段設為'Y'。不需要dbhost表的條目。

user表中的權限列不是由最後一個INSERT語句明確設置的(對dummy用戶),因此那些列被賦予內定值'N'。這是GRANT USAGE做的同樣的事情。

下列例子增加一個用戶custom,他能從主機localhostserver.domainwhitehouse.gov連接。他只想要從localhost存取bankaccount資料庫,從whitehouse.gov存取expenses資料庫和從所有3台主機存取customer資料庫。他想要從所有3台主機上使用密碼stupid

為了使用GRANT語句設置個用戶的權限,運行這些命令:

shell> mysql --user=root mysql
mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
           ON bankaccount.*
           TO custom@localhost
           IDENTIFIED BY 'stupid';
mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
           ON expenses.*
           TO custom@whitehouse.gov
           IDENTIFIED BY 'stupid';
mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
           ON customer.*
           TO custom@'%'
           IDENTIFIED BY 'stupid';

通過直接修改授權表設置用戶權限,運行這些命令(注意,在結束時FLUSH PRIVILEGES):

shell> mysql --user=root mysql
mysql> INSERT INTO user (Host,User,Password)
       VALUES('localhost','custom',PASSWORD('stupid'));
mysql> INSERT INTO user (Host,User,Password)
       VALUES('server.domain','custom',PASSWORD('stupid'));
mysql> INSERT INTO user (Host,User,Password)
       VALUES('whitehouse.gov','custom',PASSWORD('stupid'));
mysql> INSERT INTO db
       (Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv,
        Create_priv,Drop_priv)
       VALUES
       ('localhost','bankaccount','custom','Y','Y','Y','Y','Y','Y');
mysql> INSERT INTO db
       (Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv,
        Create_priv,Drop_priv)
       VALUES
       ('whitehouse.gov','expenses','custom','Y','Y','Y','Y','Y','Y');
mysql> INSERT INTO db
       (Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv,
        Create_priv,Drop_priv)
       VALUES('%','customer','custom','Y','Y','Y','Y','Y','Y');
mysql> FLUSH PRIVILEGES;

頭3個INSERT語句增加user表條目,允許用戶custom用給定密碼從不同的主機進行連接,但是沒有授予任何許可(所有權限被設置為內定值'N')。後3個INSERT語句增加db表條目,授予custombankaccountexpensescustomer資料庫權限,但是只能在從正確的主機存取時。通常,在授權表直接被修改時,伺服器必須被告知再次裝入他們(用FLUSH PRIVILEGES)以便使權限修改生效。

如果你想要給特定的用戶從一個給定的域上的任何機器上存取權限,你可以發出一個如下的GRANT語句:

mysql> GRANT ...
           ON *.*
           TO myusername@"%.mydomainname.com"
           IDENTIFIED BY 'mypassword';

為了通過直接修改授權表做同樣的事情,這樣做:

mysql> INSERT INTO user VALUES ('%.mydomainname.com', 'myusername',
           PASSWORD('mypassword'),...);
mysql> FLUSH PRIVILEGES;

你也可以使用xmysqladminmysql_webadmin甚至xmysql在授權表中插入、改變和更新值。你可以在MySQLContrib目錄找到這些實用程式。

6.12 怎樣設置密碼

在前面小節的例子裡說明了一個重要的原則:當你使用INSERTUPDATE語句儲存一個非空的密碼時,你必須使用PASSWORD()函數加密它。這是因為在user表刈脛加密形式儲存密碼,而不是作為純文本。如果你忘記這個事實,你可能像這樣試圖設置密碼:

shell> mysql -u root mysql 
mysql> INSERT INTO user (Host,User,Password) VALUES('%','jeffrey','biscuit'); 
mysql> FLUSH PRIVILEGES

結果是純文本值'biscuit'作為密碼被儲存在user表中。在用戶jeffrey試圖用這個密碼連接伺服器時,mysql客戶用PASSWORD()加密它並且將結果送給伺服器,伺服器比較在user表中的值(它是純文本值'biscuit')和加密的密碼(而不是 'biscuit'),比較失敗並且伺服器拒絕連接:

shell> mysql -u jeffrey -pbiscuit test
Access denied

因為當他們被插入user表時,密碼必須被加密,相反,INSERT語句應該像這樣被指定:

mysql> INSERT INTO user (Host,User,Password)
       VALUES('%','jeffrey',PASSWORD('biscuit'));

當你使用SET PASSWORD語句時,你也必須使用PASSWORD()函數:

mysql> SET PASSWORD FOR jeffrey@"%" = PASSWORD('biscuit'); 

如果你使用GRANT ... IDENTIFIED BY語句或mysqladmin password命令設置密碼,PASSWORD()函數是不必要的。他們都考慮到為你加密密碼,多以你可像這樣指定一個密碼'biscuit'

mysql> GRANT USAGE ON *.* TO jeffrey@"%" IDENTIFIED BY 'biscuit';

shell> mysqladmin -u jeffrey password biscuit 

注意: PASSWORD()不是以在Unix密碼加密的同樣方法施行密碼加密。你不應該假定如果你的Unix密碼和你的MySQL密碼是一樣的,PASSWORD()將導致與在Unix密碼文件被儲存的同樣的加密值。見6.2 MySQL 用戶名和密碼

6.13 Access denied錯誤的原因

當你試著聯接MySQL伺服器時,如果你碰到Access denied錯誤,顯示在下面的表指出一些你能用來更正這個問題的動作:

6.14 怎樣使MySQL安全以對抗解密高手

當你連接一個MySQL伺服器時,你通常應該使用一個密碼。密碼不以明文在連接上傳輸。

所有其它資訊作為能被任何人讀懂的文本被傳輸。如果你擔心這個,你可使用壓縮協議(MySQL3.22和以上版本)使事情變得更難。甚至為了使一切更安全,你應該安裝ssh(見http://www.cs.hut.fi/ssh)。用它,你能在一個MySQL伺服器與一個MySQL客戶之間得到一個加密的TCP/IP連接。

為了使一個MySQL系統安全,強烈要求你考慮下列建議:

下列mysqld選項影響安全:

--secure
gethostbyname()系統調用返回的IP數字被檢查,確保他們解析回到原來的主機名。這對某些外人通過模仿其它主機獲得存取權限變得更難。這個選項也增加一些聰明的主機名檢查。在MySQL3.21裡,選擇內定是關掉的,因為它有時它花很長時間執行反向解析。MySQL 3.22緩存主機名並內定地啟用了這個選項。
--skip-grant-tables
這個選項導致伺服器根本不使用權限系統。這給每個人以完全存取所有的資料庫的權力!(通過執行mysqladmin reload,你能告訴一個正在運行的伺服器再次開始使用授權表。)
--skip-name-resolve
主機名不被解析。所有在授權表的Host的列值必須是IP數字或localhost
--skip-networking
在網路上不允許TCP/IP連接。所有到mysqld的連接必須經由Unix套接字進行。這個選項對使用MIT-pthreads的系統是不合適的,因為MIT-pthreads包不支援Unix套接字。

第一章, 前一章, 下一章, 最後一章目錄