下沙论坛

 找回密码
 注册论坛(EC通行证)

QQ登录

QQ登录

下沙大学生网QQ群8(千人群)
群号:6490324 ,验证:下沙大学生网。
用手机发布本地信息严禁群发,各种宣传贴请发表在下沙信息版块有问必答,欢迎提问 提升会员等级,助你宣传
新会员必读 大学生的论坛下沙新生必读下沙币获得方法及使用
查看: 3421|回复: 3
打印 上一主题 下一主题

MySql的权限存取系统

[复制链接]
rcrun 该用户已被删除
跳转到指定楼层
1
发表于 2003-7-26 16:31:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
MySQL有一个先进但非标准的安全/权限系统。本文描述它的工作原理。 & `! T1 S  L; ]- w4 B  `. S; i% S

5 ?$ s% J" L% ^0 L% c2 g权限系统做什么
! m; f- d: M) G: L2 gMySQL权限系统的主要功能是证实连接到一台给定主机的一个用户,
8 V& h' N- G" J1 W8 [# e并且赋予该用户在一个数据库上select、 insert、update和delete的 * Q# D" U4 d+ v- c5 @4 H
权限。
* e* s; L6 X* F6 \; k5 F: @  I
+ {# ?1 S; V/ g: Y附加的功能包括有一个匿名的用户和对于MySQL特定的功能例如 + K0 s. R, K3 {' e- G5 t
LOAD DATA INFILE进行授权及管理操作的能力。
) {, ^/ a8 a- W" g+ T7 r; o' C! C2 U6 a9 x6 a$ P( h% @) k
MySQL 用户名和口令 ; ]: Q- |- [  D, M# g
由MySQL使用用户名和口令的方法与Unix或Windows使用的方式有很 8 ^. G9 ]# f. c& d- t1 ]- H) w. d
多不同之处:
; L7 A" G7 ~0 c) }
( Q" S' `6 U7 H- v" w6 NMySQL使用于认证目的的用户名,与Unix用户名(登录名字)或
, C' n) `: G) |- kWindows用户名无关。缺省地,大多数MySQL客户尝试使用当前Unix用户 3 h$ r% B" n- h" D8 L' z8 A
名作为MySQL用户名登录,但是这仅仅为了方便。客户程序允许用-u或- & x# p' y$ r. t5 U8 b% q+ |0 b
-user选项指定一个不同的名字,这意味着无论如何你不能使得一个数据 + _$ u/ o- c" E- `9 O  O0 n; Q
库更安全,除非所有的MySQL用户名都有口令。任何人可以试图用任何名
, g5 z7 p1 a' S, [$ g( r) q字连接服务器,而且如果他们指定了没有口令的任何名字,他们将成功。
4 Y; r$ N- J; o' G; lMySQL用户名最长可以是16各字符;典型地,Unix用户名限制为8个字符。
; R3 g# a; g) a* [& }$ D3 VMySQL口令与Unix口令没关系。在你使用登录到一台Unix机器口令和你使
7 }9 U& s# E& x1 e$ V- Z) {3 S用在那台机器上存取一个数据库的口令之间没有必要有关联。
( W# K8 o# ~3 t' v7 mMySQL加密口令使用了一个Unix登录期间所用的不同算法。   T0 Y' A  {2 n

: {* n4 [& Z. o+ i, c% H2 Q/ O与MySQL服务器连接
. O* w* m, R8 C. l当你想要存取一个MySQL服务器时,MySQL客户程序一般要求你指定 * d4 U+ x/ _. o# s
连接参数:你想要联接的主机、你的用户名和你的口令。例如,mysql ( c) t9 u0 I8 B/ ?" Z* e4 q
客户可以象这样启动(可选的参数被包括在“[”和“]”之间):
) p% N* O7 `$ `0 V% R( _# ?
0 a) l* `8 ]% v% f! @1 jshell> mysql [-h host_name][-u user_name][-pyour_pass ] % _. R; S+ T: ], H2 s- H4 B
-h, -u和-p选项的另一种形式是--host=host_name、--user=
. @" q3 B9 B6 |* i1 kuser_name和--password=your_pass。注意在-p或--password=与跟随它
# j& c9 \0 v* R% ~1 |+ d后面的口令之间没有空格。 0 y* j9 c& c# a# D( m$ A& [
4 O6 D: w9 U% i2 q
注意:在命令行上指定一个口令是不安全的!随后在你系统上的任 + ^6 ]5 b6 X5 b/ B6 ^; w( S
何用户可以通过打类似这样的命令发现你的口令:ps auxww。
4 x7 K8 z4 @; \& |4 z* |3 f8 ^4 ~6 z- a( E
对于命令行没有的联接参数,mysql使用缺省值:
! b9 v+ ^; [; V( I" H( A0 p- P1 p' l
缺省主机名是localhost。
6 S$ n% i; r- b5 G/ L6 R' P% o/ ^缺省用户名是你的Unix登录名。 7 E% E0 K# q7 H# p
如果没有-p,则没有提供口令。 , X: ?% u, y+ Q  [* U1 s& x
这样, 对一个Unix用户joe,下列命令是等价的:
& z' `! }" ~1 W9 h( a- \' A7 f; e$ A7 s& p' i
shell>mysql -h localhost -u joe 1 h2 O4 e' S$ W! G6 m1 B8 P. N* c
shell>mysql -h localhost
4 ^4 f2 T# @7 r( J, zshell>mysql -u joe ) S& o1 `% k2 R1 Q& X% d  K
shell>mysql 8 _+ ^+ E. [0 @2 D; W
7 a- g* s/ G6 \3 ]) G; `" V
其它MySQL客户程序有同样表现。 ( @$ d! V( W8 E- z3 R
6 E( V/ u9 K$ o1 L+ i
在Unix系统上,当你进行一个连接时,你可以指定要使用的不同的缺
+ g7 [+ B" X/ K+ s, v8 u% u8 f省值,这样你不必每次在你调用一个客户程序是在命令行上输入他们。这
! M; _% ~( _3 d1 ~可以有很多方法做到: 3 G. ]$ `6 K5 [3 H8 r

% \/ g* A/ ?3 n: V% p你能在你的主目录下“.my.cnf”的配置文件的[client]小节里指定 ( q; \, ^; A8 x, N1 G* p& z. N
连接参数。文件的相关小节看上去可能像这样:
5 Q( {" X% D' T! I% H[client]
- o2 ]& Y# s$ x; k, u' g9 P3 [host=host_name   ~( g( U. s  U" V* Q# Z- b* x  e: N
user=user_name
' E9 P4 U& m" J2 [password=your_pass 1 d; w7 r6 E) s* j

$ I, T" t7 m+ d  F. c3 C" r你可以用环境变量指定连接参数。主机可用MYSQL_HOST指定,MySQL
  T* T1 z2 I5 `& q- E) o. s. W, o: B用户名字可用USER指定(仅对 Windows),口令可用MYSQL_PWD指定(但是 + `: |8 m! g' q3 G) Q3 c
这不安全) 。
+ a1 v( s7 u' \' |9 r$ r; ~0 J如果连接参数以多种方法被指定,在命令行上被指定的值优先于在配 3 z) a8 }5 p$ M" S3 I
置文件和环境变量中指定的值,而在配置文件指定的值优先于在环境变量 1 a& ?  C) U9 ~0 L1 u* G
指定的值。 7 k8 M' v! F! r3 Y% U
  t5 v# z& b7 d& z# L; C
使你的口令安全
1 e* k( C4 m, o2 Y* \以一种暴露的可被其他用户发现的方式指定你的口令是不妥当的。
7 }/ K% j+ A/ u当你运行客户程序时,你可以使用下列方法指定你的口令,还有每个方法 4 ^" }. b9 B$ H/ T4 L! x  |' @: G
的风险评估: 7 R- N6 D  N- x4 ?
3 A" `* e. D$ d  i) S' C
使用一个在命令行上-pyour_pass或--password=your_pass的选项。 ' j3 b: p, O3 ^6 t
这很方便但是不安全,因为你的口令对系统状态程序(例如ps)变得可见, ; m; ?; t8 C& z2 A" j
它可以被其他的用户调用来显示命令行。(一般MySQL客户在他们的初始化 2 ]6 h- v, s; U5 b5 b* u
顺序期间用零覆盖命令行参数,但是仍然有一个短暂间隔时间内参数值可 % {. [/ n* Z' L5 A2 r( [. x
见的。)
7 u4 N  }  A% j6 X4 n; e使用一个-p或--password选项(没有指定your_pass值)。在这种情况 2 Q3 r" B% r" d& W# R
下,客户程序请求来自终端的口令:
; y) j5 I, L' _' n
7 T7 ]1 `* k" W/ L. V8 Nshell>mysql - u user_name - p   c6 ~2 u/ X7 k  Q( H. y
Enter password: ******** / |1 ?) H5 V( B. X& P+ E
. f+ j& }( X* ]) r$ _: r
客户回应“*”字符到作为输入你的口令的终端使得旁观者不能看见 $ ]% J- Z) |: W7 A4 \0 Z3 V
它。因为它对其他用户不可见,与在命令行上指定它相比,这样进入你
. n  ^; N1 m; ?的口令更安全。然而,这个输入一个口令的方法仅仅为你交互式运行程 # d; S2 s1 B) n' A% |
序是合适的。如果你想要从非交互式运行的一个脚本调用一个客户,就 0 Q% Q- A5 n7 G' V6 l
没有从终端输入入口令的机会。 4 w. n& P+ J' D
$ F  n; X6 z4 Y9 F% b5 y
在一个配置文件中存储你的口令。例如,你可你的主目录的
1 z% Q& Y- @8 Y# I. }2 {+ R- ]“.my.cnf”文件中的[client]节列出你的口令:
! Q+ r( ~5 H3 O  Z4 M. \[client] % x* T- l; A1 o" ^3 {9 g* p
password=your_pass % q+ F, E- ^5 |$ \

/ O, u) \, ]9 H; `3 o/ c0 A! C( C" a如果你在“.my.cnf”里面存储口令,文件应该不是组或世界可读或
2 ]; e( G3 K3 }& ~6 S5 V可写的。保证文件的存取模式是400或600。见4.15.4 选项文件。 - N! w) ~4 l! Q( t6 Q$ C

( z( k$ Z3 o. ]" E你可在MYSQL_PWD环境变量中存储口令,但是这个方法必须想到是极 3 B; P7 q$ N- u- x
不安全的且应该不使用。ps的某些版本包括显示运行进程的环境的选项;
+ E% x" T* M& D* a7 t% h3 q6 W如果你设定MYSQL_PWD,你的口令将对所有人是显而易见的,甚至在没有 % N9 P* N  @4 G9 b! I
这样一个版本的ps系统上,假设没有其他方法观察到进程环境是不明智 ; P: j4 R- _4 u: `# X% u. E0 p" [% C
的。
4 h: _. P, J' A: x" h' t总之,最安全的方法是让客户程序提示口令或在一个适当保护的“
6 H; O7 c5 \2 f.my.cnf”文件中指定口令。 7 f2 u% i9 l! v+ Y% z" R/ k  w
: o& C2 c; c: y, V
MySQL提供的权限 : l1 I' P" [$ U
权限信息用user、db、host、tables_priv和columns_priv表被存储 6 l. F: j( x/ n, L" Z
在mysql数据库中(即在名为mysql的数据库中)。在MySQL启动时和在权限
6 R5 V& C% d0 l* `$ Q修改何时生效所说的情况时,服务器读入这些数据库表内容。 . ?6 Q* j" e/ q' L* e3 c
; L4 n" {6 u$ g
由MySQL提供的权限名称显示在下表,还有在授权表中每个权限的表 % F6 x- a: F: {! D& h
列名称和每个权限有关的上下文: $ K* Y8 d! X7 P2 J" z, D" X
权限 列 上下文 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 在服务器上的文件存取 : V4 p& L1 d! @' Y) m
select、insert、update和delete权限允许你在一个数据库现有的 , p' B* K" B+ {- K( j
表上实施操作。
. |' U+ R: |" O# Q
& A3 R* m! W! F1 i7 s4 P/ C: x/ DSELECT语句只有在他们真正从一个表中检索行是才需要select权限, 6 {- I( n& W* l2 R
你可以执行某个SELECT语句,甚至没有任何到服务器上的数据库里的存
/ m8 _4 N4 }6 {( H取任何东西的许可。例如,你可使用mysql客户作为一个简单的计算器:
6 Z9 s& I; F6 Z- \$ I' v
# a( X& a1 r! q, f/ `mysql> SELECT 1+1;
0 z5 }5 @. _1 U" ~8 Mmysql> SELECT PI()*2;
( e5 p; Q7 \: E: y! H6 H4 y
( v, l5 m4 Q* C% N7 s$ ]4 H) gindex权限允许你创建或抛弃(删除)索引。 # @- |* K, X* K; v! r/ z7 E( z
7 j0 P; i, Q, o% C7 B
alter权限允许你使用ALTER TABLE。
  W0 v$ T" a+ R( J0 o; w$ T0 ?3 u: j
create和drop权限允许你创建新的数据库和表,或抛弃(删除)现存的
' ~( y. s( R) ^3 x数据库和表。
  X/ M# K9 F8 l1 B4 L* j1 h
* _. J* D5 p! Q: G# F- k注意:如果你将mysql数据库的drop权限授予一个用户,该用户能抛弃 : k& e* ?& j. Y! W4 s5 c6 P; A
存储了MySQL存取权限的数据库!
' ?9 ~  t! _5 X2 B& }$ Z$ o7 R1 \. Y2 F. h" `" @* W- O: e
grant权限允许你把你自己拥有的那些权限授给其他的用户。
- ?' ^1 m+ J" [1 d( P. [- Z- x2 U, M! V7 S: ?1 h
file权限给予你用LOAD DATA INFILE和SELECT ... INTO OUTFILE语句 - M% {2 g1 w) u5 b7 G
读和写服务器上的文件,任何被授予这个权限的用户都能读或写MySQL服务
/ k& }% l( i4 a2 n7 c器能读或写的任何文件。
: O1 q7 L+ W' W: C0 x, J0 ]# z9 h; u
其余的权限用于管理性操作,它使用mysqladmin程序实施。下表显示
. O8 {9 G7 v% Nmysqladmin支配每个管理性权限允许你执行的命令: ; P+ `# Y8 ^  s  ~( k
优惠 权限拥有者允许执行的命令 reload reload, refresh, flush-privileges, flush-hosts, flush-logs, flush-tables shutdown shutdown precess processlist, kill ) }9 v" L+ J3 N! V7 G
reload命令告诉服务器再读入授权表,refresh命令清洗所有表并打开 5 P. J! ]/ U. p9 z/ I
和关闭记录文件,flush-privileges是reload的一个同义词,其它flush-*
' b7 L/ D* }/ T' G2 w命令执行类似refresh的功能,但是范围更有限,并且在某些情况下可能更 8 ^) y  q4 x! w7 o
好用。例如,如果你只是想清洗记录文件,flush-logs比refresh是更好的 9 z; k+ V, l) b; @' s
选择。
( F& g! v/ J+ ?9 A2 }$ p) y3 P- q$ Z* l. |/ ?8 h/ W2 G; Z# R# ?
shutdown命令关掉服务器。
$ s% ^4 g# ]' C; @5 u! x) `
3 P) T2 y8 Y8 i4 xprocesslist命令显示在服务器内执行的线程的信息。kill命令杀死服
; J2 Z9 V0 b5 |1 f2 |0 C9 G9 n务器线程。你总是能显示或杀死你自己的线程,但是你需要process权限来 9 y3 e3 i4 m6 u
显示或杀死其他用户启动的线程。 6 }. C0 O+ I  G
* h* s/ u8 `: N' p
总的说来,只授予权限给需要他们的那些用户是一个好主意,但是你
: W: n; M, r% z% W  M应该在授予某个权限时试验特定的警告: 9 b! Z+ n" ]- I# u1 i! o$ N
* k  Y. ~. G& y6 J2 `2 ]
grant权限允许用户放弃他们的权限给其他用户。2个有不同的权限并
) P9 ]' L1 P* @有grant权限的用户可以合并权限。 ' P3 R1 D: W9 `  ?
alter权限可以用于通过重新命名表来推翻权限系统。
2 L4 J' d8 _: m: B$ Efile权限可以被滥用在服务器上读取任何世界可读(world-readable, * K6 T0 q2 R$ y1 N
即任何人可读)的文件到一张数据库表,然后其内容能用SELECT被存取。 ' r1 r4 a& S$ ~# ]
shutdown权限通过终止服务器可以被滥用完全拒绝为其他用户服务。
, c0 \3 y4 p# ?; ~! }8 Q" kprecess权限能被用来察看当前执行的查询的普通文本,包括设定或改
, u; j6 m5 j3 f! A变口令查询。
0 X% _4 O1 M( o* f  h在mysql数据库上的权限能被用来改变口令和其他存取权限信息。(口
% F& v9 W, x1 H; v令被加密存储,所以一个恶意的用户不能简单地读取他们。然而,有足够
9 F. O$ O8 ~+ H的权限,同一个用户能用不同的一个代替一个口令。)
& L9 C) ^# f' j有一些事情你不能用MySQL权限系统做到:   G, e# `- H/ u  T
% g& M4 W8 {! k5 f( s3 V) K: G+ w
你不能明显地指定一个给定用户应该被拒绝存取。即,你不能明显地匹
. [  I8 @: Z6 ^9 k) T& s配一个用户并且然后拒绝连接。
; Z# m! H  T; `1 _" [/ @$ M你不能指定一个用户有权创建立或抛弃一个数据库中的表,也不能创建 2 B+ j6 }; ]' C/ R3 B0 D& |7 o
或抛弃数据库本身。 + u/ H5 D  h; o# U
权限系统工作原理 % U& p4 E8 M- s2 H! d7 J
MySQL权限系统保证所有的用户可以严格地做他们假定被允许做的事情。 $ V* R0 M+ i" U1 G' m$ ~! w
当你连接一个MySQL服务器时, 你的身份由你从那连接的主机和你指定的用 7 ~. X6 m! h9 I2 k* q  M3 ?4 }
户名来决定,系统根据你的身份和你想做什么来授予权限。 ; O' o( F  h7 r9 V' G
$ {5 X$ N! _; l( Q, t6 t
MySQL在认定身份中考虑你的主机名和用户名字,是因为有很小的原因假 1 Y5 b/ M8 ]: {' H' g' i9 G$ z
定一个给定的用户在因特网上属于同一个人。例如,用户从whitehouse.gov
. d* z( F: V5 p连接的bill不必和从mosoft.com连接bill是同一个人。 MySQL通过允许你区 9 J8 u" }; C' c# e- T; Q9 f
分在不同的主机上碰巧有同样名字用户来处理它:你可以对从whitehouse.gov ! V# `4 A6 f% H$ b
连接授与bill一个权限集,而为从microsoft.com的连接授予一个不同的权限
. R1 ~. ]6 p6 ]: H  y: \9 Z/ E集。 6 r2 c# G% z* O' s! G
5 ^0 D" Y' {' i
MySQL存取控制包含2个阶段: , Z# x% E- T6 n
0 h9 s* U3 P, {, w
阶段1:服务器检查你是否允许连接。 & C" W3 i. G9 k
阶段2:假定你能连接,服务器检查你发出的每个请求。看你是否有足够
- i$ D" O" W7 m( w) @2 a* u- q+ b' x的权限实施它。例如,如果你从数据库中一个表精选(select)行或从数据库抛
6 \4 Y0 H2 Z& l7 X: P弃一个表,服务器确定你对表有select权限或对数据库有drop权限。
7 K- r6 m1 T: ?) Z# T3 K服务器在存取控制的两个阶段使用在mysql的数据库中的user、db和host 3 }. [) p9 @9 m% K- C
表,在这些授权表中字段如下:
% ?; O  C5 Q' b0 J9 ~  s/ d7 S1 r表名称 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 ( i& i0 m9 k9 _; f
对存取控制的第二阶段(请求证实),如果请求涉及表,服务器可以另外 ! j0 s/ ]8 ^9 Y4 s, t! S
参考tables_priv和columns_priv表。这些表的
, V2 P; T. ^- `: ]字段如下: 9 z2 J6 N- C3 O) z4 I: U
表名称 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 1 k5 D( N# c- I& W4 f
对存取控制的第二阶段(请求证实),如果请求涉及表,服务器可以另外
& ~' A# X* T# W; Y7 ^$ Q5 W参考tables_priv和columns_priv表。这些表的字段如下:
# r) \( m0 a  U& J8 }, X: d& m字段名 类型 Host CHAR(60) User CHAR(16) Password CHAR(16) Db CHAR(64) (tables_priv和columns_priv表为CHAR(60)) 0 f# A8 B% F( j5 A3 ^1 n
在user、db和host表中, 4 f2 _. W( Z9 h% U% K6 L2 w3 |; L
所有权限字段被声明为ENUM('N','Y')--每一个都可有值 . }1 `7 a5 \! ]0 v
'N'或'Y',并且缺省值是'N'.
. t+ n' T5 z1 |在tables_priv和columns_priv表中,权
# G0 d4 w8 G: S8 s. F2 Y+ M限字段被声明为SET字段: 9 g# e" g+ l9 ]+ R7 W7 K
表名 字段名 可能的集合成员 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'
% J  a% {4 e  i: x; h3 L4 t8 ~每个授权表包含范围字段和权限字段。
8 o( g$ Q! N- d9 Y: N. e2 r  \# D
范围字段决定表中每个条目的范围,即,条目适用的上下文。例如, # r7 Z! ^( K) S+ v; n1 [4 b
一个user表条目的Host和User值为'thomas.loc.gov'和'bob'将被用于
  Q' P7 i  g4 |" R% h8 y证实来自主机thomas.loc.gov的bob对服务器的连接。同样,一个db表条 # o* c5 S2 o5 i0 [, h
目的Host、User和Db字段的值是'thomas.loc.gov'、'bob'和'reports'
6 Z/ r7 N' {  F, z将用在bob从主机联接thomas.loc.gov存取reports数据库的时候。
5 C. T  ]7 H) q$ l! w, d+ Wtables_priv和columns_priv表包含范围字段,指出每个条目适用的表或 8 w3 H* x; i+ K+ W# j: f( H
表/列的组合。
0 V0 U2 Y& y$ T2 D# H5 ?+ M! G" F* w$ c
, ~  u) t" D% B) \7 Y" o对于检查存取的用途,比较Host值是忽略大小写的。User、Password、
1 u& Z3 I. P8 _4 p' pDb和Table_name值是区分大小写的。Column_name值在MySQL3.22.12或以
- [6 i" ?3 ~. Y. Y, T后版本是忽略大小写的。
$ Z* Q- Q) @: P1 O3 b2 N( C6 e1 R) e0 A* e4 o% r
权限字段指出由一个表条目授予的权限,即,可实施什么操作。服务
/ ?' A5 G7 W* A器组合各种的授权表的信息形成一个用户权限的完整描述。为此使用的规
# z( m6 p$ i" t  D, M则在6.8 存取控制, 阶段2:请求证实描述。
) Q! E- o2 f" `9 ~! B! v9 F* X: h# W% l
范围字段是字符串,如下所述;每个字段的缺省值是空字符串: # N+ x  R( m" H
字段名 类型 Host CHAR(60) User CHAR(16) Password CHAR(16) Db CHAR(64) (tables_priv和columns_priv表为CHAR(60))
+ `& `3 Q) H9 x0 ?: k在user、db和host表中,所有权限字段被声明为ENUM('N','Y')--每一 3 h+ [' m; @( t% ?0 e6 B' t* C
个都可有值'N'或'Y',并且缺省值是'N'. , }0 V2 z9 W0 d% o7 w% u
5 D% t. T$ ]/ g. x# K
在tables_priv和columns_priv表中,权限字段被声明为SET字段:
. \9 \" h9 y  M( Z- [; I" U( p表名 字段名 可能的集合成员 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'
# ^8 A  h/ p) w简单地说,服务器使用这样的授权表: 2 p+ s8 s( A' _9 u
1 N4 |) z3 z; e# N& L
user表范围字段决定是否允许或拒绝到来的连接。对于允许的连接,
" k7 M& S: P0 [* _权限字段指出用户的全局(超级用户)权限。
' N1 l5 f8 B" |& U% H" ]5 \8 Zdb和host表一起使用:
) e9 ?# F2 M. V' Vdb表范围字段决定用户能从哪个主机存取哪个数据库。权限字段决定 ; E* R" D# @, @. a4 d7 r6 L) L
允许哪个操作。
! N; r) `0 l) V7 ~' m$ I7 Y当你想要一个给定的db条目应用于若干主机时,host表作为db表的扩 8 ?; O' e% q1 D# e0 J4 c9 u
展被使用。例如,如果你想要一个用户能在你的网络从若干主机使用一个
' S1 E; y2 G# q, q; u1 i5 V! W5 C数据库,在用户的db表的Host条目设为空值,然后将那些主机的每一个移 * A* b" V# Z; L9 r. A  v2 e$ w: z* g
入host表。这个机制详细描述在6.8 存取控制, 阶段2:请求证实。 + p) r( L8 }; [7 w
tables_priv和columns_priv表类似于db表,但是更精致:他们在表 % |# g3 X* s/ @( Q: T: Y1 H+ t
和列级应用而非在数据库级。
# h; u' k, I+ H$ G, c9 o注意管理权限(reload, shutdown, 等等)仅在user表中被指定。这是
; |" k0 X! o/ c6 _  _3 O4 R0 M因为管理性操作是服务器本身的操作并且不是特定数据库,因此没有理由
' |2 x; ^# w! _在其他授权表中列出这样的权限。事实上,只需要请教user表来决定你是 7 g2 _  F6 O/ b6 G+ y, x
否执行一个管理操作。
9 Z% T% K$ t/ g( r9 V" ?
: C0 e% z6 R. J0 }3 n$ Mfile权限也仅在user表中指定。它不是管理性权限,但你读或谢在服 3 |. C" m! z7 G) M4 H  T
务器主机上的文件的的能力独立于你正在存取的数据库。
" j, N. r5 ?8 j* S, i
  d6 o! ~+ K) \! z1 a* D  u当mysqld服务器启动时,读取一次授权表内容。 - ?! L: a4 l! W6 {( I# r

+ O9 P3 o% K; C* S当你修改授权表的内容时,确保你按你想要的方式更改权限设置是一
$ E! F! K: H& T个好主意。
* u) o& h- {+ G/ i7 k1 T- v7 m( O) s" G% P. [& D
一个有用的诊断工具是mysqlaccess脚本,由Carlier Yves 提供给
5 L% W/ U/ B8 n- e$ @- D' i/ L( ~( IMySQL分发。使用--help选项调用mysqlaccess查明它怎样工作。注意: - p+ i8 J0 x) V2 Y+ u
mysqlaccess仅用user、db和host表仅检查存取。它不检查表或列级权限。 . b% a, _5 I5 s
* g& @1 f1 J' s- \. m3 y" n5 X
存取控制, 阶段1:连接证实
# D5 N( D/ z) Z( G. A/ [: ?( G% q4 ^当你试图联接一个MySQL服务器时,服务器基于你的身份和你是否能 2 `9 X# o  k0 y3 E# {
通过供应正确的口令验证身份来接受或拒绝连接。如果不是,服务器完全
  ^8 T0 y, F9 l# e% a7 J, v5 Z' f具结你的存取,否则,服务器接受连接,然后进入阶段2并且等待请求。
  P0 U: j5 J, Z: b4 W* }) i. l; {( A  X- f1 u8 i: b* F
你的身份基于2个信息:
8 U' n$ [5 M0 F: G! K7 r
  Q9 i4 w1 K: k3 d你从那个主机连接 ' Y% b) t3 w; P, C2 \$ n3 j) {
你的MySQL用户名 1 X) O$ x; a( E0 r0 B+ G& ^' B
身份检查使用3个user表(Host, User和Password)范围字段执行。服
+ y3 W2 P9 o8 S7 n4 ^3 ~/ P1 S务器只有在一个user表条目匹配你的主机名和用户名并且你提供了正确的
' a9 w# S! F& K6 z6 x+ H口令时才接受连接。
% P4 i& L4 |8 I2 v3 Y% V" N! Y+ I$ T" D( F$ R. L
在user表范围字段可以如下被指定: ) L* \" N# }  A
% e0 z) A7 g) O" K- Y6 B5 L
一个Host值可以是主机名或一个IP数字,或'localhost'指出本地主机。 4 A& S$ h" o. E. r  j6 G/ ?
你可以在Host字段里使用通配符字符“%”和“_”。 & p4 a3 u- a& a+ L% |
一个Host值'%'匹配任何主机名,一个空白Host值等价于'%'。注意这些 + Z( R2 j) K1 w. ]2 G
值匹配能创建一个连接到你的服务器的任何主机!
6 [& V" M2 |9 d- F, P2 Y通配符字符在User字段中不允许,但是你能指定空白的值,它匹配任何
5 F9 k9 ]# l* G: Q名字。如果user表匹配到来的连接的条目有一个空白的用户名,用户被认为
8 }6 K7 v% @/ @5 W是匿名用户(没有名字的用户),而非客户实际指定的名字。这意味着一个空
" w, ~9 I7 ^7 a/ b: C2 b( d白的用户名被用于在连接期间的进一步的存取检查(即,在阶段2期间)。
" U& M7 ^  t; u/ iPassword字段可以是空白的。这不意味着匹配任何口令,它意味着用户
8 p; h  W% Y$ L/ p$ l必须不指定一个口令进行连接。
1 E$ K+ ?5 t( A6 F8 U$ q( y非空白Password值代表加密的口令。 MySQL不以任何人可以看的纯文本 ! h6 i0 u& A( r* }0 ]' `
格式存储口令,相反,正在试图联接的一个用户提供的口令被加密(使用
% w; [: q2 N. i  Z! i7 E# z* ~PASSWORD()函数),并且与存储了user表中的已经加密的版本比较。如果他 - y; }  l2 |2 [/ E- S" L2 Z: |
们匹配,口令是正确的。 % a: W! [5 b, h3 q
! d) `8 o- J2 F) }
下面的例子显示出各种user表中Host和User条目的值的组合如何应用于到来
: i  c  F9 o% g: L的连接: $ ?. D; g- m1 s6 R$ S% a

- L" l# e3 G9 Q% s3 p: \& C2 tHost 值 User 值 被条目匹配的连接
( p9 f, M. J: }'thomas.loc.gov' 'fred' fred, 从thomas.loc.gov 连接 " c) X* z9 @, h: t
'thomas.loc.gov' '' 任何用户, 从thomas.loc.gov连接 # a1 z2 G) N0 n- d8 ?% ~) `
'%' 'fred' fred, 从任何主机连接
' l/ [7 N4 p% c  h. `+ x) c'%' '' 任何用户, 从任何主机连接
% I" y6 \' c- C: \'%.loc.gov' 'fred' fred, 从在loc.gov域的任何主机连接 ; ?8 t( I* S/ S3 Z+ k3 L. L/ M
'x.y.%' 'fred' fred, 从x.y.net、x.y.com,x.y.edu等联接。(这或许 / R% Y7 x/ }7 Z3 |2 Z, Y/ m
无用) 9 B2 J4 ?4 l! j5 h. r* B# t+ \6 i
'144.155.166.177' 'fred' fred, 从有144.155.166.177 IP 地址的主
1 ^$ {8 n5 h0 Q2 a% ?" r机连接 7 L6 p+ x8 ]( z4 z* N1 t$ b
'144.155.166.%' 'fred' fred, 从144.155.166 C类子网的任何主机连
3 u5 b1 H0 s+ J9 P& {) ^# z8 r* V! ?

1 A2 ~/ E3 I$ r& \( U$ i/ i6 A' d既然你能在Host字段使用IP通配符值(例如,'144.155.166.%'匹配在一个子
3 g* _7 s4 o" m' T7 Z5 b网上的每台主机),有可能某人可能企图探究这种能力,通过命名一台主机 1 l' c7 @3 h) x* f" C* N& A8 U
为144.155.166.somewhere.com。为了阻止这样的企图,MySQL不允许匹配以
5 S) V7 N, g2 Z数字和一个点起始的主机名,这样,如果你用一个命名为类似1.2.foo.com的 / z1 |* p6 L$ P* }0 P" i
主机,它的名字决不会匹配授权表中Host列。只有一个IP数字能匹配IP通配   _/ q: v8 W% V- ^1 t4 v, U* M
符值。 + h- }1 b: a5 J. c+ J
! I0 e7 ?) J2 z8 O5 R$ d: Y3 y
一个到来的连接可以被在user表中的超过一个条目匹配。例如,一个由 9 f1 |1 M4 R) @% O3 x
fred从thomas.loc.gov的连接匹配多个条目如上所述。如果超过一个匹配,
% i+ s& X. M* V3 C* I1 I服务器怎么选择使用哪个条目呢?服务器在启动时读入user表后通过排序来 " [4 ~+ W. c; z9 v7 ?5 T
解决这个问题,然后当一个用户试图连接时,以排序的顺序浏览条目,第一 7 F( i' i; |* s
个匹配的条目被使用。 ! B) P' {" ]5 H  y( z
0 s+ A/ k; o6 m2 L$ z6 x* J
user表排序工作如下,假定user表看起来像这样: ( {2 ]8 r. T8 J" z& A: M
, Q, ?/ Y; M* `/ Q( G1 W$ Z

9 E3 [6 p1 r0 t1 E& J$ I% r5 F+-----------+----------+-
( T/ O$ [2 B) t% E* I│ Host │ User │ ...
: M- P! e9 }7 y' O+-----------+----------+- 6 E) N% z) H$ U7 j8 k6 r
│ % │ root │ ...
. V7 P1 S1 h  a/ [, O) c) ?6 [│ % │ jeffrey │ ...
9 X* L  J- Q. }* w6 p1 c5 _│ localhost │ root │ ... 9 d: U* O* i9 b/ o3 I- Z; x
│ localhost │ │ ... - D) i( {3 ?: I& p3 G
+-----------+----------+- 9 c, K, s- M; D

, r( j# `2 ]* E& e# ~/ z7 y7 h+ d当服务器在表中读取时,它以最特定的Host值为先的次序排列('%'在 8 u# Q0 d0 @# X
Host列里意味着“任何主机”并且是最不特定的)。有相同Host值的条目以
! x# V' a1 J! u3 H: x6 P% O最特定的User值为先的次序排列(一个空白User值意味着“任何用户”并且
4 K# q" y6 R5 Y" U: U0 p2 u* [是最不特定的)。最终排序的user表看起来像这样:
. u# j/ g! t4 j' z  k/ ^" C' P1 B7 T
# {0 G! b" T/ }" z8 o1 O+ N& x. Z% Q( k) @+ V4 `
+-----------+----------+- 9 r: V% O! ]4 {$ ~
│ Host │ User │ ... 9 T6 |( o+ O" ~, t4 B! A
+-----------+----------+- : Y. B, @& S" s0 A2 H3 G
│ localhost │ root │ ... 9 P4 R! d& h1 Z  S0 X
│ localhost │ │ ... ! l+ ^3 V6 r1 O& v) }- Z) T0 A
│ % │ jeffrey │ ...
) b( v2 B9 A! q, ~2 ~│ % │ root │ ... ) L5 \; H/ d, N; b8 |# }( p. {+ D
+-----------+----------+- 9 ?+ u7 B7 \3 R8 f1 x; s+ K  ]
* q; [, w' v! B! y' N
当一个连接被尝试时,服务器浏览排序的条目并使用找到的第一个匹 ) n3 s/ t- X: }& C4 M
配。对于由jeffrey从localhost的一个连接,在Host列的'localhost'条目
8 c& k; A" }  e& g2 a  R首先匹配。那些有空白用户名的条目匹配连接的主机名和用户名。('%'/
+ A9 Z* {. v! x'jeffrey'条目也将匹配,但是它不是在表中的第一匹配。)
0 P- e1 b9 l$ c8 i
; J9 i6 c4 C/ \1 T- F这是另外一个例子。假定user桌子看起来像这样:
& J' z) K1 ]1 N
% r0 [& e& C/ L: M4 M1 w/ ?; I' b3 |  r& X& ?& \% x
+----------------+----------+- $ O) h9 Y# a+ x# Z9 h  Y
│ Host │ User │ ... ) A0 b+ D0 P9 v1 K' Z2 r
+----------------+----------+-
  w. I8 T/ k  q/ z│ % │ jeffrey │ ... + c7 |" y/ h& }
