?? manual_privilege_system.html
字號:
<p>如果你想要初始的權限不同于上面描述的那些,在你運行<code>mysql_install_db</code>之前,你可以修改它。
</p>
<p>為了完全重建權限表,刪除在包含<code>mysql</code>數據庫的目錄下所有<tt>“*.frm”</tt>,<tt>“*.MYI”</tt>和<tt>“*.MYD”</tt>文件。(這是在數據庫目錄下面命名為<tt>“mysql”</tt>的目錄,當你運行<code>mysqld
--help</code>時,它被列出。)然后運行<code>mysql_install_db</code>腳本,可能在首先編輯它擁有你想要的權限之后。
</p>
<p><strong>注意</strong>:對于比<strong>MySQL</strong> 3.22.10舊的版本,你不應該刪除<tt>“*.frm”</tt>文件。如果你偶然做了,你應該在運行<code>mysql_install_db</code>之前你的<strong>MySQL</strong>分發中拷回它們。
</p>
<h2><a NAME="Adding_users" HREF="manual_toc.html#Adding_users">6.11 向MySQL增加新用戶權限</a></h2>
<p>你可以有2個不同的方法增加用戶:通過使用<code>GRANT</code>語句或通過直接操作<strong>MySQL</strong>授權表。比較好的方法是使用<code>GRANT</code>語句,因為他們是更簡明并且好像錯誤少些。
</p>
<p>下面的例子顯示出如何使用<code>mysql</code>客戶安裝新用戶。這些例子假定權限根據以前的章節描述的缺省被安裝。這意味著為了改變,你必須在<code>mysqld</code>正在運行同一臺機器上,你必須作為<strong>MySQL</strong>
<code>root</code>用戶連接,并且<code>root</code>用戶必須對<code>mysql</code>數據庫有<strong>insert</strong>權限和<strong>reload</strong>管理權限。另外,如果你改變了<code>root</code>用戶口令,你必須如下的<code>mysql</code>命令指定它。
</p>
<p>你可以通過發出<code>GRANT</code>語句增加新用戶: </p>
<pre>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;
</pre>
<p>這些<code>GRANT</code>語句安裝3個新用戶:
<dl COMPACT="Adding_users">
<dt><code>monty</code> </dt>
<dd>可以從任何地方連接服務器的一個完全的超級用戶,但是必須使用一個口令(<code>'something'</code>做這個。注意,我們必須對<code>monty@localhost</code>和<code>monty@"%"</code>發出<code>GRANT</code>語句。如果我們增加<code>localhost</code>條目,對<code>localhost</code>的匿名用戶條目在我們從本地主機連接接時由<code>mysql_install_db</code>創建的條目將優先考慮,因為它有更特定的<code>Host</code>字段值,所以以<code>user</code>表排列順序看更早到來。</dd>
<dt><code>admin</code> </dt>
<dd>可以從<code>localhost</code>沒有一個口令進行連接并且被授予<strong>reload</strong>和<strong>process</strong>管理權限的用戶。這允許用戶執行<code>mysqladmin
reload</code>、<code>mysqladmin refresh</code>和<code>mysqladmin flush-*</code>命令,還有<code>mysqladmin
processlist</code>。沒有授予數據庫有關的權限。他們能在以后通過發出另一個<code>GRANT</code>語句授權。
</dd>
<dt><code>dummy</code> </dt>
<dd>可以不用一個口令連接的一個用戶,但是只能從本地主機。全局權限被設置為<code>'N'</code>--<code>USAGE</code>權限類型允許你無需權限就可設置一個用戶。它假定你將在以后授予數據庫相關的權限。
</dd>
</dl>
<p>你也可以直接通過發出<code>INSERT</code>語句增加同樣的用戶存取信息,然后告訴服務器再次裝入授權表:
</p>
<pre>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;
</pre>
<p>取決于你的<strong>MySQL</strong>版本,對上述,你可能必須使用一個不同數目<code>'Y'</code>值(在3.22.11以前的版本有更少的權限列)。對<code>admin</code>用戶,只用在3.22.11開始的版本具有的更加可讀的<code>INSERT</code>擴充的語法。
</p>
<p>注意,為了設置一個超級用戶,你只需創造一個<code>user</code>表條目,其權限字段設為<code>'Y'</code>。不需要<code>db</code>或<code>host</code>表的條目。
</p>
<p>在<code>user</code>表中的權限列不是由最后一個<code>INSERT</code>語句明確設置的(對<code>dummy</code>用戶),因此那些列被賦予缺省值<code>'N'</code>。這是<code>GRANT
USAGE</code>做的同樣的事情。 </p>
<p>下列例子增加一個用戶<code>custom</code>,他能從主機<code>localhost</code>、<code>server.domain</code>和<code>whitehouse.gov</code>連接。他只想要從<code>localhost</code>存取<code>bankaccount</code>數據庫,從<code>whitehouse.gov</code>存取<code>expenses</code>數據庫和從所有3臺主機存取<code>customer</code>數據庫。他想要從所有3臺主機上使用口令<code>stupid</code>。
</p>
<p>為了使用<code>GRANT</code>語句設置個用戶的權限,運行這些命令: </p>
<pre>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';
</pre>
<p>通過直接修改授權表設置用戶權限,運行這些命令(注意,在結束時<code>FLUSH
PRIVILEGES</code>): </p>
<pre>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;
</pre>
<p>頭3個<code>INSERT</code>語句增加<code>user</code>表條目,允許用戶<code>custom</code>用給定口令從不同的主機進行連接,但是沒有授予任何許可(所有權限被設置為缺省值<code>'N'</code>)。后3個<code>INSERT</code>語句增加<code>db</code>表條目,授予<code>custom</code>以<code>bankaccount</code>、<code>expenses</code>和<code>customer</code>數據庫權限,但是只能在從正確的主機存取時。通常,在授權表直接被修改時,服務器必須被告知再次裝入他們(用<code>FLUSH
PRIVILEGES</code>)以便使權限修改生效。</p>
<p>如果你想要給特定的用戶從一個給定的域上的任何機器上存取權限,你可以發出一個如下的<code>GRANT</code>語句:
</p>
<pre>mysql> GRANT ...
ON *.*
TO myusername@"%.mydomainname.com"
IDENTIFIED BY 'mypassword';
</pre>
<p>為了通過直接修改授權表做同樣的事情,這樣做: </p>
<pre>mysql> INSERT INTO user VALUES ('%.mydomainname.com', 'myusername',
PASSWORD('mypassword'),...);
mysql> FLUSH PRIVILEGES;
</pre>
<p>你也可以使用<code>xmysqladmin</code>、<code>mysql_webadmin</code>甚至<code>xmysql</code>在授權表中插入、改變和更新值。你可以在<strong>MySQL</strong>的<a HREF="http://www.mysql.com/Contrib/">Contrib目錄</a>找到這些實用程序。 </p>
<h2><a NAME="Passwords" HREF="manual_toc.html#Passwords">6.12 怎樣設置口令</a></h2>
<p>在前面小節的例子里說明了一個重要的原則:當你使用<code>INSERT</code>或<code>UPDATE</code>語句存儲一個非空的口令時,你必須使用<code>PASSWORD()</code>函數加密它。這是因為在<code>user</code>表中以加密形式存儲口令,而不是作為純文本。如果你忘記這個事實,你可能像這樣試圖設置口令:
</p>
<pre>shell> mysql -u root mysql
mysql> INSERT INTO user (Host,User,Password) VALUES('%','jeffrey','biscuit');
mysql> FLUSH PRIVILEGES
</pre>
<p>結果是純文本值<code>'biscuit'</code>作為口令被存儲在<code>user</code>表中。在用戶<code>jeffrey</code>試圖用這個口令連接服務器時,<code>mysql</code>客戶用<code>PASSWORD()</code>加密它并且將結果送給服務器,服務器比較在<code>user</code>表中的值(它是純文本值<code>'biscuit'</code>)和加密的口令(<em>而不是</em>
<code>'biscuit'</code>),比較失敗并且服務器拒絕連接: </p>
<pre>shell> mysql -u jeffrey -pbiscuit test
Access denied
</pre>
<p>因為當他們被插入<code>user</code>表時,口令必須被加密,<code>相反,INSERT</code>語句應該象這樣被指定:
</p>
<pre>mysql> INSERT INTO user (Host,User,Password)
VALUES('%','jeffrey',PASSWORD('biscuit'));
</pre>
<p>當你使用<code>SET PASSWORD</code>語句時,你也必須使用<code>PASSWORD()</code>函數:
</p>
<pre>mysql> SET PASSWORD FOR jeffrey@"%" = PASSWORD('biscuit');
</pre>
<p>如果你使用<code>GRANT ... IDENTIFIED BY</code>語句或<code>mysqladmin password</code>命令設置口令,<code>PASSWORD()</code>函數是不必要的。他們都考慮到為你加密口令,多以你可像這樣指定一個口令<code>'biscuit'</code>:
</p>
<pre>mysql> GRANT USAGE ON *.* TO jeffrey@"%" IDENTIFIED BY 'biscuit';
</pre>
<p>或</p>
<pre>shell> mysqladmin -u jeffrey password biscuit
</pre>
<p>注意: <code>PASSWORD()</code>不是以在Unix口令加密的同樣方法施行口令加密。你不應該假定如果你的Unix口令和你的<strong>MySQL</strong>口令是一樣的,<code>PASSWORD()</code>將導致與在Unix口令文件被存儲的同樣的加密值。見<a HREF="manual_Privilege_system.html#User_names">6.2 MySQL 用戶名和口令</a>。 </p>
<h2><a NAME="Access_denied" HREF="manual_toc.html#Access_denied">6.13 <code>Access denied</code>錯誤的原因</a></h2>
<p>當你試著聯接<strong>MySQL</strong>服務器時,如果你碰到<code>Access
denied</code>錯誤,顯示在下面的表指出一些你能用來更正這個問題的動作:
<ul>
<li>你是在安裝<strong>MySQL</strong>以后運行<code>mysql_install_db</code>的腳本,來設置初始授權表內容嗎?如果不是,這樣做。見<a HREF="manual_Privilege_system.html#Default_privileges">6.10 設置初始MySQL權限</a>。通過執行這個命令測試初始權限:
<pre>shell> mysql -u root test
</pre>
<p>服務器應該讓你無誤地連接。你也應該保證你在<strong>MySQL</strong>數據庫目錄有一個文件<tt>“user.MYD”</tt>。通常,它是<tt>“PATH/var/mysql/user.MYD”</tt>,在此<code>PATH</code>是<strong>MySQL</strong>安裝根目錄的路徑。
</p>
</li>
<li>在一個新的安裝以后,你應該連接服務器并且設置你的用戶及其存取許可:
<pre>shell> mysql -u root mysql
</pre>
<p>服務器應該讓你連接,因為<strong>MySQL</strong> <code>root</code>用戶初始時沒有口令。既然那也是一個安全風險,當你正在設置其他<strong>MySQL</strong>用戶時,設定<code>root</code>口令是一件重要的事請。如果你作為<code>root</code>嘗試連接并且得到這個錯誤:
</p>
<pre>Access denied for user: '@unknown' to database mysql
</pre>
<p>這意味著,你沒有一個條目在<code>user</code>表中的一個<code>User</code>列值為<code>'root'</code>并且<code>mysqld</code>不能為你的客庫解析主機名。在這種情況下,你必須用<code>--skip-grant-tables</code>選項重啟服務器并且編輯你的<tt>“/etc/hosts”</tt>或<tt>“\windows\hosts”</tt>文件為你的主機增加一個條目。
</p>
</li>
<li><a NAME="IDX148"></a>如果你從一個3.22.11以前的版本更新一個現存的<strong>MySQL</strong>安裝到3.22.11版或以后版本,你運行了<code>mysql_fix_privilege_tables</code>腳本嗎?如果沒有,運行它。在<code>GRANT</code>語句變得能工作時,授權表的結構用<strong>MySQL</strong>
3.22.11修改 。 </li>
<li>如果你直接對授權表做修改(使用<code>INSERT</code>或<code>UPDATE</code>語句)并且你的改變似乎被忽略,記住,你必須發出一個<code>FLUSH
PRIVILEGES</code>語句或執行一個<code>mysqladmin flush-privileges</code>命令導致服務器再次讀入表,否則你的改變要道下一次服務器被重啟時再生效。記住在你設定<code>root</code>口令以后,你將不需要指定它,直到在你清洗(flush)權限以后,因為服務器仍然不會知道你改變了口令!
</li>
<li>如果你的權限似乎在一個會話(session)當中改變了,可能是一個超級用戶改變了他們。再次裝入授權表作用于新客戶連接,但是它也影響現存的連接,如<a HREF="manual_Privilege_system.html#Privilege_changes">6.9 權限改變何時生效</a>小節所述。
</li>
<li>為了測試,用<code>--skip-grant-tables</code>選項啟動<code>mysqld</code>守護進程,然后你可以改變<strong>MySQL</strong>授權表并且使用<code>mysqlaccess</code>腳本檢查你的修改是否有如期的效果。當你對你的改變滿意時,執行<code>mysqladmin
flush-privileges</code>告訴<code>mysqld</code>服務器開始使用新的權限表。<strong>注意:</strong>再次裝入授權表覆蓋了<code>--skip-grant-tables</code>選項。這允許你告訴服務器開始使用授權表,而不用停掉并重啟它。
</li>
<li>如果你有一個Perl、Python或ODBC程序的存取問題,試著用<code>mysql -u
user_name db_name</code>或<code>mysql -u user_name -pyour_pass db_name</code>與服務器連接。如果你能用<code>mysql</code>客戶連接,這是你程序的一個問題而不是存取權限的問題。(注意在<code>-p</code>和口令之間沒有空格;你也能使用<code>--password=your_pass</code>句法指定口令。)</li>
<li>如果你不能讓口令工作,記得如果你用<code>INSERT</code>, <code>UPDATE</code>或<code>SET
PASSWORD</code>語句設置口令,你必須使用<code>PASSWORD()</code>函數。如果你用<code>GRANT
... INDENTIFIED BY</code>語句或<code>mysqladmin password</code>命令指定口令,<code>PASSWORD()</code>函數是不需要的。見<a HREF="manual_Privilege_system.html#Passwords">6.12 怎樣設置口令</a>。 </li>
<li><code>localhost</code>是你本地主機名的一個同義詞,并且也是如果你不明確地指定主機而客戶嘗試連接的缺省主機。然而,如果你正在運行于一個使用MIT-pthreads的系統上,連接<code>localhost</code>是不行的(<code>localhost</code>連接使用Unix套接字進行,它沒被
MIT-pthreads支持),為了在這樣的系統上避免這個問題,你應該使用<code>--host</code>選項明確地命名服務器主機,這將做一個
TCP/IP連接到<code>mysqld</code>服務器。在這種情況下,你必須有在服務器主機上的<code>user</code>表中條目的你真實的主機名。(即使你在服務器同一臺的主機上運行一個客戶程序,這也是真的。)</li>
<li>當嘗試用<code>mysql -u user_name db_name</code>與數據庫連接時,如果你得到一個<code>Access
denied</code>錯誤,你可能有與<code>user</code>桌有關的問題,通過執行<code>mysql
-u root mysql</code>并且發出下面的SQL語句檢查: <pre>mysql> SELECT * FROM u
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -