MySQL中文參考手冊-權限

1 權限系統做什麼

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

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

2 MySQL 用戶名和密碼

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

3 使你的密碼安全

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

4  MySQL提供的權限

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

 

5 權限系統工作原理

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

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

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

 

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

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

你的身份基於2個資訊:

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

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

7 存取控制,階段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字段可以包含通配符,但排序更簡單。

 

8 權限更改何時生效

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

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

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

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

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

9 建立初始的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與伺服器連接時,你必須供應那個密碼。

 

10 向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;

 

11 怎樣設置密碼

在前面小節的例子裡說明了一個重要的原則:當你使用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密碼文件被儲存的同樣的加密值。