│ thomas.loc.gov │ │ ... / d' U- U  t: e
+----------------+----------+-
' s2 o7 z% U, M$ a  E; {; r, z/ ?1 d) Y- @
排序后的表看起来像这样:
  J# m( C! `- l: O8 n0 I- U/ w9 ?
" x7 f( U# N" H5 J! Z/ W4 }4 ?4 }; {  _( D: }# w
+----------------+----------+-
5 y5 X; h; H7 N: o6 N& \4 a│ Host │ User │ ...
& s5 e. t- L# N* G9 c+----------------+----------+-
$ H$ l' K9 s. b) y4 r6 N│ thomas.loc.gov │ │ ... ; D% s& j3 z& u$ U( e
│ % │ jeffrey │ ...
. f4 p- q  u# f/ q; R0 t+----------------+----------+- " z7 c' P# {5 G/ B4 k, B

* v4 \8 Y6 D* C! v3 Y一个由jeffrey从thomas.loc.gov的连接被第一个条目匹配,而一个由 8 Z8 \# T" _% s
jeffrey从whitehouse.gov的连接被第二个匹配。
6 l  `* C7 f& R: G
$ i4 e4 h9 m3 n: ^0 [9 l! N普遍的误解是认为,对一个给定的用户名,当服务器试图对连接寻找
3 Q* R( s8 k6 G2 C" S5 Z/ |1 b匹配时,明确命名那个用户的所有条目将首先被使用。这明显不是事实。 # S- ~4 ~4 Z3 Y
先前的例子说明了这点,在那里一个由jeffrey从thomas.loc.gov的连接没
: _' T% v6 j9 F# G7 b( B: Z, O被包含'jeffrey'作为User字段值的条目匹配,但是由没有用户名的题目匹 + J5 z: `& ]6 K0 k: r& g$ r
配!
$ h. L: W: \- d8 p5 p5 ]0 a) m/ t- g& y  }$ U
如果你有服务器连接的问题,打印出user表并且手工排序它看看第一个 2 r# {+ L, l, [3 K# t0 ~
匹配在哪儿进行。 1 ^: g9 A! T& |, Q' Q

- L6 w8 |- u% ]存取控制,阶段2:请求证实
4 W3 c% A  h. k$ v+ x. U一旦你建立了一个连接,服务器进入阶段2。对在此连接上进来的每个 ; F; t& M, J7 [
请求,服务器检查你是否有足够的权限来执行它,它基于你希望执行的操作
1 s- X6 F: a- f* p类型。这正是在授权表中的权限字段发挥作用的地方。这些权限可以来子
( @/ j! p, {! T9 r4 {user、db、host、tables_priv或columns_priv表的任何一个。授权表用
9 B2 _5 A. D8 a( T) W% x/ T' MGRANT和REVOKE命令操作。见7.26 GRANT和REVOKE 句法。(你可以发觉参 7 S9 q% ?% r) B3 [2 Z5 F
考6.6 权限系统怎样工作很有帮助,它列出了在每个权限表中呈现的字段。) 5 g  k! V1 D9 e: g* B# }) s8 ~

2 r8 b! @3 g$ @# @$ c. guser表在一个全局基础上授予赋予你的权限,该权限不管当前的数据库 ' c* n. o% l, p$ ?' r& ^* \% A
是什么均适用。例如,如果user表授予你delete权限, 你可以删除在服务器
* u0 O* g: {- ?  a) |2 [" E主机上从任何数据库删除行!换句话说,user表权限是超级用户权限。只把
% d4 ^. j  y& n: ~user表的权限授予超级用户如服务器或数据库主管是明智的。对其他用户, , w  l  F8 j3 `9 B7 i6 q
你应该把在user表中的权限设成'N'并且仅在一个特定数据库的基础上授权,
% R: C% L5 a) K0 x使用db和host表。 ; y$ H+ P) {2 X& A

, K2 |. h. y( p( D1 E+ ^- ddb和host表授予数据库特定的权限。在范围字段的值可以如下被指定:
7 A3 p8 v) V: F0 ~; }# J7 M* k2 G& C% @( s; b, _
通配符字符“%”和“_”可被用于两个表的Host和Db字段。 0 x" l2 i3 W4 w9 |) q
在db表的'%'Host值意味着“任何主机”,在db表中一个空白Host值意味 ! m* R! a8 d  h( i
着“对进一步的信息咨询host表”。   {& U2 E4 n* ]. Y) F8 I
在host表的一个'%'或空白Host值意味着“任何主机”。
1 N( y# o. S2 o$ `" c7 d在两个表中的一个'%'或空白Db值意味着“任何数据库”。 ; d6 y9 Y' N' a/ F" G! J8 f
在两个表中的一个空白User值匹配匿名用户。
+ F1 E+ Z, w( b( v  pdb和host表在服务器启动时被读取和排序(同时它读user表)。db表在Host
/ E- g/ Y- H5 X、Db和User范围字段上排序,并且host表在Host和Db范围字段上排序。对于
% _' i3 I/ z# h. W% S3 t. ~) Y5 M" Wuser表,排序首先放置最特定的值然后最后最不特定的值,并且当服务器寻找 * A, k7 ?1 p! n
匹配入条目时,它使用它找到的第一个匹配。
# F' s' e) z9 |5 p/ S
, U! t, C$ F8 G3 b& O) _! rtables_priv和columns_priv表授予表和列特定的权限。在范围字段的值可 4 w0 T. Y/ ?. j, Y9 `
以如下被指定:
$ G, O# ?/ T% E  u0 Q
5 {! Y( `: ?6 b' B0 I5 M( C通配符“%”和“_”可用在使用在两个表的Host字段。 1 Z3 b; Y1 Y% u  M
在两个表中的一个'%'或空白Host意味着“任何主机”。
1 U( H" I: }7 \: C+ S: S在两个表中的Db、Table_name和Column_name字段不能包含通配符或空白。
8 b, I  X: e) E3 Dtables_priv和columns_priv表在Host、Db和User字段上被排序。这类似于 # E. d$ ?% G, A4 W
db表的排序,尽管因为只有Host字段可以包含通配符,但排序更简单。 8 y  |9 `- F# s5 ~% V8 U: j

% |3 X. w& f8 j6 j请求证实进程在下面描述。(如果你熟悉存取检查的源代码,你会注意到这 , Q0 e4 B# \! [9 V0 N7 i
里的描述与在代码使用的算法略有不同。描述等价于代码实际做的东西;它只是
! s% c7 i/ G5 Y" t8 Z不同于使解释更简单。)
- A3 X* K% k0 z9 {: M5 d! R8 ?$ K4 C) g, }; }. s$ o/ W
对管理请求(shutdown、reload等等),服务器仅检查user表条目,因为那是 : X3 h5 I. \; ]+ w
唯一指定管理权限的表。如果条目许可请求的操作,存取被授权了,否则拒绝。 + `8 I; O0 o7 C% t5 z
例如,如果你想要执行mysqladmin shutdown,但是你的user表条目没有为你授 . V2 X2 c2 x& ?) v
予shutdown权限,存取甚至不用检查db或host表就被拒绝。(因为他们不包含
4 p! ^) o! U; r* i+ CShutdown_priv行列,没有这样做的必要。)
! y  d; e0 q7 h4 K" t2 {) I% K+ R
5 W1 T* c2 |' N$ ?; b3 X对数据库有关的请求(insert、update等等),服务器首先通过查找user表
; z4 R. q- {% E' H: B条目来检查用户的全局(超级用户)权限。如果条目允许请求的操作,存取被授 . b$ _0 ]9 j& a( N& y* `8 v
权。如果在user表中全局权限不够,服务器通过检查db和host表确定特定的用 / w5 t  u" S, w% x4 a. T7 E
户数据库权限: + ]9 T; Q7 ^$ W9 y6 C

% u/ L) F% A2 ?8 e) z- e/ V+ ]服务器在db表的Host、Db和User字段上查找一个匹配。 Host和User对应连
7 Z: K& z! P8 Y" n# Y, `! }接用户的主机名和MySQL用户名。Db字段对应用户想要存取的数据库。如果没有
, |" A; e3 c# ^( Y8 nHost和User的条目,存取被拒绝。
" y+ t9 z0 ~& J* a+ Z如果db表中的条目有一个匹配而且它的Host字段不是空白的,该条目定义用
1 l' N( W( \9 N+ m1 H: b户的数据库特定的权限。 0 J! z+ j0 C# m) y
如果匹配的db表的条目的Host字段是空白的,它表示host表列举主机应该被 0 w5 E/ z  U6 g2 o- w$ I
允许存取数据库的主机。在这种情况下,在host表中作进一步查找以发现Host和
% V7 T1 W3 F! W$ [Db字段上的匹配。如果没有host表条目匹配,存取被拒绝。如果有匹配,用户数 6 P4 U. u- a5 C. P% Z
据库特定的权限以在db和host表的条目的权限,即在两个条目都是'Y'的权限的交 ) l2 T& `! D4 C: t8 t
集(而不是并集!)计算。(这样你可以授予在db表条目中的一般权限,然后用host / c5 g! j$ f7 s: b2 K( ]& n
表条目按一个主机一个主机为基础地有选择地限制它们。)
& T& I3 G4 i" Y6 {" y在确定了由db和host表条目授予的数据库特定的权限后,服务器把他们加到
9 n3 H0 ?5 F- Z2 Q由user表授予的全局权限中。如果结果允许请求的操作,存取被授权。否则,服 % ~& _. J  Z- ]) }5 P
务器检查在tables_priv和columns_priv表中的用户的表和列权限并把它们加到 4 ?9 P1 y# {5 k3 @  F* B- w
用户权限中。基于此结果允许或拒绝存取。
9 f8 t% D( \5 \" m$ a  W$ W& x+ V4 w5 w; ]. t5 E
用布尔术语表示,前面关于一个用户权限如何计算的描述可以这样总结: & e5 r3 `# U  y0 V

4 ?4 Y) ]" d5 G+ ]global privileges
5 }3 b1 Y+ B( j. Y/ F+ L7 POR (database privileges AND host privileges)
: }) W. i' m: \, tOR table privileges 6 [" Y( Y' I9 F$ o& o2 |# Q+ I
OR column privileges
) `% u! C. L9 a  ]  n5 C0 l  |$ W! w  s" ^
它可能不明显,为什么呢,如果全局user条目的权限最初发现对请求的操作不 8 N. S! U( H: X+ h5 P. T8 S: Q  ]
够,服务器以后把这些权限加到数据库、表和列的特定权限。原因是一个请求可能
9 D) v/ R6 N7 `5 J7 Z0 A0 D7 c要求超过一种类型的权限。例如,如果你执行一个INSERT ... SELECT语句,你就都
' s# o1 X9 ^# M% f7 ?3 \要insert和select权限。你的权限必须如此以便user表条目授予一个权限而db表条
" Q& j/ F" o( r7 F7 C4 W: m目授予另一个。在这种情况下,你有必要的权限执行请求,但是服务器不能自己把
9 C" X. `: n6 z9 M( F8 X. O3 O, @两个表区别开来;两个条目授予的权限必须组合起来。 - R# ?7 [) ?3 t" ]

; v/ p  C  T) ?" Mhost表能被用来维护一个“安全”服务器列表。在TcX,host表包含一个在本
4 x: c% y( q+ O. U+ a地的网络上所有的机器的表,这些被授予所有的权限。 ( L; X* D7 }0 d9 _+ x8 R5 j* a) O' F

% t# X3 l. h) O& C你也可以使用host表指定不安全的主机。假定你有一台机器public.your. 8 n% x9 W5 W0 g5 j7 h
domain,它位于你不认为是安全的一个公共区域,你可以用下列的host表条目子允
5 ^0 F5 u  M, Z2 d$ \5 b许除了那台机器外的网络上所有主机的存取: % Y2 k  l0 Y* V) `- L

# ]& \' u3 J9 w4 C# F3 u) t. h' e: J! \/ i" m
+--------------------+----+-
5 w6 T6 ~1 w, S2 Y, Y│ Host │ Db │ ... 5 ?, u) S! C; `( t! r# n
+--------------------+----+-
& B5 X9 r" C/ W: s8 @4 y8 |: T7 w│ public.your.domain │ % │ ... (所有权限设为 'N') 2 B3 O7 G& N( U7 h2 p
│ %.your.domain │ % │ ... (所有权限设为 'Y') 6 `/ ]: `! K. V4 f) J: n% G
+--------------------+----+-
; g5 t9 x5 a. R# L, v6 v5 Y* L' q' V% f; Z7 `
当然,你应该总是测试你在授权表中的条目(例如,使用mysqlaccess)让你确保 ; L; F; _+ P+ i& `+ a. z
你的存取权限实际上以你认为的方式被设置。 # @( j. o  Z1 l/ ^' f% d
2 p  h; ^- J7 Q, c5 @1 z) h+ ~. A- }
权限更改何时生效
7 y4 K4 j. I* P3 E当mysqld启动时,所有的授权表内容被读进存储器并且从那点生效。
: Z. x$ t& c9 c) M' G( w) B
4 F5 Y$ w  p% J9 }$ f) @用GRANT、REVOKE或SET PASSWORD对授权表施行的修改会立即被服务器注意到。
' i& T$ u. C: @2 C! `$ |9 e  y8 c" j$ s* P+ d  E* m4 |6 h! A1 l
如果你手工地修改授权表(使用INSERT、UPDATE等等),你应该执行一个FLUSH % _; [. L2 `% x. B3 r$ B, z
PRIVILEGES语句或运行mysqladmin flush-privileges告诉服务器再装载授权表,否 0 n# b7 X7 U7 |
则你的改变将不生效,除非你重启服务器。
& j9 O4 f/ |" U8 C( s" p' T
+ L3 X5 o2 `; ?6 P* E3 p; P' i当服务器注意到授权表被改变了时,现存的客户连接有如下影响:
  I! C: I) v- ^0 ^8 G- S
& K9 \! l7 a, n* b* J8 m1 K+ r表和列权限在客户的下一次请求时生效。 0 m$ H0 A$ \0 u2 j' C" J
数据库权限改变在下一个USE db_name命令生效。 5 W& [  R$ O, D* j, L
全局权限的改变和口令改变在下一次客户连接时生效。 ! }, N, M' X) T

7 @; c0 D) X( [; F" L, }( K建立初始的MySQL权限 2 A& Z( E5 Q) _: y) X0 n# D1 M4 E+ g1 \
在安装MySQL后,你通过运行scripts/mysql_install_db安装初始的存取权限。
; S! z1 T  ?0 ?& l' `" G) ~' |scripts/mysql_install_db脚本启动mysqld服务器,然后初始化授权表,包含下列   p" X* f/ \1 a: }
权限集合:
( l- \4 k/ X: {1 }# |9 i
- ~: [1 h( i" M; {6 N/ Y# I2 `* B/ \MySQL root用户作为可做任何事情的一个超级用户被创造。连接必须由本地主
9 g0 Z9 u/ G) {. }' Y机发出。注意:出世的root口令是空的,因此任何人能以root而没有一个口令进行 ( l6 c6 a9 d) L' y/ [+ z6 @+ H  g
连接并且被授予所有权限。
1 q7 U2 ], F$ `6 g, d' W一个匿名用户被创造,他可对有一个'test'或以'test_'开始的名字的数据库 + g5 \" s0 V5 ~2 [+ I  I- u
做任何时期事情,连接必须由本地主机发出。这意味着任何本地用户能连接并且视
4 O1 k6 d0 M: i. Z# z4 y, b为匿名用户。
9 K6 v+ k# f) j3 I其他权限被拒绝。例如,一般用户不能使用mysqladmin shutdown或
/ M- F, @8 Z7 f# imysqladmin processlist。
% a6 _5 d* Z! n8 W/ m0 V注意:对Win32的初始权限是不同的。
0 d  ]! x% u6 d  D7 o0 I0 f; U* U; Y
既然你的安装初始时广开大门,你首先应该做的事情之一是为MySQL root用户 ) e5 ^+ o7 z1 v8 v1 n
指定一个口令。你可以做如下(注意,你使用PASSWORD()函数指定口令):
3 D! |* [& }- {+ o7 p+ N2 i! q; X/ k
shell> mysql -u root mysql 9 y* }0 K4 K, ~- M( ~
mysql> UPDATE user SET Password=PASSWORD('new_password') & s% u: X7 n. y$ E( F6 h9 c
WHERE user='root';
7 q7 `8 j6 m/ zmysql> FLUSH PRIVILEGES; 1 c- y) v8 x; @
0 Q4 a8 H5 o0 @
在MySQL 3.22和以上版本中,你可以使用SET PASSWORD语句: 9 T, p$ m$ i1 \  H* {: b* u5 M
; V" w8 ~# s$ [  M, Y0 r
shell> mysql -u root mysql , r2 H5 S5 e( K
mysql> SET PASSWORD FOR root=PASSWORD('new_password'); ; `9 M4 `7 \2 c1 t) e
: E9 U8 h' F: M5 ]; @& e2 g- {0 J
设置口令的另一种方法是使用mysqladmin命令:
# r, M& Z6 c) d* E$ E' Z/ ^6 E
9 |4 w' @/ b+ u7 O2 D5 V% U+ Jshell> mysqladmin -u root password new_password
$ |+ z3 Q( @1 j. v' l# v7 h" N1 y" C9 n) I5 c% i/ N( w" U
注意:如果你使用第一种方法在user表里直接更新口令,你必须告诉服务器 2 c' Q/ ]8 ?# l  Y" L, T, l7 j
再次读入授权表(用FLUSH PRIVILEGES),因为否则改变将不被注意到。
; e3 d3 m) F' o4 R) P. A6 ~' B$ C+ |3 \9 h4 ~0 C& Q  {3 y  L2 o
一旦root口令被设置,此后当你作为root与服务器连接时,你必须供应那个
0 X2 Q2 h% R8 l2 g* t" M6 J口令。 2 n6 t9 O7 W' i4 P
* J. Z" M; S' |  j$ V) ?
你可能希望让root口令为空白以便当你施行附加的安装时,你不需要指定它 7 X* W5 g$ w# h3 m4 G, Z
或测试,但是保证在任何真实的生产工作中使用你的安装之前,设置它。
2 ?9 f' M: i+ B$ l
# j* [$ D/ J/ X" d+ L7 t5 F看看scripts/mysql_install_db脚本,看它如何安装缺省的权限。你可用它 5 h$ d0 E+ u4 I/ S) n! f6 Q
作为一个研究如何增加其他用户的基础。 + D; s7 k, D9 x* r
4 E- P2 F% {5 N5 e3 A
如果你想要初始的权限不同于上面描述的那些,在你运行mysql_install_db 4 C* s, {2 u! n$ B& t& C- E
之前,你可以修改它。 " w% l  P2 \* O: L
# o2 l5 ?9 c, H5 Q
为了完全重建权限表,删除在包含mysql数据库的目录下所有“*.frm”, 6 x" V3 @. A: k, h
“*.MYI”和“*.MYD”文件。(这是在数据库目录下面命名为“mysql”的目录,
  G- \/ A. o$ F% h! ?. j% J7 c当你运行mysqld --help时,它被列出。)然后运行mysql_install_db脚本,可能 7 k  \8 M7 c$ @' C1 Z4 R: p
在首先编辑它拥有你想要的权限之后。
% ]9 a) {3 q# n( ~" Z% m  y
# _5 ]6 A8 i7 p/ N) M注意:对于比MySQL 3.22.10旧的版本,你不应该删除“*.frm”文件。如果
; F8 j# D& }( `4 A) @. J& V你偶然做了,你应该在运行mysql_install_db之前你的MySQL分发中拷回它们。
% S3 s9 o: b" e) Z; p" Y, s& R: Z9 Z, z# q. l( N0 E
向MySQL增加新用户权限
4 l: g7 G( L' q5 M; p你可以有2个不同的方法增加用户:通过使用GRANT语句或通过直接操作MySQL授
1 F2 M( V% X2 N权表。比较好的方法是使用GRANT语句,因为他们是更简明并且好像错误少些。   ~( w; p$ R4 E* v2 s
6 U% ^  E3 \- |4 |% z, Q' Q
下面的例子显示出如何使用mysql客户安装新用户。这些例子假定权限根据以前 6 W9 _3 B; G& u" V6 Y6 a
的章节描述的缺省被安装。这意味着为了改变,你必须在mysqld正在运行同一台
- t$ }( t! b& P# d机器上,你必须作为MySQL root用户连接,并且root用户必须对mysql数据库有 2 I3 ~; v3 f/ A( Q  O
insert权限和reload管理权限。另外,如果你改变了root用户口令,你必须如下
' a9 b+ I, k0 E( k$ t# N的mysql命令指定它。 / B9 v: W4 z, H3 {- D' A
/ ^( ~9 _4 h8 J  V& c
你可以通过发出GRANT语句增加新用户:
1 T: L1 E2 W  I! \, A7 ^# t
- o7 p8 R! p  j5 W7 sshell> mysql --user=root mysql
, A3 _) h9 G& q4 ?8 Y1 S, @5 w% qmysql> GRANT ALL PRIVILEGES ON *.* TO monty@localhost 6 F6 ~7 f- \! \: Z, Z; Y
IDENTIFIED BY 'something' WITH GRANT OPTION;
, \" x. b2 ]& v9 S# o: }mysql> GRANT ALL PRIVILEGES ON *.* TO monty@"%"
* `9 q4 W6 a. N0 w5 X( fIDENTIFIED BY 'something' WITH GRANT OPTION;
6 s9 S2 d8 z# F' Ymysql> GRANT RELOAD,PROCESS ON *.* TO admin@localhost; 9 G0 r7 {" |+ o. U1 u: q& @7 |
mysql> GRANT USAGE ON *.* TO dummy@localhost;   ?. ?) G/ }; e+ u

8 J2 _4 q' L( o: P6 ~9 U这些GRANT语句安装3个新用户:
; H0 d( }  q- O$ x: G- A) Y7 [. m$ f3 Z
monty ( P/ z/ Z, L( h) }
可以从任何地方连接服务器的一个完全的超级用户,但是必须使用一个
8 D, i' |: v* A& k+ b: H口令('something'做这个。注意,我们必须对monty@localhost和monty@"%"
* x1 e- ]" S3 a6 }发出GRANT语句。如果我们增加localhost条目,对localhost的匿名用户条目
3 e+ r; u6 ?7 T$ B: b- Y- e0 {在我们从本地主机连接接时由mysql_install_db创建的条目将优先考虑,因为 , M) ?9 V, v& x
它有更特定的Host字段值,所以以user表排列顺序看更早到来。 2 j% b0 Y9 ~3 O0 R
admin
# Z' y7 l3 D' G  x可以从localhost没有一个口令进行连接并且被授予reload和process管理 % U3 H. G. ]2 Z
权限的用户。这允许用户执行mysqladmin reload、mysqladmin refresh和
% C- T  d& _5 t1 n, t! Jmysqladmin flush-*命令,还有mysqladmin processlist。没有授予数据库有 / {: h# l4 k" z$ Z
关的权限。他们能在以后通过发出另一个GRANT语句授权。
* J% ]4 P8 B& v; w& P. z( Fdummy : ~$ M5 O* C: ^0 T$ T, y5 M' p
可以不用一个口令连接的一个用户,但是只能从本地主机。全局权限被设 9 X/ N, p) Z7 r3 S$ L4 L
置为'N'--USAGE权限类型允许你无需权限就可设置一个用户。它假定你将在以
" E1 c% b  R7 q  s9 N后授予数据库相关的权限。 + k3 k& P6 q/ a# E2 X
你也可以直接通过发出INSERT语句增加同样的用户存取信息,然后告诉服   k0 Y1 K$ \5 m# V4 |. V1 G& c  M
务器再次装入授权表:
* ~( ?$ l7 f( L. d4 `. W
: V7 `, q7 N2 I" Qshell> mysql --user=root mysql ( U" M0 o" ~& z! l) H" K! z  u
mysql> INSERT INTO user VALUES('localhost','monty',PASSWORD 2 }  Z% X7 T1 V3 v: Y
('something'), 7 U( t0 n' h* F1 x* [
'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y',
% N* G% [2 C$ {8 I# Q'Y','Y') 7 W5 y; M$ g4 ^1 e- p0 R& j
mysql> INSERT INTO user VALUES('%','monty',PASSWORD('something'),
: L) L3 \' R" i0 E2 j% N; A% k'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y',
2 G* C( I. J6 e  e( J/ ['Y') % |" [9 |6 p- D/ g  Q
mysql> INSERT INTO user SET Host='localhost',User='admin',
" u7 h4 }$ d) D& R5 G6 tReload_priv='Y', Process_priv='Y'; 4 M! ~! @. g+ V
mysql> INSERT INTO user (Host,User,Password) 9 J1 `. i8 C6 h, S5 ^3 R+ i
VALUES('localhost','dummy',''); # u4 t+ d) @$ D; O4 L3 P1 X
mysql> FLUSH PRIVILEGES;
* I# _8 r7 |$ X& B
( Y/ ^. p& U' I+ }% A$ h9 f8 c取决于你的MySQL版本,对上述,你可能必须使用一个不同数目'Y'值(在
0 l6 }; U: l& {* I: B3.22.11以前的版本有更少的权限列)。对admin用户,只用在3.22.11开始的版 ; b4 q' `' E8 k) e% N- M0 P
本具有的更加可读的INSERT扩充的语法。 2 X2 s9 W) B1 u* ^. ^  z
6 s# d; |% K+ |/ }7 o; X
注意,为了设置一个超级用户,你只需创造一个user表条目,其权限字段设为 / `6 b4 T9 S/ f/ k$ l3 b5 K! e
'Y'。不需要db或host表的条目。 , l% r, t4 L; I& Y2 w- \8 q7 s" j
/ W! \$ x2 e# y) }/ ^7 S7 D( D
在user表中的权限列不是由最后一个INSERT语句明确设置的(对dummy用户),
% P4 n' P6 z. U- E# R因此那些列被赋予缺省值'N'。这是GRANT USAGE做的同样的事情。
/ Y- G) y: h3 x- `7 ?
2 f( R8 J; K" p+ v下列例子增加一个用户custom,他能从主机localhost、server.domain和
% F: ^. f6 d4 _whitehouse.gov连接。他只想要从localhost存取bankaccount数据库,从
: x# I- _& C- H6 ?& nwhitehouse.gov存取expenses数据库和从所有3台主机存取customer数据库。他
+ I8 e3 y% P9 G想要从所有3台主机上使用口令stupid。
& j( h+ V+ K# X8 c0 t0 {- k$ k" q
. ^$ ?- ]8 O4 _0 k3 a为了使用GRANT语句设置个用户的权限,运行这些命令: ; y% ?+ @/ W% V1 P) f

& N/ G/ P9 l1 Q9 Dshell> mysql --user=root mysql
, H# Z) a; T4 W) f% M5 E- P+ ?4 F# Omysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
# h- p( G: y! V% {1 \ON bankaccount.*
8 N/ n0 E: ?/ RTO custom@localhost 7 G. L1 D& @. i$ K" m+ e$ `$ i
IDENTIFIED BY 'stupid';
! I4 H0 G8 c& emysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP * z( d- I0 Y1 j* k/ \. y
ON expenses.*
2 A9 Q0 T- `$ m/ h& m# G7 eTO custom@whitehouse.gov " \8 e' {  C! J. p
IDENTIFIED BY 'stupid'; 8 \5 i$ Y, A# P
mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
- W- D* c( h' e: b' ]& [/ t0 C8 xON customer.* ( q" u, Q/ m: e2 t
TO custom@'%'
) v: v+ r+ @4 x0 b; L% KIDENTIFIED BY 'stupid'; * z! ?3 Y! s2 j$ l# Y$ l, X' W9 H+ I
( h5 x& _! K# S5 q
通过直接修改授权表设置用户权限,运行这些命令(注意,在结束时
5 I; K6 T2 W/ ~+ l2 lFLUSH PRIVILEGES):
! m' Z: k) W8 j8 M: |& y* }" w& Y: Q( B/ b2 G
shell> mysql --user=root mysql
( `6 ]4 a: S7 [9 Imysql> INSERT INTO user (Host,User,Password)
- ^+ L3 n& u  q2 ~% oVALUES('localhost','custom',PASSWORD('stupid')); % ^. W- r6 V5 W8 h+ K/ g
mysql> INSERT INTO user (Host,User,Password)
( l6 C& t+ z% D; x3 KVALUES('server.domain','custom',PASSWORD('stupid')); 8 c. r' A6 @: |* t/ B
mysql> INSERT INTO user (Host,User,Password) . `6 |9 j$ q' }+ F% z! l
VALUES('whitehouse.gov','custom',PASSWORD('stupid')); , ^% K8 b% X( K0 {
mysql> INSERT INTO db + M, V; x1 {8 T
(Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv,
& E% }8 s' q0 w$ UCreate_priv,Drop_priv) * f) q* N7 q0 b9 b; U! _. |
VALUES
. ?# E' w) A6 P('localhost','bankaccount','custom','Y','Y','Y','Y','Y','Y'); 8 x+ {6 ~: H4 b( t" h
mysql> INSERT INTO db 7 v2 t7 W% Q3 h8 X1 v
(Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv,
  K$ G! u* ^5 B+ X* m  LCreate_priv,Drop_priv)
* m5 H' C1 \+ c. y* H* T" `) ~VALUES
4 m- ?& N4 R  J  N('whitehouse.gov','expenses','custom','Y','Y','Y','Y','Y','Y'); 0 }5 |, L+ x" H0 J8 J
mysql> INSERT INTO db
4 L) Y' a9 p- O- [" p(Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv, # j; G, g( z; f$ J
Create_priv,Drop_priv)   ?' J0 a/ O1 Y4 @5 z0 h2 B
VALUES('%','customer','custom','Y','Y','Y','Y','Y','Y'); ! K, h$ l- w- C) T( ?2 @' |$ x; C
mysql> FLUSH PRIVILEGES; - s  d9 O+ {6 S! C, o3 J

1 [; ~- M4 M* x# r头3个INSERT语句增加user表条目,允许用户custom用给定口令从不同的主机
. F0 W0 t+ Z  T7 N- \' ?& W; c6 @8 o进行连接,但是没有授予任何许可(所有权限被设置为缺省值'N')。后3个INSERT 2 \. H2 W2 d8 C- t
语句增加db表条目,授予custom以bankaccount、expenses和customer数据库权限, : n: d* c- |7 |8 Z: R2 s9 |. f
但是只能在从正确的主机存取时。通常,在授权表直接被修改时,服务器必须被告   u2 n7 O% z3 E9 l  e
知再次装入他们(用FLUSH PRIVILEGES)以便使权限修改生效。 5 e( @! ~+ u4 }3 \' z) |: {/ K

, z. _2 ^& U% G# Q( o( f" A. y如果你想要给特定的用户从一个给定的域上的任何机器上存取权限,你可以发
; ^1 A! @& W2 C, V出一个如下的GRANT语句:
3 p% B6 Y7 {. {/ T  p! x! H7 ?6 a: t( {/ V3 M
mysql> GRANT ...
4 M8 L! v+ _' W6 [# e2 v7 N5 XON *.*
) n) G! k% C6 X7 xTO myusername@"%.mydomainname.com"
' ?0 f6 M3 t2 ^: |3 |# ^  W  d/ QIDENTIFIED BY 'mypassword'; ) p7 e- y5 R; n8 `' Z

! D; C9 G3 ^6 Q; t+ O为了通过直接修改授权表做同样的事情,这样做:
# ?, h" T5 I6 ^& O1 N/ o$ \' v
, o$ G8 i- x5 e) c9 W. h, i- omysql> INSERT INTO user VALUES ('%.mydomainname.com', 'myusername', . s2 q2 Y* Z. B' h) T; ^* D7 @
PASSWORD('mypassword'),...); 9 d% n: Q" d+ b' T6 c
mysql> FLUSH PRIVILEGES;
/ l& A, {2 X3 s6 c! i
9 e, I3 q1 q  O- \9 }9 L你也可以使用xmysqladmin、mysql_webadmin甚至xmysql在授权表中插入、改变
; }$ D& J6 O7 r. a和更新值。你可以在MySQL的Contrib目录找到这些实用程序。
7 U* B9 _3 e4 T2 j1 k+ w% {) i4 K" n) v6 W" O0 J# z' r
怎样设置口令 ( k4 Q: q# {& m# X
在前面小节的例子里说明了一个重要的原则:当你使用INSERT或UPDATE语句存 * Q* z' n( |* s; C6 o
储一个非空的口令时,你必须使用PASSWORD()函数加密它。这是因为在user表中以 * A0 [9 `+ [! e
加密形式存储口令,而不是作为纯文本。如果你忘记这个事实,你可能像这样试图
8 {+ d" Y' J4 F: Z) y( l设置口令:
/ t& a/ T; ~) q
* {4 v; p4 y- d6 j; Q; h0 S1 r" Ashell> mysql -u root mysql
: V7 s+ k5 B1 r: Y: umysql> INSERT INTO user (Host,User,Password) VALUES('%','jeffrey', - S# c& k5 n( H3 S, \4 |$ s
'biscuit');
# T5 F! u2 v) h9 c' `( Smysql> FLUSH PRIVILEGES 2 q3 ~, M" O( B( V

3 [# T6 A$ t+ j8 E7 C- O结果是纯文本值'biscuit'作为口令被存储在user表中。在用户jeffrey试图用 ; W) T$ R5 ^- \# V2 [# p0 g
这个口令连接服务器时,mysql客户用PASSWORD()加密它并且将结果送给服务器,服 5 M- t, _2 H7 J% A  a/ E. R& p
务器比较在user表中的值(它是纯文本值'biscuit')和加密的口令(而不是 5 A; y+ }3 x7 ?! d& _$ O+ I
'biscuit'),比较失败并且服务器拒绝连接: 3 S. r# p' t% ~& J

. p' H; D$ y) L0 |: G# U6 rshell> mysql -u jeffrey -pbiscuit test ) q( l; `" |2 n  M" ]2 M
Access denied
) F- ~- N: S( O
8 _! Z- m) ~) |4 h/ p因为当他们被插入user表时,口令必须被加密,相反,INSERT语句应该象这样
& `/ I# ?7 ?0 J被指定:
/ S, h9 b% p" M
  b# m6 [4 j3 \% d8 umysql> INSERT INTO user (Host,User,Password) / r$ E3 p5 n, X9 @0 c3 ?, w
VALUES('%','jeffrey',PASSWORD('biscuit')); 1 d4 r+ K& @& r, q+ [% [3 b+ _' h

* D/ I6 h2 G  q4 \5 I* O当你使用SET PASSWORD语句时,你也必须使用PASSWORD()函数:
2 W/ m9 ~5 l+ ^$ P! o5 a8 p, f% U5 E6 L9 V& ?9 ^* B1 R
mysql> SET PASSWORD FOR jeffrey@"%" = PASSWORD('biscuit'); 8 @1 y" g- L7 Q2 ~" x

7 t- v5 D6 X" X1 E+ l8 }如果你使用GRANT ... IDENTIFIED BY语句或mysqladmin password命令设置口 ' U# U  p( U8 S, ]( `1 n. _
令,PASSWORD()函数是不必要的。他们都考虑到为你加密口令,多以你可像这样指
9 L4 M/ i7 M! g: v定一个口令'biscuit': 9 p4 |2 d! D" _8 N2 C1 J

  l. G: X0 I, K  v4 c+ E; tmysql> GRANT USAGE ON *.* TO jeffrey@"%" IDENTIFIED BY 'biscuit';
) p+ |, ?2 M) a* A& w- `; E) L) u

2 D5 ^$ m( K# ?# F
9 z7 p+ i, x% K' nshell> mysqladmin -u jeffrey password biscuit & Q$ l' n: t( c  f! N% q" x' u
注意: PASSWORD()不是以在Unix口令加密的同样方法施行口令加密。你不应
* R- y% P( E& b该假定如果你的Unix口令和你的MySQL口令是一样的,PASSWORD()将导致与在Unix / `( {' F( @$ ?" n( Y3 i
口令文件被存储的同样的加密值。见6.2 MySQL 用户名和口令。
) ?9 S( {  _) D+ a# ^/ T9 j8 Y1 @- }$ P& w% |
Access denied错误的原因
4 k; b4 P! r- e' G$ b当你试着联接MySQL服务器时,如果你碰到Access denied错误,显示在下面 : I% R" S- u* G( P" v
的表指出一些你能用来更正这个问题的动作: $ c3 P! S6 f+ w
; f# T# L  R) G' `: G" b, `2 k7 S
你是在安装MySQL以后运行mysql_install_db的脚本,来设置初始授权表内容
$ i' I$ _% U# }3 P) m6 ]) @吗?如果不是,这样做。见6.10 设置初始MySQL权限。通过执行这个命令测试初
! A& a9 I  k* _1 W始权限: 4 r1 h5 n2 ^9 |4 M( ~2 P- s! _
shell> mysql -u root test
, ?! o) H- P: r8 K7 j
' j& x  ]) u/ m! J1 X' z: L3 n服务器应该让你无误地连接。你也应该保证你在MySQL数据库目录有一个文件
2 l! U( k9 W- U, Z, x. ?“user.MYD”。通常,它是“PATH/var/mysql/user.MYD”,在此PATH是MySQL安 ! [* W2 z, G3 n! r1 X5 m
装根目录的路径。
5 a3 o8 N8 `, `; b
' b' I1 K4 \; U" l* o4 L/ R' i) w在一个新的安装以后,你应该连接服务器并且设置你的用户及其存取许可:
# K! r8 R2 ]7 j' t1 }, [shell> mysql -u root mysql
6 F7 Q9 _& [  m5 H# g/ @/ `/ E. n- M7 Y4 F
服务器应该让你连接,因为MySQL root用户初始时没有口令。既然那也是一个 0 z* c0 K, Z, W( U9 g
安全风险,当你正在设置其他MySQL用户时,设定root口令是一件重要的事请。如 " e& B) ?3 h. S' G8 z
果你作为root尝试连接并且得到这个错误:
! \8 L9 O) o/ U* S& k: y: n% N8 m' W2 x! o& G2 b* \/ c
Access denied for user: '@unknown' to database mysql 1 _' G8 C' g0 O" u% ~+ J
' Y$ Y( F' L2 X7 C" b( Y. J2 h4 z, }
这意味着,你没有一个条目在user表中的一个User列值为'root'并且mysqld
- k" }, P" m2 B9 S2 m6 j" Y1 s不能为你的客库解析主机名。在这种情况下,你必须用--skip-grant-tables选项 7 \& N2 y; o* L3 j% X9 c) ^
重启服务器并且编辑你的“/etc/hosts”或“\windows\hosts”文件为你的主机
2 F7 Q) U8 ]4 {6 |1 T# G$ F增加一个条目。 4 G( _1 w( e4 ^, D7 V( t  |

8 o; Y/ D" c* `9 V如果你从一个3.22.11以前的版本更新一个现存的MySQL安装到3.22.11版或以 ) p  b* f3 r4 d/ ?- ]
后版本,你运行了mysql_fix_privilege_tables脚本吗?如果没有,运行它。在 * B  t- f! {# I2 \9 v) T1 G4 J
GRANT语句变得能工作时,授权表的结构用MySQL 3.22.11修改 。 $ r, ^- y$ K. H4 y+ B: a
如果你直接对授权表做修改(使用INSERT或UPDATE语句)并且你的改变似乎被 4 i5 _4 `7 T( r; X9 T
忽略,记住,你必须发出一个FLUSH PRIVILEGES语句或执行一个mysqladmin
3 S0 X! e; t( g% X) ~flush-privileges命令导致服务器再次读入表,否则你的改变要道下一次服务器被
  z  g2 |% T) H/ B0 ~重启时再生效。记住在你设定root口令以后,你将不需要指定它,直到在你清洗
7 f! k( g$ [2 ~% w+ m) R6 i2 H(flush)权限以后,因为服务器仍然不会知道你改变了口令!
% h, L0 ~+ d9 [- C如果你的权限似乎在一个会话(session)当中改变了,可能是一个超级用户改变 . N% Q: S4 S6 K9 a, h: @, X
了他们。再次装入授权表作用于新客户连接,但是它也影响现存的连接,如6.9 权
8 Y) u% `/ D, ]# N  b8 p限改变何时生效小节所述。 ' \/ j' J* v6 d( ~% l2 o
为了测试,用--skip-grant-tables选项启动mysqld守护进程,然后你可以改变 $ ~8 S, E+ f' y$ A6 y/ Q3 `) R; u
MySQL授权表并且使用mysqlaccess脚本检查你的修改是否有如期的效果。当你对你的 , A) q. d% j( U
改变满意时,执行mysqladmin flush-privileges告诉mysqld服务器开始使用新的权
1 p+ j; M7 z9 F7 n7 K' m. e8 R) H限表。注意:再次装入授权表覆盖了--skip-grant-tables选项。这允许你告诉服务
* {6 S# N. m& r! j! H器开始使用授权表,而不用停掉并重启它。 ' u$ N2 D" c: N, T9 M
如果你有一个Perl、Python或ODBC程序的存取问题,试着用mysql -u user_name 2 I: |" H& S2 m) A0 b
db_name或mysql -u user_name -pyour_pass db_name与服务器连接。如果你能用
9 `; I( a; K! v7 u* Mmysql客户连接,这是你程序的一个问题而不是存取权限的问题。(注意在-p和口令
6 D: _9 G" z8 s( T) ]5 K之间没有空格;你也能使用--password=your_pass句法指定口令。) " M/ l  c+ j, ]( h" c
如果你不能让口令工作,记得如果你用INSERT, UPDATE或SET PASSWORD语句
& p/ }* g9 u" M+ d3 X, X6 {设置口令,你必须使用PASSWORD()函数。如果你用GRANT ... INDENTIFIED BY语
. o: ~& w6 [7 c# T, D$ y句或mysqladmin password命令指定口令,PASSWORD()函数是不需要的。
" @# B& E' m( s' ]localhost是你本地主机名的一个同义词,并且也是如果你不明确地指定主机 1 V7 X1 F% b* r! E
而客户尝试连接的缺省主机。然而,如果你正在运行于一个使用MIT-pthreads的系 4 g1 [! D9 G- D+ O
统上,连接localhost是不行的(localhost连接使用Unix套接字进行,它没被 MIT
' A* J2 Z& m' V- K-pthreads支持),为了在这样的系统上避免这个问题,你应该使用--host选项明确
' Z% m( y1 _: M8 B# l( B9 K/ H: M地命名服务器主机,这将做一个 TCP/IP连接到mysqld服务器。在这种情况下,你
  W9 e" g6 p" O: Q必须有在服务器主机上的user表中条目的你真实的主机名。(即使你在服务器同一 - _: S8 h4 H; T! c0 n% K$ o$ C- f
台的主机上运行一个客户程序,这也是真的。)
3 |! X! g, G: c! w! b$ E当尝试用mysql -u user_name db_name与数据库连接时,如果你得到一个 ! D/ u. C/ k: g8 N- `" M
Access denied错误,你可能有与user桌有关的问题,通过执行mysql -u root - E7 `) a& n% F: A1 U5 K# ?
mysql并且发出下面的SQL语句检查:
# a8 U9 O/ h! W) Q3 K, v# w8 V- p# Smysql> SELECT * FROM user; $ m- z3 T8 y- O8 G/ n5 Z

/ P. l% [4 a( B9 R* Y# u结果应该包含一个有Host和User列的条目匹配你的计算机主机名和你的MySQL用户
# @$ ?7 L; K: A- b8 U$ u/ F  {名。 5 L- E7 v5 P! L& T

  {9 }+ J. ~" @; F4 W3 ^. W: s, SAccess denied错误消息将告诉你,你正在用哪个用户尝试登录,你正在试图 3 E# x3 S1 v" y! b: S% ]6 m
用连接哪个主机,并且你是否正在使用一个口令。通常,你应该在user表中有一
- E5 X: \! i9 C1 n: `个条目,正确地匹配在错误消息给出的主机名和用户名。 - R0 s$ @  l2 H8 e
如果当你试着从一个不是MySQL服务器正在运行的主机上连接时,你得到下列
/ s( |  I/ T3 F) ]6 N+ W! p' R/ J$ ~错误,那么在user表中没有匹配那台主机行: - j0 p4 S* N" C; G
Host ... is not allowed to connect to this MySQL server
1 |- C) s! G# @+ o& d4 W3 ^* Y( u( i9 h9 ^- J2 ?. Q8 e
你可以通过使用mysql命令行工具(在服务器主机上!)修正它,把你正在试 0 L. U) k4 L; c- ~, ~
图连接的用户/主机名组合新加一行到user表中。如果你不在运行MySQL 3.22并且 . W9 |* t6 T4 B6 p
你不知道你正在从它连接的机器的IP数字或主机名,你应该把一个'%'条目作为
' y5 I6 d- P/ H9 ^5 z" @Host列值放在user表中并且在服务器机器上使用--log选项重启mysqld。在试图从
( ?% ]/ H) x" B客户机器连接以后,在MySQL记录文件中的信息将显示你如何真正进行连接。(
/ w$ V: F  s, K$ t5 P1 m* a; L& N然后用在记录文件上面显示出的实际的主机名代替user表中的'%'条目。否则, & g& M7 ?! p! ]3 @
你将有一个不安全的系统。) # B: }% {$ E0 h3 K2 Y6 t
- L8 h. I7 S; O- J, _: S
如果mysql -u root test工作但是mysql -h your_hostname -u root test
6 W4 E  w. D, ?/ U+ [/ Z导致Access denied,那么在user表中你可能没有你的主机的正确名字。这里的 3 V; d/ o  v7 k
一个普遍的问题是在user表条目中的Host值指定一个唯一的主机名,但是你系统
0 d/ Y" Z& y  [. G. E( u' l+ `6 j, j的名字解析例程返回一个完全正规的域名(或相反)。例如,如果你在user表中有
0 ^: h0 r# h7 _一个主机是'tcx'的条目,但是你的 DNS告诉MySQL你的主机名是'tcx.subnet. , O* x8 u- O; r5 ]; t
se',条目将不工作。尝试把一个条目加到user表中,它包含你主机的IP数字作
9 {; ]$ H" P2 g3 `为Host列的值。(另外,你可以把一个条目加到user表中,它有包含一个通配符
1 [" n2 o  p: z' p如'tcx.%'的Host值。然而,使用以“%”结尾的主机名是不安全的并且不推荐!)
) M/ E5 z5 T6 [  |$ s如果mysql -u user_name test工作但是mysql -u user_name other_db_name 3 s6 k* t7 ]/ r3 W
不工作,对other_db_name,你在db表中没有没有一个条目列出。 # O. F. p/ _% \% T! {
当在服务器机器上执行mysql -u user_name db_name时,它工作,但是在其
8 m* `7 J1 R5 K9 @  X; y5 G1 k它客户机器上执行mysql -h host_name -u user_name db_name时,它却不工作,
; k+ g  t' w/ ^1 e' S5 s你没有把客户机器列在user表或db表中。
4 v; \% Z8 M# K1 L" V如果你不能弄明白你为什么得到Access denied,从user表中删除所有Host 1 n9 G% k; L( I' X& q- c) W0 n
包含通配符值的条目(包含“%”或“_”的条目)。一个很普遍的错误是插入用 : ?. U3 j/ l2 ~
Host='%'和User='some user'插入一个新条目,认为这将允许你指定localhost
  X  Z) W+ }* e, \0 s* [& B$ X3 e从同一台机器进行连接。它不工作的原因是缺省权限包括一个有Host='localhost'
( K" D; k( L, A和User=''的条目,因为那个条目一个比'%'更具体的Host值'localhost',当从
2 c" B) t2 F) q5 Q( Flocalhost连接时,它用于指向新条目!正确的步骤是插入Host='localhost'和 * n% n" y' Z7 m. ^; h& n, p
User='some_user'的第2个条目,或删除Host='localhost'和User=''条目。
2 g  b/ J$ D2 K4 }5 p) Z7 T- [如果你得到下列错误,你可以有一个与db或host表有关的问题: ( j4 W% I. d3 j( U1 |
Access to database denied # k3 s+ e' @, ~4 L  e) {4 V
' x2 Z& S  F' Z8 ?; {1 S
如果从db表中选择了在Host列有空值的条目,保证在host表中有一个或多
6 S1 t# d: i0 y4 y. ~个相应的条目,指定运用db表中的哪些主机。如果在使用SQL命令SELECT ...
1 m1 `5 i- @/ P  bINTO OUTFILE或LOAD DATA INFILE时,你得到错误,在user表中的你的条目可
. W# t5 A# ^7 Q" o  A2 T, U能启用file权限。
2 p3 [8 S8 O6 t0 Y7 y- E, g( J. r+ B
记住,客户程序将使用在配置文件或环境变量被指定了的连接参数。如果
1 ]1 p' w# M) a$ b8 n当你不在命令行上指定他们时,一个客户似乎正在发送错误的缺省连接参数,
8 _* O: }+ b' d& L$ X9 C检查你的环境和在你的主目录下的“.my.cnf”文件。你也可以检查系统范围 ; v$ u% x& Q4 r1 \" `; {
的MySQL配置文件,尽管更不可能将在那里指定那个客户的连接参数。如果当   y+ F7 y5 u, T  C; t
你没有任何选项运行一个客户时,你得到Access denied,确认你没在任何选
( q" m  Q" w6 w4 w6 e5 _项文件里指定一个旧的口令!见4.15.4 选项文件。
7 S" k* G% k' E' I" V( i2 Q如果任何其它事情失败,用调试选项(例如,--debug=d,general,query)
! K7 O  y# P* Z5 |7 N- z+ Z( A- ?! f启动mysqld守护进程。这将打印有关尝试连接的主机和用户信息,和发出的每
6 U4 C0 H& B# Y9 T0 i+ e个命令的信息。见G.1 调试一个MySQL服务器。 - a4 \5 v0 Z/ i$ C! \! E# Q
如果你有任何与MySQL授权表的其它问题,而且觉得你必须邮寄这个问题 * c6 c1 B  y* H% P& {# j
到邮寄表,总是提供一个MySQL授权表的倾倒副本(dump)。你可用mysqldump
5 |7 J7 w( a8 t% g. P7 p! |mysql命令倾倒数据库表。象平时一样,用mysqlbug脚本邮寄你的问题。在一
& Z  I. a, `4 z& Y- y些情况下你可能用--skip-grant-tables重启mysqld以便能运行mysqldump。 7 u5 ?. e4 m2 W7 m$ D
怎样使MySQL安全以对抗解密高手 0 X  p. @( V! a: d6 _4 E& G
当你连接一个MySQL服务器时,你通常应该使用一个口令。口令不以明文
  Z  c; I* n8 R) k* z" ^% c  Q在连接上传输。
* s0 T# u- K- z; T7 q
; P. `* s& S* `% ?所有其它信息作为能被任何人读懂的文本被传输。如果你担心这个,你可 8 j& }3 `: k! T6 v7 T
使用压缩协议(MySQL3.22和以上版本)使事情变得更难。甚至为了使一切更安全
' g& z9 W1 b0 P# Z9 }/ O' u; u, C,你应该安装ssh(见http://www.cs.hut.fi/ssh)。用它,你能在一个MySQL服
/ |. o! j% y) o* M, o务器与一个MySQL客户之间得到一个加密的TCP/IP连接。 # E  {0 _# Y! D$ D  T, o1 G: \8 L
( [. P: j$ k5 E2 P! |9 c0 q$ y
为了使一个MySQL系统安全,强烈要求你考虑下列建议:
- p3 Z1 z2 Q$ u- @) o( i/ }
% q" D6 H1 E, r+ h8 Y对所有MySQL用户使用口令。记住,如果other_user没有口令,任何人能简 8 x6 \. v3 X6 ?
单地用mysql -u other_user db_name作为任何其它的人登录。对客户机/服务器
: M, q+ D$ e, O应用程序,客户可以指定任何用户名是常见的做法。在你运行它以前,你可以通
& I8 `5 w8 n3 h过编辑mysql_install_db脚本改变所有用户的口令,或仅仅MySQL root的口令,
6 w, d) H' s5 k% k+ ^; Q象这样:   T  V2 x' |$ T" S& m, b
shell> mysql -u root mysql 9 t  m3 _" ?0 P) L, D( Y
mysql> UPDATE user SET Password=PASSWORD('new_password')
; i! z$ J# T8 KWHERE user='root'; . b  Y* ^: F9 r4 ~& {. _; l
mysql> FLUSH PRIVILEGES;
. `6 q/ K# J3 Q
2 G# m2 n' V8 ?0 }% v. i# C不要作为Unix的root用户运行MySQL守护进程。mysqld能以任何用户运行, & q$ j5 H, s9 [4 ^
你也可以创造一个新的Unix用户mysql使一切更安全。如果你作为其它Unix用户
. @: `& S) b* ?  F$ ^8 y! j1 r) p运行mysqld,你不需要改变在user表中的root用户名,因为MySQL用户名与Unix
# X4 ^- S: Z. e4 Q; [用户名没关系。你可以作为其它Unix用户编辑mysql.server启动脚本mysqld。
  W9 I2 ]% v- |& a: _1 M0 ~通常这用su命令完成。对于更多的细节,见18.8 怎样作为一个一般用户运行
( W. y$ Z1 j& }4 @# qMySQL。
$ }9 R) C9 _; J; @- g如果你把一个Unix root用户口令放在mysql.server脚本中,确保这个脚本 : n% U) u4 X; L: k/ X( ^
只能对root是可读的。
, |) T+ J3 ^& V/ E, q( v" S4 H检查那个运行mysqld的Unix用户是唯一的在数据库目录下有读/写权限的用 2 z$ H( J! V8 z6 f. N
户。
" C! y; }; I& }0 V, m$ j; J不要把process权限给所有用户。mysqladmin processlist的输出显示出当 - S) M" _  J* r* r2 X. V
前执行的查询正文,如果另外的用户发出一个UPDATE user SET password= + d0 k, `9 ^- a5 y5 }7 z5 V4 G
PASSWORD('not_secure')查询,被允许执行那个命令的任何用户可能看得到。 % M) X" s: x/ d3 J- }
mysqld为有process权限的用户保留一个额外的连接, 以便一个MySQL root用
8 z) h3 c3 B, d% Q7 m7 r户能登录并检查,即使所有的正常连接在使用。
1 l& Y( K0 J. N% L- x不要把file权限给所有的用户。有这权限的任何用户能在拥有mysqld守护 0 a  |% Z/ _+ d9 @) F% I% |. ^
进程权限的文件系统那里写一个文件!为了使这更安全一些,用SELECT ... " p# p4 t  l2 l, |) p7 p* W
INTO OUTFILE生成的所有文件对每个人是可读的,并且你不能覆盖已经存在的 . x. {' z* s& j$ u
文件。file权限也可以被用来读取任何作为运行服务器的Unix用户可存取的文
+ c. Q* M7 h/ ?8 B3 \& Z) Q8 P4 Y) ~  z件。这可能被滥用,例如,通过使用LOAD DATA装载“/etc/passwd”进一个数
9 B6 v  U9 g8 y0 T2 k据库表,然后它能用SELECT被读入。 3 s: L1 o+ m0 R( i* D# \% b9 G
如果你不信任你的DNS,你应该在授权表中使用IP数字而不是主机名。原则 4 B0 j& {( ]& H% _  D8 L
上讲,--secure选项对mysqld应该使主机名更安全。在任何情况下,你应该非常 2 }1 u( e' E: h% H6 \
小心地使用包含通配符的主机名!
% x+ c3 z# M* I: m/ F( G( _下列mysqld选项影响安全:
* [% s; ~6 a6 \1 M0 }# N  n/ W5 {" w
--secure
& X3 K( H. P/ j/ t+ K$ j由gethostbyname()系统调用返回的IP数字被检查,确保他们解析回到原来 4 S  \+ ]0 ~5 s. N7 B
的主机名。这对某些外人通过模仿其它主机获得存取权限变得更难。这个选项也
* q( V* Z. [2 l. q5 F6 s增加一些聪明的主机名检查。在MySQL3.21里,选择缺省是关掉的,因为它有时
& i/ X& A, {6 `4 u8 \$ e它花很长时间执行反向解析。MySQL 3.22缓存主机名并缺省地启用了这个选项。
7 ~* T; g$ H5 N3 c; |- A7 q--skip-grant-tables
8 B9 O8 l0 [& E9 v这个选项导致服务器根本不使用权限系统。这给每个人以完全存取所有的数
8 O: C0 @' D! U- d( q7 w据库的权力!(通过执行mysqladmin reload,你能告诉一个正在运行的服务器 6 M8 M0 l/ j# B( |2 J+ y6 w
再次开始使用授权表。)
) x& j$ U6 \0 L& M7 h--skip-name-resolve
7 n# i. S2 z$ `8 q7 z主机名不被解析。所有在授权表的Host的列值必须是IP数字或localhost。
$ h: o3 O7 F/ o, U4 r--skip-networking 1 q# t1 c  z1 z( t' M. u8 {# [
在网络上不允许TCP/IP连接。所有到mysqld的连接必须经由Unix套接字进
; M5 I% t# @4 ~. g* D1 l6 o行。这个选项对使用MIT-pthreads的系统是不合适的,因为MIT-pthreads包不 $ t& y" {8 b8 B# l1 k! ~: l
支持Unix套接字。
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 顶 踩
丧心病狂 该用户已被删除
2
发表于 2003-7-26 16:39:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
其实我也很想买了看的,可是我是版主,不用钱。
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 顶 踩

该用户从未签到

3
发表于 2003-7-26 16:52:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
讲什么啊?
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 顶 踩

该用户从未签到

4
发表于 2003-7-26 20:02:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
看了一屏就晕了。。。
5 d' [/ V( M4 n6 T. V8 m6 h+ U  i汗。。. r) U' P9 s8 X0 W, v+ |; O: ~
水平不够,消化不了。。
+ ~" q' [: U$ u8 C3 L+ i+ O. c9 L不过还是顶一下
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 顶 踩

本版积分规则

关闭

下沙大学生网推荐上一条 /1 下一条

快速回复 返回顶部 返回列表