下沙论坛

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

QQ登录

QQ登录

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

MySql的权限存取系统

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

5 C: _4 {! t, l1 a$ ~# i, Q7 o权限系统做什么 : n) }( W+ e7 V
MySQL权限系统的主要功能是证实连接到一台给定主机的一个用户,
" U6 ?  K3 _& y2 a6 T& X" z并且赋予该用户在一个数据库上select、 insert、update和delete的 * I1 @! ?9 X# R
权限。
4 c! c; h6 T3 L0 I  A* c( x& E1 h
附加的功能包括有一个匿名的用户和对于MySQL特定的功能例如 ; l8 L; {3 O6 C1 J3 ?! r
LOAD DATA INFILE进行授权及管理操作的能力。
& ^4 N$ Q! G6 R) J- W. ^! r
- v' F$ R2 F5 ]) ~6 E; `( IMySQL 用户名和口令 + X$ G# `5 {. c; ]( n. ~
由MySQL使用用户名和口令的方法与Unix或Windows使用的方式有很 4 e- N0 S" l2 u$ u7 K
多不同之处:
% d- G; i3 C  f; y* A; B5 J" Q$ u$ ^5 m: X9 J; ?/ i
MySQL使用于认证目的的用户名,与Unix用户名(登录名字)或 7 O3 C3 ]( y2 L  B& \9 _
Windows用户名无关。缺省地,大多数MySQL客户尝试使用当前Unix用户 3 C; m( @. l/ u8 F3 I
名作为MySQL用户名登录,但是这仅仅为了方便。客户程序允许用-u或-
- W/ O+ H& ^5 u; h-user选项指定一个不同的名字,这意味着无论如何你不能使得一个数据
0 m" D8 P) |9 i' {库更安全,除非所有的MySQL用户名都有口令。任何人可以试图用任何名
5 v9 P( e1 Q( w$ [7 ?' g字连接服务器,而且如果他们指定了没有口令的任何名字,他们将成功。
# s: Q% H- J% C7 p" EMySQL用户名最长可以是16各字符;典型地,Unix用户名限制为8个字符。
- ^/ l9 b8 @" f  NMySQL口令与Unix口令没关系。在你使用登录到一台Unix机器口令和你使
$ d$ q4 D4 {' B7 _" ~; i3 D用在那台机器上存取一个数据库的口令之间没有必要有关联。 8 G& d( @7 t& W' h* }! D
MySQL加密口令使用了一个Unix登录期间所用的不同算法。 + m3 \/ s/ t0 a+ s# J1 A
; a( W! \0 Y- [3 J5 W9 }
与MySQL服务器连接 6 ]2 _+ ?1 F- j# [7 b9 U
当你想要存取一个MySQL服务器时,MySQL客户程序一般要求你指定 2 t  K, t9 |* d' Z
连接参数:你想要联接的主机、你的用户名和你的口令。例如,mysql ( p; A% r0 a* s2 \! V! |
客户可以象这样启动(可选的参数被包括在“[”和“]”之间): % B3 Z4 E0 z: D
$ `( [7 x! r& R& w; j
shell> mysql [-h host_name][-u user_name][-pyour_pass ]
. d. x- _  T8 U  E-h, -u和-p选项的另一种形式是--host=host_name、--user=
( H: }: `% Q4 Cuser_name和--password=your_pass。注意在-p或--password=与跟随它 2 |) U/ S, h# w: M
后面的口令之间没有空格。
2 a, \- P9 t% Z/ \1 ]: Z6 ]
3 \" M9 [4 S2 O1 `: l注意:在命令行上指定一个口令是不安全的!随后在你系统上的任 7 L% o$ j  S- @1 \3 A* B8 f8 E
何用户可以通过打类似这样的命令发现你的口令:ps auxww。 5 Y6 H2 E. A5 l$ ~3 n
' o! t7 ^9 {7 I9 g) z5 W) g5 \5 A
对于命令行没有的联接参数,mysql使用缺省值:
' M/ K9 G3 P. |( i+ R6 y& `, b' m& p# P& r& c
缺省主机名是localhost。
6 w; E9 s  R: a. y% B/ H缺省用户名是你的Unix登录名。 3 x' I" @: w0 `1 n6 I4 |
如果没有-p,则没有提供口令。
# J+ [5 x# H9 l这样, 对一个Unix用户joe,下列命令是等价的:
$ D$ _. @: a: V0 t
$ L' k3 w: Y& G; oshell>mysql -h localhost -u joe
1 ^- R0 A  Q5 Y1 O  i7 @shell>mysql -h localhost
; c% d2 g# V: D( B: d( |  Kshell>mysql -u joe 5 d4 Y  l; _% f: B
shell>mysql / [. Q  Y, E) g( p
9 F" O% q$ k3 ?2 u" b9 |! \
其它MySQL客户程序有同样表现。
$ b/ n# j+ s3 n1 T. S/ J- x1 n
! o% t- M( C/ N* g# V) c在Unix系统上,当你进行一个连接时,你可以指定要使用的不同的缺 ! ?5 v4 d6 T6 A8 Y2 r
省值,这样你不必每次在你调用一个客户程序是在命令行上输入他们。这
# |! k8 o$ y  z, }可以有很多方法做到:
3 |! u, V$ z# [  s+ E1 J9 J( t4 \2 f8 x& q
你能在你的主目录下“.my.cnf”的配置文件的[client]小节里指定 8 V! z! t) @% L0 I: m
连接参数。文件的相关小节看上去可能像这样:
& V* Q3 ]5 h% u( O# ]+ B% g- Q[client] ) X+ w2 o, Q# `* `9 D2 g" x* ?) Z6 R2 S; Y
host=host_name
8 M- W9 }( X5 K: puser=user_name & Z, E$ t: F$ y1 h4 E
password=your_pass
) J  R& f: k0 u( f8 t+ p7 q! h$ s: c2 F
你可以用环境变量指定连接参数。主机可用MYSQL_HOST指定,MySQL & D8 B. F8 s; f. b
用户名字可用USER指定(仅对 Windows),口令可用MYSQL_PWD指定(但是
; k3 j& m/ R' T这不安全) 。
( p: I) ^! H7 r" V+ A* A3 k如果连接参数以多种方法被指定,在命令行上被指定的值优先于在配 ; C1 X% |8 ^, s+ H1 k8 Y0 L6 F7 y
置文件和环境变量中指定的值,而在配置文件指定的值优先于在环境变量
, Q& x" g2 w! E* }+ M指定的值。 - X* N0 S, n( ?- }; \" \, D) X5 H$ C

7 I1 [. c% S$ y+ j% a使你的口令安全
! u  r1 {4 h# b/ b/ F2 J+ [% `以一种暴露的可被其他用户发现的方式指定你的口令是不妥当的。 * l8 W7 S/ b2 ?
当你运行客户程序时,你可以使用下列方法指定你的口令,还有每个方法 1 q/ c# k* V, J; x) R$ F
的风险评估:
  Y! Q$ C0 h8 F3 L: R/ o
& p  i' H' _+ M) |* L使用一个在命令行上-pyour_pass或--password=your_pass的选项。
( x8 X8 e* ^" T这很方便但是不安全,因为你的口令对系统状态程序(例如ps)变得可见,
+ s( o7 o$ i- E% r- ~5 A它可以被其他的用户调用来显示命令行。(一般MySQL客户在他们的初始化
" H8 }7 C! M  ~0 z# R3 {; E顺序期间用零覆盖命令行参数,但是仍然有一个短暂间隔时间内参数值可
1 a! K' [% N& g0 c见的。)
3 q7 @. n2 ?7 B5 [  ~/ G使用一个-p或--password选项(没有指定your_pass值)。在这种情况
, C4 @, p3 T& _* w4 S6 [下,客户程序请求来自终端的口令: & V+ _: J( W6 {

, n0 x8 z* R/ v" s$ g7 D, fshell>mysql - u user_name - p 2 U4 j& |) `. A; I' R9 [$ M/ S& f
Enter password: ******** , M% V" t3 ?7 j3 C

) }, j: _3 ~6 r( Y( X- C) ?客户回应“*”字符到作为输入你的口令的终端使得旁观者不能看见 ) u9 }$ I" \% C1 C
它。因为它对其他用户不可见,与在命令行上指定它相比,这样进入你
+ U0 Y" R  r  i" B5 g% |的口令更安全。然而,这个输入一个口令的方法仅仅为你交互式运行程
2 u1 x6 y' b' A3 D! P# ]序是合适的。如果你想要从非交互式运行的一个脚本调用一个客户,就
0 w9 p9 N$ z# {1 T& m# j没有从终端输入入口令的机会。 0 b. Q1 w8 d( D. K+ k# d

! ]6 W0 ]) O7 C# Z- V8 @在一个配置文件中存储你的口令。例如,你可你的主目录的 # \( U" v0 f3 K" o' a  h4 O
“.my.cnf”文件中的[client]节列出你的口令: . B2 c& R6 b; [$ [: o/ W7 ~
[client] 1 {5 d: m/ H; h; E' \) F
password=your_pass
1 S' a- c3 D7 X5 U  d8 n1 P: x9 _( u" D
如果你在“.my.cnf”里面存储口令,文件应该不是组或世界可读或
2 ]3 y; s; {$ `- l可写的。保证文件的存取模式是400或600。见4.15.4 选项文件。
2 C* f! V3 ?+ P3 S# C9 u9 H  h
你可在MYSQL_PWD环境变量中存储口令,但是这个方法必须想到是极
; S9 Q- O6 h6 a2 }9 S不安全的且应该不使用。ps的某些版本包括显示运行进程的环境的选项; 8 z- L4 C% u) R% t% ^0 v8 i" E
如果你设定MYSQL_PWD,你的口令将对所有人是显而易见的,甚至在没有
( @, p/ P, y  b) I# n! N这样一个版本的ps系统上,假设没有其他方法观察到进程环境是不明智 / x* p" o2 z3 O2 c2 N4 r( U
的。   C, r% o( c8 y
总之,最安全的方法是让客户程序提示口令或在一个适当保护的“
" n/ `8 g1 n! g& Q7 ]" v# I( z! f, x.my.cnf”文件中指定口令。
9 C) E' X0 ?5 ^# u  v; c2 q  |2 S. K& p- n2 y3 z/ O1 h
MySQL提供的权限 5 m+ |/ Q% G$ }' ?  {2 f# c+ S
权限信息用user、db、host、tables_priv和columns_priv表被存储 ) ^4 |( `# i: |/ M
在mysql数据库中(即在名为mysql的数据库中)。在MySQL启动时和在权限 - h) b2 p/ E! }9 x; d
修改何时生效所说的情况时,服务器读入这些数据库表内容。   U- u& o1 d+ ]# Y6 O. r4 w4 T

4 W& y  A( l- Y" `2 G+ g由MySQL提供的权限名称显示在下表,还有在授权表中每个权限的表
/ {  v. L4 x6 ~5 i列名称和每个权限有关的上下文:
& j$ m5 q8 q* J  U0 w2 J0 a8 \; P" e权限 列 上下文 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 在服务器上的文件存取 - m- z$ L* P1 i; y
select、insert、update和delete权限允许你在一个数据库现有的
$ y  K& u  P. p, g) C7 S表上实施操作。 ( Q9 ~+ ?9 k, T5 j: A! k3 m- y& t

: L0 L" m+ l  {! ]SELECT语句只有在他们真正从一个表中检索行是才需要select权限, ' a( P' p! G6 q8 C* P
你可以执行某个SELECT语句,甚至没有任何到服务器上的数据库里的存
5 d1 w7 k% ]0 U: a$ Q" H取任何东西的许可。例如,你可使用mysql客户作为一个简单的计算器:
4 u6 l. N7 k# a; E) T9 v4 ?+ d9 s# K; C
mysql> SELECT 1+1;
6 s# x/ \6 V5 ~) y$ r7 {  Lmysql> SELECT PI()*2;
% E1 I- X8 O: T- R) k, f! h0 K7 e$ p9 ^6 v& w0 F* X! a
index权限允许你创建或抛弃(删除)索引。
9 ?! l" b) q# p" d+ i5 ]; _
) _/ C- }6 J; s; t2 }alter权限允许你使用ALTER TABLE。 $ o* B  m. q5 ]+ G
: s4 g6 I! h; R) a' K. I9 C- c
create和drop权限允许你创建新的数据库和表,或抛弃(删除)现存的 ) p5 x2 N; t: w# K# A6 x
数据库和表。
6 W3 N' [. A( Q7 N* G
3 W. l7 V$ U, y: v! Y7 H注意:如果你将mysql数据库的drop权限授予一个用户,该用户能抛弃
8 B+ O3 w2 z/ J$ z  R  i0 l+ ~存储了MySQL存取权限的数据库! 2 Y  k1 ~+ W9 s& R: S

# s; [# d' E8 U+ L" t1 Zgrant权限允许你把你自己拥有的那些权限授给其他的用户。 ) u) w, q  Z$ u  G  r( m9 S" L* H
8 p0 i* j3 F# K. w4 S  U! Y
file权限给予你用LOAD DATA INFILE和SELECT ... INTO OUTFILE语句
6 v4 D- z. Q; Q0 E# Q$ |读和写服务器上的文件,任何被授予这个权限的用户都能读或写MySQL服务
7 r3 u8 Z$ I8 z% D; j5 c  ]$ w器能读或写的任何文件。 2 |8 B) |8 d; _$ \4 i1 B8 r

: j; b5 |/ A" H其余的权限用于管理性操作,它使用mysqladmin程序实施。下表显示 : l5 H8 o0 l0 _! f% j& N
mysqladmin支配每个管理性权限允许你执行的命令: 8 }* x( j% k. E( R* k% G! \
优惠 权限拥有者允许执行的命令 reload reload, refresh, flush-privileges, flush-hosts, flush-logs, flush-tables shutdown shutdown precess processlist, kill
1 {3 c# V) m7 sreload命令告诉服务器再读入授权表,refresh命令清洗所有表并打开
5 ~' @+ H1 }( T/ I* M4 w和关闭记录文件,flush-privileges是reload的一个同义词,其它flush-*
0 o# U% O, Q4 e4 A3 L! ]命令执行类似refresh的功能,但是范围更有限,并且在某些情况下可能更 4 K0 Z/ ~; T' V, D; p, r
好用。例如,如果你只是想清洗记录文件,flush-logs比refresh是更好的
5 l( [$ }* w* e- P! w& L4 }选择。
' g1 [- ]8 N4 U6 [3 L# P) }) `& F: `* Q5 h! W
shutdown命令关掉服务器。 % r6 }. w5 Q/ w& f
$ v  s  g6 h6 v+ M* _- K  J6 g
processlist命令显示在服务器内执行的线程的信息。kill命令杀死服
: z* ^  Z/ S; [1 v9 e8 Q6 t! R9 \务器线程。你总是能显示或杀死你自己的线程,但是你需要process权限来
/ n+ y( @5 v6 S* T1 M( h显示或杀死其他用户启动的线程。
& O6 f! m+ W+ U/ g9 v" s  P0 b) j# [. ^! |+ h5 `
总的说来,只授予权限给需要他们的那些用户是一个好主意,但是你
  b7 {% e" M- W5 K+ {* g应该在授予某个权限时试验特定的警告:
$ j! t/ x; d* L; _, w
4 b! ^5 H4 |& i5 {4 Zgrant权限允许用户放弃他们的权限给其他用户。2个有不同的权限并
2 R; H4 z2 [; h6 a有grant权限的用户可以合并权限。 5 b$ P0 o& I$ y8 d6 _- {% N
alter权限可以用于通过重新命名表来推翻权限系统。 8 H! c' I; E1 n
file权限可以被滥用在服务器上读取任何世界可读(world-readable, $ k0 @- v  H- b# c/ Y
即任何人可读)的文件到一张数据库表,然后其内容能用SELECT被存取。 , q; ?  D5 E* ?
shutdown权限通过终止服务器可以被滥用完全拒绝为其他用户服务。
: a% p. n1 H  C# _* n, ~$ g- p5 wprecess权限能被用来察看当前执行的查询的普通文本,包括设定或改
% h2 i* V4 X: J* i5 r: S5 D变口令查询。 % t; \% w% ^* B& k7 H, x9 O
在mysql数据库上的权限能被用来改变口令和其他存取权限信息。(口
8 P1 z& ^- Q" q: w( c! \" t令被加密存储,所以一个恶意的用户不能简单地读取他们。然而,有足够 6 a9 }7 [" y  v: {- u# o0 n
的权限,同一个用户能用不同的一个代替一个口令。)
9 E0 n& W0 d: Z- l. y+ X有一些事情你不能用MySQL权限系统做到:
" t% z- v9 x0 o) }
  u4 ]- p- c7 O3 F你不能明显地指定一个给定用户应该被拒绝存取。即,你不能明显地匹
  q1 K. ^# _6 e, D! e4 n配一个用户并且然后拒绝连接。 ' ]6 X7 Z% M8 `8 ?. d4 M! \4 O
你不能指定一个用户有权创建立或抛弃一个数据库中的表,也不能创建 & C: \9 Z* n' b2 A  ^. X
或抛弃数据库本身。 $ g6 h8 A/ V2 N& D" q  d5 ^+ i
权限系统工作原理
- [/ V' B5 E; TMySQL权限系统保证所有的用户可以严格地做他们假定被允许做的事情。
7 L2 a" o( [6 J) G) \5 g0 v6 @当你连接一个MySQL服务器时, 你的身份由你从那连接的主机和你指定的用
, ]: A# y1 C2 @0 G1 L/ y/ R9 i户名来决定,系统根据你的身份和你想做什么来授予权限。
8 J& e/ ?( P% H. y( K9 W. \; t/ n, y
MySQL在认定身份中考虑你的主机名和用户名字,是因为有很小的原因假 # p8 K1 ?" H1 _/ K- g" t- c
定一个给定的用户在因特网上属于同一个人。例如,用户从whitehouse.gov ( t! _) `6 Z% u3 A& c( s
连接的bill不必和从mosoft.com连接bill是同一个人。 MySQL通过允许你区 / w% m2 v5 g: `" }# y9 {
分在不同的主机上碰巧有同样名字用户来处理它:你可以对从whitehouse.gov 1 ~* {5 {' l" _' {/ V4 N* \! M
连接授与bill一个权限集,而为从microsoft.com的连接授予一个不同的权限
$ {  }$ D) \6 [  x# k. p, j( B/ h' m" C集。
( Z# J/ p/ y' T/ F
5 D( }7 V8 Y2 R/ K5 U6 c. S: d; VMySQL存取控制包含2个阶段: - [# C# |* X0 r- y/ a
, d! w. L: u5 }" H
阶段1:服务器检查你是否允许连接。 " B( l/ P, G9 T( J8 c  j
阶段2:假定你能连接,服务器检查你发出的每个请求。看你是否有足够 / j  t+ a  {' f4 b- t5 V
的权限实施它。例如,如果你从数据库中一个表精选(select)行或从数据库抛
4 f; e3 l% \  N弃一个表,服务器确定你对表有select权限或对数据库有drop权限。 " R% }3 p3 }, {4 ~
服务器在存取控制的两个阶段使用在mysql的数据库中的user、db和host
- r: g4 M0 X  k2 J( b5 D& N表,在这些授权表中字段如下: * J4 s0 q* x# D5 A$ \, p
表名称 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
0 @5 b6 j! P( j7 f对存取控制的第二阶段(请求证实),如果请求涉及表,服务器可以另外 " y: c* E: A1 Z: i$ Y
参考tables_priv和columns_priv表。这些表的
& W3 ^9 U1 \- c+ ]- i7 [字段如下:
, \0 N/ ~- ^2 ~表名称 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 ! I% T$ R; n! D, D! M5 Q0 g' T
对存取控制的第二阶段(请求证实),如果请求涉及表,服务器可以另外 6 a, g) t# i# Z
参考tables_priv和columns_priv表。这些表的字段如下: ! ^7 Z$ B. F5 @
字段名 类型 Host CHAR(60) User CHAR(16) Password CHAR(16) Db CHAR(64) (tables_priv和columns_priv表为CHAR(60)) 5 s: r) ?0 {( X3 O6 O
在user、db和host表中, 4 {1 i0 b" O! a, R9 u
所有权限字段被声明为ENUM('N','Y')--每一个都可有值 # h7 X% _0 w, `5 h& D. P
'N'或'Y',并且缺省值是'N'.
3 b! Y5 R2 T9 o在tables_priv和columns_priv表中,权 - \7 B$ X5 X( Q
限字段被声明为SET字段:
# {7 W+ c- Y- g0 |1 T! C表名 字段名 可能的集合成员 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' 7 J- @) s, l7 E+ T
每个授权表包含范围字段和权限字段。
! E+ W7 P: |7 ]: w1 |# v* v, [+ H' G4 O
范围字段决定表中每个条目的范围,即,条目适用的上下文。例如,
3 b6 G, A% ~5 Z7 o; g' P. l一个user表条目的Host和User值为'thomas.loc.gov'和'bob'将被用于 2 {* n! S! e& c7 U
证实来自主机thomas.loc.gov的bob对服务器的连接。同样,一个db表条 * a* ]5 L. V0 l& Y" \! p  a
目的Host、User和Db字段的值是'thomas.loc.gov'、'bob'和'reports'
. z+ F+ _% A% ~( {6 y/ r# N% S将用在bob从主机联接thomas.loc.gov存取reports数据库的时候。 - T9 {' ?1 e- a9 V8 m/ |* Q# F
tables_priv和columns_priv表包含范围字段,指出每个条目适用的表或 - h. i+ L9 Y+ _; _! d- \0 P
表/列的组合。 9 B" N$ {- z9 r! O7 S

0 G6 G% m! w% ^! A对于检查存取的用途,比较Host值是忽略大小写的。User、Password、
/ @; i6 g0 b9 h# p* lDb和Table_name值是区分大小写的。Column_name值在MySQL3.22.12或以
$ X7 w7 B" x- h- U后版本是忽略大小写的。 - e; y: R8 m! H  X( b
, A/ Y' t4 g( p, [: A
权限字段指出由一个表条目授予的权限,即,可实施什么操作。服务
+ y& h/ Q- v* N器组合各种的授权表的信息形成一个用户权限的完整描述。为此使用的规 3 v+ E! F: m0 u7 P# D. L
则在6.8 存取控制, 阶段2:请求证实描述。
2 [1 A  w  J. M9 H" C/ G4 F1 e9 Q+ F% k3 d4 V; P
范围字段是字符串,如下所述;每个字段的缺省值是空字符串:
9 r8 r# O  a! t字段名 类型 Host CHAR(60) User CHAR(16) Password CHAR(16) Db CHAR(64) (tables_priv和columns_priv表为CHAR(60))
9 h5 m6 `* S8 x" w在user、db和host表中,所有权限字段被声明为ENUM('N','Y')--每一
/ p1 H' V' c3 R4 C( }! C, M# t个都可有值'N'或'Y',并且缺省值是'N'. 0 S8 [" ^( D" W
  Q1 v& H0 j! u3 g6 j
在tables_priv和columns_priv表中,权限字段被声明为SET字段: - g2 H: F' {5 W+ a
表名 字段名 可能的集合成员 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'
6 f* L4 S* L2 [9 c7 Q0 m简单地说,服务器使用这样的授权表: , S' {) ~3 X7 d. h' b% w8 R6 h  w

9 v6 g" G  B& Ruser表范围字段决定是否允许或拒绝到来的连接。对于允许的连接, & S! j. t3 E# f8 n& {& R( g' `% ?
权限字段指出用户的全局(超级用户)权限。
+ C4 G3 W; H- z; L2 r/ O- a6 tdb和host表一起使用:
4 l9 Y" `6 ], j6 Z- o$ |8 x: vdb表范围字段决定用户能从哪个主机存取哪个数据库。权限字段决定 1 w- e; X0 Q1 a& ?4 `2 G
允许哪个操作。
  E4 ]# G6 E1 A当你想要一个给定的db条目应用于若干主机时,host表作为db表的扩
) P, g6 y! P: t6 q$ w! A/ n2 z展被使用。例如,如果你想要一个用户能在你的网络从若干主机使用一个 - f9 c/ P, s/ g% z! |
数据库,在用户的db表的Host条目设为空值,然后将那些主机的每一个移
  p. \# C8 v8 m- f" w- F) U入host表。这个机制详细描述在6.8 存取控制, 阶段2:请求证实。
; x; y/ T' e% gtables_priv和columns_priv表类似于db表,但是更精致:他们在表 - I% e2 z# J8 b: i
和列级应用而非在数据库级。 7 w9 s: k1 w. \+ r0 K3 s7 ?3 t
注意管理权限(reload, shutdown, 等等)仅在user表中被指定。这是
% L! {- Z5 F- f- y7 i: D  S因为管理性操作是服务器本身的操作并且不是特定数据库,因此没有理由 ; E, s* L& B+ H; n9 ^# D) x
在其他授权表中列出这样的权限。事实上,只需要请教user表来决定你是 . X) ~7 ?8 C$ p9 u4 L# a$ e
否执行一个管理操作。
$ w4 ^, U9 @7 w+ W" I8 }; u
" F% D  @1 h: ^file权限也仅在user表中指定。它不是管理性权限,但你读或谢在服 , l0 h3 f8 }6 ]2 Z( C7 |; X
务器主机上的文件的的能力独立于你正在存取的数据库。 ) l7 Q1 Z* H, \! f5 C5 m7 R. G

7 r: P2 S; o5 h/ {4 l/ c- q当mysqld服务器启动时,读取一次授权表内容。 3 @# _" u/ N+ L5 R( K& \

5 g. W- e: }! k0 L6 n当你修改授权表的内容时,确保你按你想要的方式更改权限设置是一 ; j! [! U- }/ a- k
个好主意。 / |. ]6 j) u" Q% a' Z5 \
( r, v% U* y7 [/ h  q4 G& E& o9 H
一个有用的诊断工具是mysqlaccess脚本,由Carlier Yves 提供给
4 y, g' t. E5 Q/ S$ p$ DMySQL分发。使用--help选项调用mysqlaccess查明它怎样工作。注意: - ~, \# y( s2 c
mysqlaccess仅用user、db和host表仅检查存取。它不检查表或列级权限。 $ \3 q: L9 [! J  E3 T/ I9 q9 S4 t
! Y9 y8 r( K4 p1 L
存取控制, 阶段1:连接证实 7 U& O# g5 a  e- i) M3 |
当你试图联接一个MySQL服务器时,服务器基于你的身份和你是否能
. Z2 \! k! Q7 ~9 i4 v, h$ B, `通过供应正确的口令验证身份来接受或拒绝连接。如果不是,服务器完全 $ ]; [2 [5 ]) Q
具结你的存取,否则,服务器接受连接,然后进入阶段2并且等待请求。
8 M4 o+ y4 p6 w2 m# N9 z& w
) u. b5 ~4 Y0 D9 j你的身份基于2个信息:
; y: X$ f1 `$ F
2 Q/ |( ^& y0 G: X: O  m4 Y8 G你从那个主机连接
3 @1 ^3 g& A; o. t" u1 U. L你的MySQL用户名 ) g" o: s# g, y7 U0 _9 R/ S
身份检查使用3个user表(Host, User和Password)范围字段执行。服 0 a; e# c4 [9 ^1 d
务器只有在一个user表条目匹配你的主机名和用户名并且你提供了正确的 4 a3 a: v2 i$ Q# M6 ]8 d" R5 P
口令时才接受连接。
! |/ w/ R- f( s0 H$ C4 Y4 O$ \. k+ }8 L7 `
在user表范围字段可以如下被指定: # r2 q" R( ?' P, h2 T" a

- m, p: o5 j- b5 E1 n一个Host值可以是主机名或一个IP数字,或'localhost'指出本地主机。
8 P+ b" j3 Q$ |5 ?8 i% W* z你可以在Host字段里使用通配符字符“%”和“_”。 7 G& l. n5 V! G+ |. @# C
一个Host值'%'匹配任何主机名,一个空白Host值等价于'%'。注意这些
' y+ z* [* K! w: X# ]/ E值匹配能创建一个连接到你的服务器的任何主机! 1 ]7 i) s; }6 ~, W. W4 w. j: l' ]
通配符字符在User字段中不允许,但是你能指定空白的值,它匹配任何 & s$ o7 v" T0 X
名字。如果user表匹配到来的连接的条目有一个空白的用户名,用户被认为 1 ?( w3 X* m1 S+ o: q/ M
是匿名用户(没有名字的用户),而非客户实际指定的名字。这意味着一个空 ( Q& ?5 G; j' z4 q% X* {
白的用户名被用于在连接期间的进一步的存取检查(即,在阶段2期间)。
) d" {( h' }0 O/ r1 e% V% ~Password字段可以是空白的。这不意味着匹配任何口令,它意味着用户
$ A* M* h- I* S6 M" ~* p必须不指定一个口令进行连接。
6 J) @2 e; I" j7 L/ H! e非空白Password值代表加密的口令。 MySQL不以任何人可以看的纯文本 7 e4 U! N' O9 d
格式存储口令,相反,正在试图联接的一个用户提供的口令被加密(使用
' p2 d# u1 A: ]PASSWORD()函数),并且与存储了user表中的已经加密的版本比较。如果他
6 O' r4 l5 B/ \们匹配,口令是正确的。
/ I: J0 C, g" |9 a. O& m6 N( S% L) G4 D( l0 W+ u6 O
下面的例子显示出各种user表中Host和User条目的值的组合如何应用于到来 5 f- u/ Y/ f6 U  v: q
的连接:
/ x7 e# |# p1 n! v$ i  M0 q5 v9 n
Host 值 User 值 被条目匹配的连接
# t* d! S) i! h, Q'thomas.loc.gov' 'fred' fred, 从thomas.loc.gov 连接 9 Y% t9 n$ b; E/ R, R) o
'thomas.loc.gov' '' 任何用户, 从thomas.loc.gov连接 2 ?; w% P$ |' A  b/ Q8 h
'%' 'fred' fred, 从任何主机连接
2 B' q! `* T/ L$ _0 }' l'%' '' 任何用户, 从任何主机连接
+ Z* i3 H, A) V'%.loc.gov' 'fred' fred, 从在loc.gov域的任何主机连接
- @! s. ~+ m1 p4 f! c  W. j4 ?'x.y.%' 'fred' fred, 从x.y.net、x.y.com,x.y.edu等联接。(这或许
' U( j1 N4 w) b. D/ S无用)
: s  _) Z! T8 U! L' Y'144.155.166.177' 'fred' fred, 从有144.155.166.177 IP 地址的主 0 K! G! g9 k1 s$ Y4 A
机连接
3 m2 a2 h/ g) z+ L) m1 w'144.155.166.%' 'fred' fred, 从144.155.166 C类子网的任何主机连 6 X. g0 d) [0 O8 _

- K; b: [- j* F
( x+ _% }& a& {+ g5 q既然你能在Host字段使用IP通配符值(例如,'144.155.166.%'匹配在一个子
" y0 g1 Q( {- }6 J2 y. L网上的每台主机),有可能某人可能企图探究这种能力,通过命名一台主机 ! O% z1 A2 C4 V+ x
为144.155.166.somewhere.com。为了阻止这样的企图,MySQL不允许匹配以
& S1 V" S! f& M. R数字和一个点起始的主机名,这样,如果你用一个命名为类似1.2.foo.com的
/ I7 H& o7 M; |% t主机,它的名字决不会匹配授权表中Host列。只有一个IP数字能匹配IP通配
* Q) z- @0 y5 f" G$ U符值。
+ B# @$ Q' _; r1 Z2 l( R6 T/ ^5 h! z# S/ w( ?& P
一个到来的连接可以被在user表中的超过一个条目匹配。例如,一个由 ! z8 U* }2 U1 B7 X0 J
fred从thomas.loc.gov的连接匹配多个条目如上所述。如果超过一个匹配, 1 g! j; M/ }4 f. Z9 ~
服务器怎么选择使用哪个条目呢?服务器在启动时读入user表后通过排序来 7 b, J! E. ?+ [. T' V7 u! @
解决这个问题,然后当一个用户试图连接时,以排序的顺序浏览条目,第一 7 H0 L* W$ c2 I3 _
个匹配的条目被使用。
" b) U+ A$ j2 d/ I) `# s
! d7 B1 k& z5 Tuser表排序工作如下,假定user表看起来像这样: " g* d/ t; O# \) l' h

" b2 l% p: j/ L% q1 }* k' E; e, A( r5 e: [) Y
+-----------+----------+- $ u6 w9 h1 u; T; M- ~/ l/ Q, X
│ Host │ User │ ... & {( O3 Y" @& `: {- Y4 D; f, [
+-----------+----------+-
, v: J# q' u  v7 r: [. L│ % │ root │ ...
* y/ c0 i  D" k4 E: u│ % │ jeffrey │ ...
$ z/ Y% ?4 T; ?- ]" j: E. ?0 k5 y│ localhost │ root │ ...
: w. U- s  {/ h4 w) K│ localhost │ │ ... , q% |1 q! ?4 z* r8 O! e: ?7 l
+-----------+----------+- / `  N  D( x  u- {
7 ]8 z+ n( H- h- ?
当服务器在表中读取时,它以最特定的Host值为先的次序排列('%'在
  p! e; \1 u! k9 r. pHost列里意味着“任何主机”并且是最不特定的)。有相同Host值的条目以
2 x. E8 N. d; `+ K' U) w最特定的User值为先的次序排列(一个空白User值意味着“任何用户”并且
. \$ f4 x3 L0 H1 V, h是最不特定的)。最终排序的user表看起来像这样: & G# S+ l4 s- d/ p! a% u( E

6 g, h# @0 \6 w. _7 G7 ^
$ g- G' O0 B: x# [& D$ h1 h+-----------+----------+-
) P1 a. [$ L8 l$ I. }: Q) \" L+ V│ Host │ User │ ... 3 m4 I: H  `* \$ n5 o# \
+-----------+----------+-
0 `- o, `0 [& ~) b│ localhost │ root │ ...
. e, a/ ~3 q% u6 v8 X│ localhost │ │ ...
  m9 q5 P' d3 h6 Q1 ^& R│ % │ jeffrey │ ... 7 _) s5 O+ u8 k& X- K8 p. f
│ % │ root │ ...
$ w) F! y. c" \7 Y+-----------+----------+-
  I: b: Z1 @. X1 Q: Z) V; l2 a( B$ H7 o8 N$ N4 H2 m1 i- U- j
当一个连接被尝试时,服务器浏览排序的条目并使用找到的第一个匹 5 o5 u$ p" e# o
配。对于由jeffrey从localhost的一个连接,在Host列的'localhost'条目 3 ~+ i' W# o! i% j0 f/ F% b0 I
首先匹配。那些有空白用户名的条目匹配连接的主机名和用户名。('%'/ 7 M( N. X6 h/ [( l
'jeffrey'条目也将匹配,但是它不是在表中的第一匹配。)
! t. @, }' l+ \/ i
/ c8 Y) \5 x: u7 k$ I这是另外一个例子。假定user桌子看起来像这样:
: N0 p, y8 Y) B$ _! y0 Y: w4 y2 M8 B4 \' a$ _+ A: u  g+ W& r

% U% O1 l7 G: X) W+----------------+----------+-
+ e9 F% E4 R" W5 u1 ?. F│ Host │ User │ ... , P2 J9 A2 s: u3 [3 m9 K
+----------------+----------+-
. L7 G4 p( j" x! C1 V, s│ % │ jeffrey │ ...
1 {* r# G: W- j│ thomas.loc.gov │ │ ...
* v0 B0 x9 i) m* d+----------------+----------+- ) P4 X! a( j8 g2 P3 {6 q
. N5 X5 z4 M* U
排序后的表看起来像这样:
2 E0 x  @- a$ q$ Z. ^
* ]4 F6 t! c' N6 V- Q6 @! d" @$ }& X) M
9 R- j) r4 C0 K1 x. K+----------------+----------+- - A8 v; J; Y3 I  L/ p% o
│ Host │ User │ ...
. x) v, M; f( v  K+----------------+----------+-
" `6 F2 i4 f& W: m( \% f9 w* L: d│ thomas.loc.gov │ │ ...
) k. I& z0 P4 g3 }│ % │ jeffrey │ ... 3 m( ]! S# E% `8 y
+----------------+----------+- ( h! j- U4 o* c
- Q. g- e2 A5 u
一个由jeffrey从thomas.loc.gov的连接被第一个条目匹配,而一个由
& K' W! U# |: C7 f& b& E: \0 [jeffrey从whitehouse.gov的连接被第二个匹配。
! ?# b" p0 u3 v" C' p7 }) s* p8 T
普遍的误解是认为,对一个给定的用户名,当服务器试图对连接寻找
, J+ \! O7 I, n; G+ \匹配时,明确命名那个用户的所有条目将首先被使用。这明显不是事实。
  m' t; r( c9 Q1 E0 n先前的例子说明了这点,在那里一个由jeffrey从thomas.loc.gov的连接没
% E2 s( W/ E2 V1 a/ D* T' ]被包含'jeffrey'作为User字段值的条目匹配,但是由没有用户名的题目匹
- O" `- R8 Y* r0 y) f$ j& Y; |配!
  q$ H( I' V3 C" B3 ?) o$ G
3 i0 E7 G' y; l5 j如果你有服务器连接的问题,打印出user表并且手工排序它看看第一个
$ r' ~9 b" W; |0 t4 z: _. H0 G匹配在哪儿进行。 ! e6 ~) }0 f. m0 o# F0 @
/ A5 v& I, i7 i: i) r1 a
存取控制,阶段2:请求证实 0 D7 a' K% ?# j: B2 W; B. Y' D8 `9 W
一旦你建立了一个连接,服务器进入阶段2。对在此连接上进来的每个
* O8 F) X* g4 A  u9 G* K3 @6 V7 }请求,服务器检查你是否有足够的权限来执行它,它基于你希望执行的操作
: }7 B2 W( r3 K! u0 _0 R- j类型。这正是在授权表中的权限字段发挥作用的地方。这些权限可以来子 9 y. b' P+ `; c% p. e
user、db、host、tables_priv或columns_priv表的任何一个。授权表用
. C; S/ ?, }2 `- i1 p" ?* ~GRANT和REVOKE命令操作。见7.26 GRANT和REVOKE 句法。(你可以发觉参 ) U2 x4 G( G  E1 Z) F5 o
考6.6 权限系统怎样工作很有帮助,它列出了在每个权限表中呈现的字段。) ! P. x2 W$ X# w2 l7 ~- g9 F% l- \$ _

( p7 W+ E! n3 B6 Kuser表在一个全局基础上授予赋予你的权限,该权限不管当前的数据库
5 U+ C6 [1 b, @" V& e是什么均适用。例如,如果user表授予你delete权限, 你可以删除在服务器 ! U3 K7 p4 v! }) y* S; F+ |( C
主机上从任何数据库删除行!换句话说,user表权限是超级用户权限。只把
& H# I3 c; X1 o4 juser表的权限授予超级用户如服务器或数据库主管是明智的。对其他用户, ) l- f6 u4 B# m. J1 c! D
你应该把在user表中的权限设成'N'并且仅在一个特定数据库的基础上授权, 8 w0 f% a2 g" p, \: j' R9 J
使用db和host表。 . [8 \7 P2 |+ \* o4 P

4 w2 w- R1 D2 h! Q$ Pdb和host表授予数据库特定的权限。在范围字段的值可以如下被指定: $ k1 n  F1 o+ {6 Z9 o- I$ g

9 h0 @1 j$ B# [( i, [9 A* h通配符字符“%”和“_”可被用于两个表的Host和Db字段。
1 j# O) K* H- x. B( A" h5 O在db表的'%'Host值意味着“任何主机”,在db表中一个空白Host值意味 ' p" h* @. R2 b+ e2 b4 v1 Q7 u7 y
着“对进一步的信息咨询host表”。 & ^2 O, N0 J+ E- M
在host表的一个'%'或空白Host值意味着“任何主机”。 7 m, b8 m' C1 e
在两个表中的一个'%'或空白Db值意味着“任何数据库”。
7 E6 J* ^; |" C9 p% D8 A4 }在两个表中的一个空白User值匹配匿名用户。
6 Y* K; t! r' B! X% rdb和host表在服务器启动时被读取和排序(同时它读user表)。db表在Host
& ]7 C2 [: x6 a. \、Db和User范围字段上排序,并且host表在Host和Db范围字段上排序。对于
; C. x) l2 l) j$ n! E. V  Guser表,排序首先放置最特定的值然后最后最不特定的值,并且当服务器寻找 + g, g5 l1 Q# s' E/ I1 b
匹配入条目时,它使用它找到的第一个匹配。 7 [, G7 t8 A+ ~8 E( W6 y
$ {, n& u3 g" M/ D' ?
tables_priv和columns_priv表授予表和列特定的权限。在范围字段的值可
8 Q5 C# w+ W! v% a2 Z, ~, \以如下被指定: ) e2 r% c, Y" n" L
, ^6 }, e% }6 H5 C" a$ A
通配符“%”和“_”可用在使用在两个表的Host字段。 5 h( E9 k' ^3 e3 E
在两个表中的一个'%'或空白Host意味着“任何主机”。 % L) o- f, s* C- E3 w
在两个表中的Db、Table_name和Column_name字段不能包含通配符或空白。 - `+ ?7 A+ i5 t5 W  S
tables_priv和columns_priv表在Host、Db和User字段上被排序。这类似于   p2 g/ Q( u/ m+ v5 b& @# o+ N
db表的排序,尽管因为只有Host字段可以包含通配符,但排序更简单。   `: i; t! m  ~. `1 Z/ J

+ U* c* X8 L& d* r+ x( @& o请求证实进程在下面描述。(如果你熟悉存取检查的源代码,你会注意到这 ; }9 O* C/ ]6 Q" \% A# G
里的描述与在代码使用的算法略有不同。描述等价于代码实际做的东西;它只是 : H" J* }5 s3 Z
不同于使解释更简单。)
: G, C9 X) N- L9 u5 @- t1 Y* z# }+ w% ?  x1 M; H
对管理请求(shutdown、reload等等),服务器仅检查user表条目,因为那是 2 E; X5 p3 c: n/ n3 ~( g; ]
唯一指定管理权限的表。如果条目许可请求的操作,存取被授权了,否则拒绝。 3 T7 M6 }2 v+ A/ b4 H( Z
例如,如果你想要执行mysqladmin shutdown,但是你的user表条目没有为你授 / A0 f" j/ _5 G9 @" S1 M6 M- E
予shutdown权限,存取甚至不用检查db或host表就被拒绝。(因为他们不包含
, `- }9 m/ p$ C) ?Shutdown_priv行列,没有这样做的必要。) ( e. D5 V+ V/ Z3 Z( D

! J* x) M' Z0 P2 M3 S. @对数据库有关的请求(insert、update等等),服务器首先通过查找user表
6 r6 Y: V; }; R* N! E% j0 z* f7 |条目来检查用户的全局(超级用户)权限。如果条目允许请求的操作,存取被授 # c8 c: o0 {( j$ [9 B- s
权。如果在user表中全局权限不够,服务器通过检查db和host表确定特定的用
* V* ]9 |2 k# j" y& p* X户数据库权限: / A+ v; O# O* D

; k9 l! }+ U7 w2 X; R服务器在db表的Host、Db和User字段上查找一个匹配。 Host和User对应连 & Y2 O) R: U, P+ p. C" `
接用户的主机名和MySQL用户名。Db字段对应用户想要存取的数据库。如果没有 7 x" O; m; H  n) i! q* {
Host和User的条目,存取被拒绝。 * |* ]' O- G' `+ g
如果db表中的条目有一个匹配而且它的Host字段不是空白的,该条目定义用 ( `  Z6 [2 |' H9 @7 o' i7 \& v
户的数据库特定的权限。 1 m2 S* [% s  w- N. h6 i1 K, z. `! Z
如果匹配的db表的条目的Host字段是空白的,它表示host表列举主机应该被
2 j' m1 E. I( _/ e1 r$ ?. W) ]允许存取数据库的主机。在这种情况下,在host表中作进一步查找以发现Host和
1 d2 ^$ s) C4 S' }; BDb字段上的匹配。如果没有host表条目匹配,存取被拒绝。如果有匹配,用户数
2 }3 z! ?+ `. y; V/ R据库特定的权限以在db和host表的条目的权限,即在两个条目都是'Y'的权限的交 4 q7 P' v0 B; L  X' g- T
集(而不是并集!)计算。(这样你可以授予在db表条目中的一般权限,然后用host 9 f2 X* x9 n2 |
表条目按一个主机一个主机为基础地有选择地限制它们。) ; W# a7 K8 ?; x% k( x% E' P: Y
在确定了由db和host表条目授予的数据库特定的权限后,服务器把他们加到 & ]0 q8 P+ ~5 H& s& L. X9 d2 M/ x5 l
由user表授予的全局权限中。如果结果允许请求的操作,存取被授权。否则,服 + J7 t% X  _* r, \) Z7 C
务器检查在tables_priv和columns_priv表中的用户的表和列权限并把它们加到 6 N3 @: A+ |" U7 J6 [# g! s2 g2 M
用户权限中。基于此结果允许或拒绝存取。
* |& w! N  d7 B0 g8 L4 |+ `" I' i# M7 t8 N2 a) G) w
用布尔术语表示,前面关于一个用户权限如何计算的描述可以这样总结:   R) G4 |0 n# P  v/ U
8 P- r0 b9 F! N( n7 X$ ^
global privileges
# M6 O# W8 m6 Y7 N0 _OR (database privileges AND host privileges) - h8 f$ {5 d! Y6 _. ]
OR table privileges
2 O" G% }. F. f, mOR column privileges
' F; e/ ]% K3 ^2 y& C. R7 f9 B$ J6 I
它可能不明显,为什么呢,如果全局user条目的权限最初发现对请求的操作不
* F; {" e" T% ]9 V! A2 u5 T- F够,服务器以后把这些权限加到数据库、表和列的特定权限。原因是一个请求可能
5 Q0 n. p' ]) u1 g. f! v要求超过一种类型的权限。例如,如果你执行一个INSERT ... SELECT语句,你就都 $ L$ ~4 w/ G" V, Z1 }
要insert和select权限。你的权限必须如此以便user表条目授予一个权限而db表条 1 {+ j1 t( w1 W7 I5 j% p' v! M
目授予另一个。在这种情况下,你有必要的权限执行请求,但是服务器不能自己把
3 h" ]2 I5 i7 y/ U7 _) H; Q+ ^两个表区别开来;两个条目授予的权限必须组合起来。   `& W6 ~3 A. n8 H
7 @( [0 E0 F+ T
host表能被用来维护一个“安全”服务器列表。在TcX,host表包含一个在本
) a8 x- S! C* B4 Q5 Z$ c9 v地的网络上所有的机器的表,这些被授予所有的权限。 ; y: W- K5 c+ {9 |5 Q0 I

: Z4 t( D8 j: I/ _( G* w1 T0 i你也可以使用host表指定不安全的主机。假定你有一台机器public.your.
; a" @: L$ Y/ {! m, A  q: ldomain,它位于你不认为是安全的一个公共区域,你可以用下列的host表条目子允 3 R. k8 H( v  [% d  d' w5 w" a
许除了那台机器外的网络上所有主机的存取: 8 ]- g0 k+ F, V# j% ?1 K& ]4 `

& J( G! Q! h% d$ }! f
& x( e" k  [2 x  C+--------------------+----+-
  E( X: p  b2 r. C# ~│ Host │ Db │ ... - W' T% x; |1 a+ O: q
+--------------------+----+- % B: V5 J! g0 Y$ d& R" g
│ public.your.domain │ % │ ... (所有权限设为 'N') ' }/ J% a' V. k$ C, `
│ %.your.domain │ % │ ... (所有权限设为 'Y') : h3 n% D+ l" n6 X! n
+--------------------+----+-
) _' q" c: ~/ W* f% P" A) u3 Y
( u8 g& O# P# p当然,你应该总是测试你在授权表中的条目(例如,使用mysqlaccess)让你确保
& g1 @5 h" Y4 k6 H4 i你的存取权限实际上以你认为的方式被设置。
2 O8 Z. o7 A* c
! z! u6 `/ D- q; J1 ^权限更改何时生效
. Y! W! |( w* d0 c当mysqld启动时,所有的授权表内容被读进存储器并且从那点生效。
: G& Z- W8 k$ ^; o$ H$ K+ D( F, B: S* N& J9 V6 X' f6 t
用GRANT、REVOKE或SET PASSWORD对授权表施行的修改会立即被服务器注意到。
4 K. f/ U8 U6 i  X& z, i
  y* l5 W- }- o. D如果你手工地修改授权表(使用INSERT、UPDATE等等),你应该执行一个FLUSH 8 V1 @) Z/ q0 e0 d3 @' x# v6 h; C
PRIVILEGES语句或运行mysqladmin flush-privileges告诉服务器再装载授权表,否 , r1 F% d# A6 ?
则你的改变将不生效,除非你重启服务器。 0 f- W& o0 y5 g

/ q4 I; ^$ S6 G当服务器注意到授权表被改变了时,现存的客户连接有如下影响: ; W6 w, Q) v6 [( Y" U

( u+ w7 \" M6 |" F, P" s. }表和列权限在客户的下一次请求时生效。
- m4 u6 N) d- t" [. m数据库权限改变在下一个USE db_name命令生效。
; u9 f5 ~* ~0 G全局权限的改变和口令改变在下一次客户连接时生效。
$ B0 \5 d8 {3 K" R. R: U* T  y- ?2 f' s) [4 ]7 x
建立初始的MySQL权限
# q$ t+ @" `4 T! B6 u在安装MySQL后,你通过运行scripts/mysql_install_db安装初始的存取权限。 ! y: J( X* u6 I1 L
scripts/mysql_install_db脚本启动mysqld服务器,然后初始化授权表,包含下列 4 a" e* B) G, a8 l3 K) }; b$ Q  l# @
权限集合:
4 D) l! H; f: j/ B4 K
& H! ]) o* m7 Y: b4 dMySQL root用户作为可做任何事情的一个超级用户被创造。连接必须由本地主 0 ?2 p8 z, Q" |
机发出。注意:出世的root口令是空的,因此任何人能以root而没有一个口令进行 8 y6 h2 |7 \+ M1 ^- }9 f
连接并且被授予所有权限。 1 S: \) L% j% @+ _" ]  V- Z
一个匿名用户被创造,他可对有一个'test'或以'test_'开始的名字的数据库 * J  ]% _! _# g# L% @% H$ v
做任何时期事情,连接必须由本地主机发出。这意味着任何本地用户能连接并且视
2 T/ n, j% X. a* A6 k为匿名用户。 7 X) T/ L* M: v! `
其他权限被拒绝。例如,一般用户不能使用mysqladmin shutdown或
% Y8 _5 p) ~; @" t7 N* P; u+ emysqladmin processlist。 ' g% a1 L, K* ], {6 k2 B
注意:对Win32的初始权限是不同的。
# C5 t( G" N0 W7 N" X" h
) P# c, X* |$ c9 d( Y: `既然你的安装初始时广开大门,你首先应该做的事情之一是为MySQL root用户 4 w- Y9 P# M$ \+ @1 m; f
指定一个口令。你可以做如下(注意,你使用PASSWORD()函数指定口令):
6 |$ |5 v! l. x- O( l2 T% }5 R" M8 r4 e) n
shell> mysql -u root mysql
' u, _. T# p; c5 {. J7 Q9 tmysql> UPDATE user SET Password=PASSWORD('new_password')
4 ~) k$ P* R8 i+ J1 b. Q1 aWHERE user='root';
: w3 s1 {6 K/ V! `; S$ ymysql> FLUSH PRIVILEGES;
# c0 i: K) g( c" i+ D$ q! b1 _9 M* _8 M% W  p
在MySQL 3.22和以上版本中,你可以使用SET PASSWORD语句: 6 O4 H" A! q/ f0 U; V' @4 H' j/ N

% q: B4 M3 _5 u% _0 {shell> mysql -u root mysql ; H, K% t, L) r4 U' z- ^
mysql> SET PASSWORD FOR root=PASSWORD('new_password'); & P) V& @3 u7 `
: n. [( s7 r8 A7 D% `2 F3 A
设置口令的另一种方法是使用mysqladmin命令: ! g1 I: t+ S9 Q* U) \

8 Y) W. x8 P0 R0 R) z1 t" pshell> mysqladmin -u root password new_password & ^- v" l  q: K" W& w8 t5 [! T6 t

" p0 J' O/ M3 d. n注意:如果你使用第一种方法在user表里直接更新口令,你必须告诉服务器
$ f- }2 @& z" L再次读入授权表(用FLUSH PRIVILEGES),因为否则改变将不被注意到。
" g, g6 I6 X! v' V0 K( T& T2 y  b1 l; _8 s# W* r- O! u
一旦root口令被设置,此后当你作为root与服务器连接时,你必须供应那个 / F1 k2 N+ S! w/ h: ~: a' E( D- K
口令。 . K4 [  n- w* V% O' X1 h; [9 d& f

* a5 W, L1 ~9 v8 V4 i你可能希望让root口令为空白以便当你施行附加的安装时,你不需要指定它
9 Z: S) s# D. W4 d2 U! D8 t或测试,但是保证在任何真实的生产工作中使用你的安装之前,设置它。   U9 s4 w' t6 X
- b! j: ?7 K3 N' X  w* W3 B
看看scripts/mysql_install_db脚本,看它如何安装缺省的权限。你可用它 3 K4 U# x" h- H+ t! F- @+ }" o
作为一个研究如何增加其他用户的基础。
8 h8 C1 f1 x  ~5 B
- l( B- x8 [: v, J) ^$ U4 L$ f如果你想要初始的权限不同于上面描述的那些,在你运行mysql_install_db
( y) Q3 m  V/ G之前,你可以修改它。 " I- D) @2 G  _) j4 J- F5 L7 P

' \$ V+ ?' \) H1 F! b为了完全重建权限表,删除在包含mysql数据库的目录下所有“*.frm”,
( L1 c1 f7 Q3 J$ r“*.MYI”和“*.MYD”文件。(这是在数据库目录下面命名为“mysql”的目录, ( x8 F; ^9 U! q
当你运行mysqld --help时,它被列出。)然后运行mysql_install_db脚本,可能
" ?9 v$ v% y( H$ ^$ c* Y在首先编辑它拥有你想要的权限之后。
1 @( S# z0 Z0 s- g( L! j- v' a' u4 S/ |$ R0 }8 z, c4 |3 X$ Z
注意:对于比MySQL 3.22.10旧的版本,你不应该删除“*.frm”文件。如果
/ |" @! g) G% @! V$ ~你偶然做了,你应该在运行mysql_install_db之前你的MySQL分发中拷回它们。
: i" ?/ W2 U9 u2 \' {3 J& t2 H
2 Y% |0 a, O4 I' L' G2 ]+ _向MySQL增加新用户权限 + I. D. L0 W0 b' H1 {
你可以有2个不同的方法增加用户:通过使用GRANT语句或通过直接操作MySQL授
  W+ X( p2 Q# ]3 V% u权表。比较好的方法是使用GRANT语句,因为他们是更简明并且好像错误少些。
* E5 I5 _) z, C$ V+ K
( {* Z9 `9 E+ S4 \下面的例子显示出如何使用mysql客户安装新用户。这些例子假定权限根据以前 0 F2 P& u. [4 S( F3 ^3 A
的章节描述的缺省被安装。这意味着为了改变,你必须在mysqld正在运行同一台 - ?1 n! e* B/ m' F8 L- R0 T- _
机器上,你必须作为MySQL root用户连接,并且root用户必须对mysql数据库有
( |" E# @0 D/ @! Sinsert权限和reload管理权限。另外,如果你改变了root用户口令,你必须如下 6 w# T( w. ]1 I  T; x8 Y9 D. p
的mysql命令指定它。 , h' l  T8 H8 [% p

8 n, K) f# U' A9 K" j你可以通过发出GRANT语句增加新用户:
0 Z0 [3 P9 o. c% r; }9 J/ X/ u: U) S9 I: r, Q1 S
shell> mysql --user=root mysql 4 E5 W2 l: O. \! t+ g6 h; G/ E# g
mysql> GRANT ALL PRIVILEGES ON *.* TO monty@localhost 3 q8 _1 D0 k9 S2 t( }; S+ _
IDENTIFIED BY 'something' WITH GRANT OPTION;
" x0 k# Q1 s& \% M% E5 G1 Umysql> GRANT ALL PRIVILEGES ON *.* TO monty@"%" 9 f4 m$ O4 Q4 O% _. z% N  t
IDENTIFIED BY 'something' WITH GRANT OPTION;
! C" o1 h: j1 A* V1 I; I& V5 s3 Amysql> GRANT RELOAD,PROCESS ON *.* TO admin@localhost; ! @3 a4 |' Z* F. [' G
mysql> GRANT USAGE ON *.* TO dummy@localhost;
& V& q' C% M+ x" X% p
  r# D; S+ A" T这些GRANT语句安装3个新用户:
! W! a3 w* U- u7 }" V
0 w% I' @6 n& \8 Amonty * x" b+ R2 x, M( J
可以从任何地方连接服务器的一个完全的超级用户,但是必须使用一个 : `9 i( w6 Q( `+ v
口令('something'做这个。注意,我们必须对monty@localhost和monty@"%"
* m+ }; O! R+ H- f5 I( H4 t/ u发出GRANT语句。如果我们增加localhost条目,对localhost的匿名用户条目 3 q9 Z" A9 I% m. d1 x3 n, o4 Y# V6 e
在我们从本地主机连接接时由mysql_install_db创建的条目将优先考虑,因为
: Q0 q, @$ y  A- w# H; I它有更特定的Host字段值,所以以user表排列顺序看更早到来。
' h: ?1 Y7 Y2 _admin + s# b+ _- A; X, W- ?% ?
可以从localhost没有一个口令进行连接并且被授予reload和process管理 ' o( o$ k! Q( a4 f  y4 Y5 f
权限的用户。这允许用户执行mysqladmin reload、mysqladmin refresh和
# H6 H7 E5 w& m, S8 }' a8 Rmysqladmin flush-*命令,还有mysqladmin processlist。没有授予数据库有
! F! Y$ M3 R, p" L% e关的权限。他们能在以后通过发出另一个GRANT语句授权。 1 Y0 q2 A& u! d( o6 N
dummy : N  q$ @% U6 a5 t9 h' {. C
可以不用一个口令连接的一个用户,但是只能从本地主机。全局权限被设 , F: R4 Z: Y2 F  Q4 K( _, @' F
置为'N'--USAGE权限类型允许你无需权限就可设置一个用户。它假定你将在以
) y: K. x( n+ S. l后授予数据库相关的权限。 , a5 ?1 t1 E% o, [0 m2 T
你也可以直接通过发出INSERT语句增加同样的用户存取信息,然后告诉服
, X* q0 R: K2 u; S' _1 g2 T& T务器再次装入授权表:
/ E% t9 m5 A8 O; J1 R
0 b( q% _$ l; Hshell> mysql --user=root mysql ) |5 z0 }% ~  ?( X
mysql> INSERT INTO user VALUES('localhost','monty',PASSWORD   [5 M. t  j/ x
('something'), 1 C# \5 G* |" u! f
'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y',
; D& t' n% B& @9 \$ ]'Y','Y') ; W' [+ e# T- n1 u! I
mysql> INSERT INTO user VALUES('%','monty',PASSWORD('something'),   q- G" y3 n3 b7 }; f9 a6 F
'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y',
* J, H! B/ ]2 U1 m'Y')
  N9 A/ c9 o5 Vmysql> INSERT INTO user SET Host='localhost',User='admin',
9 H% k2 S/ K/ u7 KReload_priv='Y', Process_priv='Y';
3 `4 F- `  ^# O0 N8 Hmysql> INSERT INTO user (Host,User,Password) 7 _, z) E. W8 A2 \, Z
VALUES('localhost','dummy','');
4 _; E( v1 k+ s- Zmysql> FLUSH PRIVILEGES; ) f, ?# `7 S6 X9 S% u
( E$ i& I5 b$ z8 S/ T& G' F/ u  Q
取决于你的MySQL版本,对上述,你可能必须使用一个不同数目'Y'值(在
9 b9 q! ?. c. Y: Y! V8 G# y9 J# O- ~3.22.11以前的版本有更少的权限列)。对admin用户,只用在3.22.11开始的版 * {5 V0 h0 h0 w& ^
本具有的更加可读的INSERT扩充的语法。 * `' Q4 m: _" [3 q6 V2 u' Y9 ]

  L* g8 y) U% I, `注意,为了设置一个超级用户,你只需创造一个user表条目,其权限字段设为 1 M/ N6 `$ J; |3 ~8 G) M
'Y'。不需要db或host表的条目。 ; P* u" {7 }: k9 A/ Y" X  S6 m

& o* i, z0 F0 r- x9 |在user表中的权限列不是由最后一个INSERT语句明确设置的(对dummy用户),
" l9 Y8 C0 r+ C因此那些列被赋予缺省值'N'。这是GRANT USAGE做的同样的事情。
3 W  e- Z1 k7 i# _$ L4 e' E8 o/ i, u  C4 }8 U6 `
下列例子增加一个用户custom,他能从主机localhost、server.domain和
+ l$ V' K8 [, I# g$ Ywhitehouse.gov连接。他只想要从localhost存取bankaccount数据库,从 / B/ S* g0 O# p& M6 u
whitehouse.gov存取expenses数据库和从所有3台主机存取customer数据库。他
7 g; f1 h  w" K: }想要从所有3台主机上使用口令stupid。
5 W# Q) {$ h2 U& u. `" E# ]
, n" _/ {, b) [2 @9 _  M为了使用GRANT语句设置个用户的权限,运行这些命令: ' ^- ]" K. x7 C& G5 z! A# Q
# e+ {4 X* t- C: l  `" f
shell> mysql --user=root mysql
% A( g3 Z: ?: w8 vmysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
# t% e# o: S# |9 U2 oON bankaccount.* 4 F5 e0 U! M8 V* C7 @5 A/ Y
TO custom@localhost
" k# R" a# r" V- L  SIDENTIFIED BY 'stupid';
7 R# b. a8 D3 M( L) `& l+ @mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
  }( n5 d1 |" P- P5 ~, z) \ON expenses.* % x& a% \" q+ j$ N7 j: x1 p8 z
TO custom@whitehouse.gov
4 L: \5 d4 V3 G4 }IDENTIFIED BY 'stupid';
- p- v6 Z5 z; p# ?+ r+ q* ~mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP # z* U& d8 f' j- N
ON customer.* . u9 H7 n9 q' Y, M: @+ v
TO custom@'%'
" d4 ^- Z- f  d. ^! F' TIDENTIFIED BY 'stupid'; ! m+ Q" B6 {$ W0 c+ u
4 }: ]# T1 ^- m
通过直接修改授权表设置用户权限,运行这些命令(注意,在结束时
2 X& T) ^3 X0 g+ KFLUSH PRIVILEGES):
8 S) A2 p, v8 a$ M# ?. O. z) _  C% ~; X% \; x! r
shell> mysql --user=root mysql
" V, [* B7 l$ \9 f$ fmysql> INSERT INTO user (Host,User,Password) 3 e4 `& o8 r. Y$ M3 R
VALUES('localhost','custom',PASSWORD('stupid')); ) N$ G% \$ a- v4 X1 g2 D
mysql> INSERT INTO user (Host,User,Password)
2 b9 N7 `5 t1 c4 C7 T+ VVALUES('server.domain','custom',PASSWORD('stupid'));
1 u' E; h4 N8 k- x* jmysql> INSERT INTO user (Host,User,Password) ! G1 d* k" h% c2 h! Z
VALUES('whitehouse.gov','custom',PASSWORD('stupid'));
6 d( d4 E# E& f1 A1 @mysql> INSERT INTO db
* d; Q- l; H: m2 x(Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv,
! x! f' w$ J6 @: e/ K' w2 VCreate_priv,Drop_priv) & o" g" U6 g/ b2 t
VALUES - y* ^# Q% j3 ^! i, d% n
('localhost','bankaccount','custom','Y','Y','Y','Y','Y','Y');
' d7 U* h8 n/ k, [- fmysql> INSERT INTO db
) A" f3 `) F5 L( [- ^(Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv,
, i9 k# I7 Q: oCreate_priv,Drop_priv)
7 v9 ~0 j% i% SVALUES
( j0 Q* \  q4 k1 m('whitehouse.gov','expenses','custom','Y','Y','Y','Y','Y','Y'); . S4 c9 H+ d9 m" Q- T& p; Q
mysql> INSERT INTO db 3 {" L; O/ D" H( T; x5 Y
(Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv, 8 j; i$ ~- }% ^9 `9 R! O" b2 p
Create_priv,Drop_priv) 4 G0 \& l# n7 C' [/ m
VALUES('%','customer','custom','Y','Y','Y','Y','Y','Y'); 6 L4 N  M2 t. O
mysql> FLUSH PRIVILEGES;
6 O3 u; A1 ~& B2 x  q
8 ^" m6 `: R' @5 V9 l头3个INSERT语句增加user表条目,允许用户custom用给定口令从不同的主机
( Y" O+ k$ C/ A: K+ D4 y进行连接,但是没有授予任何许可(所有权限被设置为缺省值'N')。后3个INSERT ; Y+ b" D' v/ C& z9 ?* X
语句增加db表条目,授予custom以bankaccount、expenses和customer数据库权限,
" F( g: e4 h! k. {1 C1 E) p. x但是只能在从正确的主机存取时。通常,在授权表直接被修改时,服务器必须被告 0 W* v' Y! ^; Y  N2 m
知再次装入他们(用FLUSH PRIVILEGES)以便使权限修改生效。 ' I* V7 @# v1 j! O5 A0 r
( l/ Q- K) w) d# R4 Y  D6 ]8 A* y
如果你想要给特定的用户从一个给定的域上的任何机器上存取权限,你可以发 0 u' Y$ W# p" K# o2 W
出一个如下的GRANT语句:
) _. W: Q: x; x6 ]+ Z  M* @! j) U7 D. D, E5 u
mysql> GRANT ... ' i( j$ D  N% b) j
ON *.*
( Q! x% {* |* R9 E1 Q' jTO myusername@"%.mydomainname.com"
. O% i* }2 _& z) V+ x- g2 R, WIDENTIFIED BY 'mypassword'; ; S: t; M6 U9 [& }7 u

- L0 s' I  i6 c+ C+ C" d为了通过直接修改授权表做同样的事情,这样做:
7 f6 y# p6 Z8 T9 B7 k; V) j- X
7 n; a! M1 g: a) s% Gmysql> INSERT INTO user VALUES ('%.mydomainname.com', 'myusername', 6 @3 X- w, U! X" c# j: _
PASSWORD('mypassword'),...);
4 I$ W; g: M- P* emysql> FLUSH PRIVILEGES;
( I8 k( K% i4 K2 J2 W2 k' ?& ?/ R% ^  P3 H
你也可以使用xmysqladmin、mysql_webadmin甚至xmysql在授权表中插入、改变
" {# v( V3 g* v3 A和更新值。你可以在MySQL的Contrib目录找到这些实用程序。
& W: `. e& W; |: l0 X: Z" f9 C0 K1 @, Z7 l8 x3 \
怎样设置口令 - {6 U6 M: X1 ^) X/ ]' F
在前面小节的例子里说明了一个重要的原则:当你使用INSERT或UPDATE语句存
+ g$ ?2 j; Y% |储一个非空的口令时,你必须使用PASSWORD()函数加密它。这是因为在user表中以
7 y9 n/ r$ e% L加密形式存储口令,而不是作为纯文本。如果你忘记这个事实,你可能像这样试图 . m2 c, h% W) F. h/ f: x
设置口令: 3 R, b7 Z( w9 f( }. s6 q
2 [% c6 A* @% t- A+ V3 \
shell> mysql -u root mysql
0 H: i* m3 `/ x: Smysql> INSERT INTO user (Host,User,Password) VALUES('%','jeffrey',
, ?1 u% I$ b8 ]* {; e'biscuit');
1 M! q' N* F8 I3 P3 Tmysql> FLUSH PRIVILEGES
! \1 u: x7 D; ^! D; n3 h8 h$ `8 s! M. P% H/ b# ~, q
结果是纯文本值'biscuit'作为口令被存储在user表中。在用户jeffrey试图用
) I7 e9 J9 p9 E* [2 g, L! }, x% D这个口令连接服务器时,mysql客户用PASSWORD()加密它并且将结果送给服务器,服 / G3 o" \* Z4 k6 k6 g$ b) R4 c' K
务器比较在user表中的值(它是纯文本值'biscuit')和加密的口令(而不是
4 d) L; I, X* q4 d$ L4 l'biscuit'),比较失败并且服务器拒绝连接: 6 _4 h  p' q6 S/ P% `. I% q

+ f9 d/ g! M7 R9 o& l2 zshell> mysql -u jeffrey -pbiscuit test / U. U$ C4 _# M  `
Access denied
. |% L) }& O6 V' E( v
. @# _8 ^* a: w" P8 q0 i" x# m' |因为当他们被插入user表时,口令必须被加密,相反,INSERT语句应该象这样 % t! L5 }1 g0 r$ V
被指定: . t" j; P# W7 t: j0 q; l* o3 k
: h, P. Z$ o4 G5 a+ k' s
mysql> INSERT INTO user (Host,User,Password)
( G, r2 @; f' A8 mVALUES('%','jeffrey',PASSWORD('biscuit'));
& |4 u. d' O( V' D3 f0 E- T/ o) ]7 X( i( S/ l1 A
当你使用SET PASSWORD语句时,你也必须使用PASSWORD()函数: 1 `# |+ ?8 b! L

0 T9 R) V6 C" \$ h1 Z9 V1 p8 Kmysql> SET PASSWORD FOR jeffrey@"%" = PASSWORD('biscuit');
7 \( j( l6 n7 h; G9 R5 P
7 s, \% z2 u9 C9 G! R' r; k. b如果你使用GRANT ... IDENTIFIED BY语句或mysqladmin password命令设置口 ( l, w4 i7 L: R  s
令,PASSWORD()函数是不必要的。他们都考虑到为你加密口令,多以你可像这样指
( E6 y7 y( Q: F# Y% |3 M$ m4 O定一个口令'biscuit': 9 l* M7 X* _/ X! f* A  u

. U# E  t) H' J* `mysql> GRANT USAGE ON *.* TO jeffrey@"%" IDENTIFIED BY 'biscuit';
0 ~* `: r" l; N+ n) X4 L
1 t& [6 i3 _: Z" x+ p3 n0 j
+ j8 }( b# V5 p8 {$ `# |( n
$ D) V0 [0 q: B2 a1 gshell> mysqladmin -u jeffrey password biscuit
5 H: F+ W, ^$ G9 ?注意: PASSWORD()不是以在Unix口令加密的同样方法施行口令加密。你不应 ! H! j/ e. e' E
该假定如果你的Unix口令和你的MySQL口令是一样的,PASSWORD()将导致与在Unix % l2 [* ?4 V" `$ B! }; l
口令文件被存储的同样的加密值。见6.2 MySQL 用户名和口令。
6 I8 Q/ w, L% l  c0 v6 E
  A. j# T2 p* FAccess denied错误的原因 4 ~0 ^# `) M6 G2 Z" P" F! d' R5 i
当你试着联接MySQL服务器时,如果你碰到Access denied错误,显示在下面 5 D7 G% o4 B1 Q2 x# L' p6 \
的表指出一些你能用来更正这个问题的动作:
6 K; T$ n; {" h& e! E! W
4 P6 Z; Y3 Q* u0 l4 Q你是在安装MySQL以后运行mysql_install_db的脚本,来设置初始授权表内容 $ k, {( F1 f) Q0 G. ]& J4 K: }: {6 g6 k
吗?如果不是,这样做。见6.10 设置初始MySQL权限。通过执行这个命令测试初
0 a, S$ h$ y6 F0 A  |; D8 S& T. p/ V始权限: + b# Z0 j$ @' c$ Q; C# y& z
shell> mysql -u root test " d7 c( m& a! {! a1 x1 V( ^: v

" Q4 r) F% d4 a服务器应该让你无误地连接。你也应该保证你在MySQL数据库目录有一个文件
2 W- ~2 ]  X6 f+ P2 X) y1 u  }“user.MYD”。通常,它是“PATH/var/mysql/user.MYD”,在此PATH是MySQL安
2 D! f8 _( b0 l9 [装根目录的路径。
5 O- e0 ]0 S' N4 c: q
" \* Y8 w4 e9 c$ J, w在一个新的安装以后,你应该连接服务器并且设置你的用户及其存取许可:
" j5 D, j+ ]$ O0 bshell> mysql -u root mysql
7 X0 L& X- l0 i
( P# t3 ?: N1 ~4 N5 V) p3 G服务器应该让你连接,因为MySQL root用户初始时没有口令。既然那也是一个 / p7 ]- Y6 I. V  j1 _
安全风险,当你正在设置其他MySQL用户时,设定root口令是一件重要的事请。如   Q2 {. e1 X  U! l2 W
果你作为root尝试连接并且得到这个错误: # b! b7 F0 O; h! O6 @) A
7 C: a' P$ }( c! V! J; h$ G
Access denied for user: '@unknown' to database mysql
- |  Z9 C& x! T( }8 E  V9 w
2 h: L5 o- i* n, v  i这意味着,你没有一个条目在user表中的一个User列值为'root'并且mysqld + g) A( c. I/ H; V/ M8 X  o7 {& G9 |
不能为你的客库解析主机名。在这种情况下,你必须用--skip-grant-tables选项
% ]" _+ X% P2 R5 N- m! N! \/ O0 H重启服务器并且编辑你的“/etc/hosts”或“\windows\hosts”文件为你的主机
; G2 Y% n8 ~* R) O* y8 O  ]增加一个条目。
0 K- J/ h9 }$ y& d: f/ q! c* V) Y3 X1 z+ ?. \/ o" }
如果你从一个3.22.11以前的版本更新一个现存的MySQL安装到3.22.11版或以
' j* H6 \& Q: b) s: T后版本,你运行了mysql_fix_privilege_tables脚本吗?如果没有,运行它。在
% p  u0 `% t! ?/ }8 l4 W2 [. qGRANT语句变得能工作时,授权表的结构用MySQL 3.22.11修改 。   u+ F# K- ]; ~* P* B3 D
如果你直接对授权表做修改(使用INSERT或UPDATE语句)并且你的改变似乎被 2 u* u8 v0 S/ j& w, `3 W% O
忽略,记住,你必须发出一个FLUSH PRIVILEGES语句或执行一个mysqladmin
+ Q  o: k( j2 ?. f! J9 ?flush-privileges命令导致服务器再次读入表,否则你的改变要道下一次服务器被
- i* s8 w- ~) L1 O$ ?. _$ k3 m重启时再生效。记住在你设定root口令以后,你将不需要指定它,直到在你清洗
$ P/ k& E' o8 @5 Y( j(flush)权限以后,因为服务器仍然不会知道你改变了口令! + E" [" H! R) ?4 k- y
如果你的权限似乎在一个会话(session)当中改变了,可能是一个超级用户改变 & `1 ]/ Q" `/ e
了他们。再次装入授权表作用于新客户连接,但是它也影响现存的连接,如6.9 权
6 s5 k. |0 e# m0 V: a限改变何时生效小节所述。
1 x3 k  ~- V9 V* H8 B2 K为了测试,用--skip-grant-tables选项启动mysqld守护进程,然后你可以改变 4 o3 F9 v# Q3 N
MySQL授权表并且使用mysqlaccess脚本检查你的修改是否有如期的效果。当你对你的
  s3 a5 I) y: n) e. h改变满意时,执行mysqladmin flush-privileges告诉mysqld服务器开始使用新的权 , X/ d0 W/ _4 `6 m! v
限表。注意:再次装入授权表覆盖了--skip-grant-tables选项。这允许你告诉服务
4 H. J( f! x' H器开始使用授权表,而不用停掉并重启它。 8 l/ H/ D4 x; m+ W
如果你有一个Perl、Python或ODBC程序的存取问题,试着用mysql -u user_name 1 \# f" D& D4 G
db_name或mysql -u user_name -pyour_pass db_name与服务器连接。如果你能用   {. {, G& q! J3 v- d& N0 w  P
mysql客户连接,这是你程序的一个问题而不是存取权限的问题。(注意在-p和口令
5 q+ P; F6 v0 ~; K! N+ Z& d3 z* G之间没有空格;你也能使用--password=your_pass句法指定口令。) + }$ I! ]6 `3 [
如果你不能让口令工作,记得如果你用INSERT, UPDATE或SET PASSWORD语句 ! b. K# P* P, b! x2 T6 q1 @
设置口令,你必须使用PASSWORD()函数。如果你用GRANT ... INDENTIFIED BY语
3 w% ]; c$ }" _0 ^5 P5 @8 C  V' y句或mysqladmin password命令指定口令,PASSWORD()函数是不需要的。 ; W% u0 n2 ~4 M1 l
localhost是你本地主机名的一个同义词,并且也是如果你不明确地指定主机 3 S' W4 Z: o2 ?; J( `
而客户尝试连接的缺省主机。然而,如果你正在运行于一个使用MIT-pthreads的系
! c$ ^* ]" J8 S- u8 l统上,连接localhost是不行的(localhost连接使用Unix套接字进行,它没被 MIT
+ x( y, R# A4 T" U1 H% ]; ]) k-pthreads支持),为了在这样的系统上避免这个问题,你应该使用--host选项明确
9 k5 G0 R9 d( f- {5 R$ M. o地命名服务器主机,这将做一个 TCP/IP连接到mysqld服务器。在这种情况下,你 0 ?( k" |4 A- k4 |* K4 y, p
必须有在服务器主机上的user表中条目的你真实的主机名。(即使你在服务器同一
! U3 P- U; X! A& S6 `% b台的主机上运行一个客户程序,这也是真的。)
' ~% w2 o% b9 B3 Z$ r4 [当尝试用mysql -u user_name db_name与数据库连接时,如果你得到一个 * ]0 T' P) E9 u- V. Z
Access denied错误,你可能有与user桌有关的问题,通过执行mysql -u root / W  @1 C6 c, _1 v" ?3 c+ N
mysql并且发出下面的SQL语句检查: ( j4 W5 J8 D# k! M/ e0 g( v
mysql> SELECT * FROM user;
/ e: m5 x3 u4 k4 ~- b
0 f. ]: Y! V* C结果应该包含一个有Host和User列的条目匹配你的计算机主机名和你的MySQL用户   k/ ?7 r" [% _2 v
名。 * N1 U& A* [: A2 `8 E% x

$ I0 W/ W( x9 C8 z! [Access denied错误消息将告诉你,你正在用哪个用户尝试登录,你正在试图 0 C# C4 V2 W4 z2 C7 m
用连接哪个主机,并且你是否正在使用一个口令。通常,你应该在user表中有一 + s* q' W( c+ e
个条目,正确地匹配在错误消息给出的主机名和用户名。
9 U; {# `& c$ h, K5 ]1 m如果当你试着从一个不是MySQL服务器正在运行的主机上连接时,你得到下列 # \' Q5 k  D' w6 p3 E  u* k& D* J
错误,那么在user表中没有匹配那台主机行: ) s2 O, S4 m# i& M
Host ... is not allowed to connect to this MySQL server
7 \2 S$ t) v, j# T& ^6 y) u- {* S* E: m0 u* x
你可以通过使用mysql命令行工具(在服务器主机上!)修正它,把你正在试 # f6 y( W& r) |, Q) N$ \
图连接的用户/主机名组合新加一行到user表中。如果你不在运行MySQL 3.22并且
: R6 h' j, j7 y! t& }- @你不知道你正在从它连接的机器的IP数字或主机名,你应该把一个'%'条目作为
: G1 E5 Y2 D% }0 q# f% aHost列值放在user表中并且在服务器机器上使用--log选项重启mysqld。在试图从
5 ~1 u: W0 W! b( V3 y5 A% E. u客户机器连接以后,在MySQL记录文件中的信息将显示你如何真正进行连接。( , W. ]4 C, V' q
然后用在记录文件上面显示出的实际的主机名代替user表中的'%'条目。否则, / _- y9 S- {1 N( j( g
你将有一个不安全的系统。)
/ ?5 a- K6 o: J6 M4 O2 C1 N5 W% ?; H$ f  X: }+ E+ i/ a
如果mysql -u root test工作但是mysql -h your_hostname -u root test
% D, k2 {# U: d1 n导致Access denied,那么在user表中你可能没有你的主机的正确名字。这里的
! w9 V# c; C* u' v$ F# Q. Z一个普遍的问题是在user表条目中的Host值指定一个唯一的主机名,但是你系统 $ @$ t  V$ I. A; o9 p
的名字解析例程返回一个完全正规的域名(或相反)。例如,如果你在user表中有
  e0 z3 u  ]2 c" D( W  E一个主机是'tcx'的条目,但是你的 DNS告诉MySQL你的主机名是'tcx.subnet.
0 J0 m; Z- d: R- n- \' c9 vse',条目将不工作。尝试把一个条目加到user表中,它包含你主机的IP数字作 , J& `6 E( X- Y4 p
为Host列的值。(另外,你可以把一个条目加到user表中,它有包含一个通配符 - Z" u2 d/ l* i- b/ ^* Y6 ^
如'tcx.%'的Host值。然而,使用以“%”结尾的主机名是不安全的并且不推荐!)
' ?' E$ l( X) m& ^如果mysql -u user_name test工作但是mysql -u user_name other_db_name 8 x4 p0 J) V% ~# {* J" @
不工作,对other_db_name,你在db表中没有没有一个条目列出。 - A3 I0 |0 {: E; y. A: G/ I1 Q7 |
当在服务器机器上执行mysql -u user_name db_name时,它工作,但是在其 & b$ D  Y- c1 {5 r+ ]! Q/ j
它客户机器上执行mysql -h host_name -u user_name db_name时,它却不工作, , L3 p& j7 I1 v+ Y: y  N$ \
你没有把客户机器列在user表或db表中。
& ^  m  X- N' `; B4 G如果你不能弄明白你为什么得到Access denied,从user表中删除所有Host
# k( [) B  s, ]/ V: r包含通配符值的条目(包含“%”或“_”的条目)。一个很普遍的错误是插入用 ! Q* d# M- S3 B* @
Host='%'和User='some user'插入一个新条目,认为这将允许你指定localhost
$ V% e- @( U' }# @% H3 [0 q" {从同一台机器进行连接。它不工作的原因是缺省权限包括一个有Host='localhost' $ S7 L0 H& a! ]5 R
和User=''的条目,因为那个条目一个比'%'更具体的Host值'localhost',当从
* V9 ^8 Q* O; ?- G) T, H# Wlocalhost连接时,它用于指向新条目!正确的步骤是插入Host='localhost'和
# q' O1 p" g' u. b3 ?" j% FUser='some_user'的第2个条目,或删除Host='localhost'和User=''条目。
& l" T' j( x- e  N. T如果你得到下列错误,你可以有一个与db或host表有关的问题:
: Q7 K/ D1 d" K# RAccess to database denied / j/ F1 A1 a5 I0 j
( Q% r# }, \! l" t. c# {
如果从db表中选择了在Host列有空值的条目,保证在host表中有一个或多
2 o- _7 o7 b; H* E) w& n% i个相应的条目,指定运用db表中的哪些主机。如果在使用SQL命令SELECT ...
8 V0 V4 q, j' e" f4 c- ~INTO OUTFILE或LOAD DATA INFILE时,你得到错误,在user表中的你的条目可
! S, T7 n7 @6 \0 X* T% w* e能启用file权限。 ! G$ [; O/ O- X( t3 A
  J2 z6 C( k) S6 D
记住,客户程序将使用在配置文件或环境变量被指定了的连接参数。如果 3 u* `/ \' `, P4 P0 o. o! w8 k% e
当你不在命令行上指定他们时,一个客户似乎正在发送错误的缺省连接参数, # l3 d- Y# P: ]  p$ P# @$ S+ `
检查你的环境和在你的主目录下的“.my.cnf”文件。你也可以检查系统范围 ! R9 ?: H& b' h: Z
的MySQL配置文件,尽管更不可能将在那里指定那个客户的连接参数。如果当
" t% g) O- {; y7 L8 E  V6 D* X你没有任何选项运行一个客户时,你得到Access denied,确认你没在任何选 " p5 j3 f" V4 u7 }# c! Y
项文件里指定一个旧的口令!见4.15.4 选项文件。
% c- M1 G! N7 `如果任何其它事情失败,用调试选项(例如,--debug=d,general,query)
$ u; `7 W2 Z/ e' ^" G+ H* c' k, S启动mysqld守护进程。这将打印有关尝试连接的主机和用户信息,和发出的每 ; p$ K5 o' m# Y! e6 h
个命令的信息。见G.1 调试一个MySQL服务器。
5 l8 q: @0 v6 v& f6 F- W* f如果你有任何与MySQL授权表的其它问题,而且觉得你必须邮寄这个问题 ' ]! Q  Z8 ~7 h( p; d0 d, M
到邮寄表,总是提供一个MySQL授权表的倾倒副本(dump)。你可用mysqldump 4 l+ L0 r5 E( b) L
mysql命令倾倒数据库表。象平时一样,用mysqlbug脚本邮寄你的问题。在一
+ h8 ^) ]8 p) c& d3 i些情况下你可能用--skip-grant-tables重启mysqld以便能运行mysqldump。 2 {' R6 r* {  k& j. k4 K
怎样使MySQL安全以对抗解密高手 5 t' {0 X9 }/ [" `- ^4 |: v( x
当你连接一个MySQL服务器时,你通常应该使用一个口令。口令不以明文 ; c5 o/ f6 f# l& K' V. ?& ?
在连接上传输。 ' u: I. W, R7 B! o! p9 ?9 }4 `2 e
9 d' w0 F% b. P; v! `+ R1 x. [, x0 O
所有其它信息作为能被任何人读懂的文本被传输。如果你担心这个,你可 6 R8 T) m% l+ m2 [" U
使用压缩协议(MySQL3.22和以上版本)使事情变得更难。甚至为了使一切更安全 5 I) F" U4 y4 m5 M1 M
,你应该安装ssh(见http://www.cs.hut.fi/ssh)。用它,你能在一个MySQL服
' ?1 I! k$ k$ s" `# Q( \' _务器与一个MySQL客户之间得到一个加密的TCP/IP连接。
# L6 {: K0 b# W; ?
) T8 i  i0 w( ^' ]( Q; {# C8 D% y为了使一个MySQL系统安全,强烈要求你考虑下列建议:
9 T, r3 U, Q0 Q$ [& }# v0 A; }/ n" l2 P3 d
对所有MySQL用户使用口令。记住,如果other_user没有口令,任何人能简 8 w! z' D3 F' H; w5 Z; a( R
单地用mysql -u other_user db_name作为任何其它的人登录。对客户机/服务器
& z% Q$ n7 A+ f0 E5 A" e  a0 Y# H应用程序,客户可以指定任何用户名是常见的做法。在你运行它以前,你可以通
8 z9 J' D  X2 A+ s过编辑mysql_install_db脚本改变所有用户的口令,或仅仅MySQL root的口令,
: e" w- n( k' h# R9 m象这样: ' C) {8 ^7 s3 [4 u5 T4 u
shell> mysql -u root mysql 6 O- a2 H  K. {3 \4 Y& n# \
mysql> UPDATE user SET Password=PASSWORD('new_password')
2 o, |* }& m0 K* ^2 F& T! a3 P/ D1 T, KWHERE user='root'; ; s, ]2 s+ U* p
mysql> FLUSH PRIVILEGES;
9 ]$ y8 _* K2 f, }4 w" }9 t, a9 f
不要作为Unix的root用户运行MySQL守护进程。mysqld能以任何用户运行, " r8 m8 n9 `$ T
你也可以创造一个新的Unix用户mysql使一切更安全。如果你作为其它Unix用户 . u- {( {) M6 E5 [, m8 `
运行mysqld,你不需要改变在user表中的root用户名,因为MySQL用户名与Unix
7 ^; e2 ^5 }2 ]2 K& \用户名没关系。你可以作为其它Unix用户编辑mysql.server启动脚本mysqld。   ?" t7 a. y- f% R  O& c! w
通常这用su命令完成。对于更多的细节,见18.8 怎样作为一个一般用户运行
) V& A& @( ?+ r! cMySQL。
4 [# G" Z0 S. \1 A5 c# h# s如果你把一个Unix root用户口令放在mysql.server脚本中,确保这个脚本 / h* i- f+ N0 q7 ^2 r* Z2 L2 }$ ?
只能对root是可读的。
8 @( w5 S2 X2 k; E4 |; [3 i检查那个运行mysqld的Unix用户是唯一的在数据库目录下有读/写权限的用 " i% R3 `" q7 v: X$ A
户。
; E" U" {- @% p( V$ E0 a; D& D不要把process权限给所有用户。mysqladmin processlist的输出显示出当 ' l7 u, j; }& e& L
前执行的查询正文,如果另外的用户发出一个UPDATE user SET password= + p. m5 \4 P, I6 H
PASSWORD('not_secure')查询,被允许执行那个命令的任何用户可能看得到。
) F9 j+ k* Z9 T1 \( Nmysqld为有process权限的用户保留一个额外的连接, 以便一个MySQL root用
! o  l4 n( O+ E户能登录并检查,即使所有的正常连接在使用。
- ]+ I# x) W2 N  Q  y不要把file权限给所有的用户。有这权限的任何用户能在拥有mysqld守护
; d0 ?7 @! ?5 |( L进程权限的文件系统那里写一个文件!为了使这更安全一些,用SELECT ... . F' u7 |$ h4 s5 f
INTO OUTFILE生成的所有文件对每个人是可读的,并且你不能覆盖已经存在的 . X$ W! A* [7 K8 g
文件。file权限也可以被用来读取任何作为运行服务器的Unix用户可存取的文 9 Y; s( z1 r. ~1 h  o
件。这可能被滥用,例如,通过使用LOAD DATA装载“/etc/passwd”进一个数 6 ]' [5 Y* N1 K+ z( f) ~' X8 |3 z6 a, {
据库表,然后它能用SELECT被读入。
4 h6 q" o: \5 X( M5 a2 F如果你不信任你的DNS,你应该在授权表中使用IP数字而不是主机名。原则 $ I0 M0 p7 E" r( J2 d
上讲,--secure选项对mysqld应该使主机名更安全。在任何情况下,你应该非常
# l0 W1 B( u' l. s7 w6 K7 M小心地使用包含通配符的主机名!
7 E4 J4 W  x& M' s/ h7 I下列mysqld选项影响安全:
" T( |) e- Q0 c- H5 ]- v6 i4 N  J! i- M) ?$ N5 E8 I- ]
--secure
# s+ Y# z/ Z2 K$ d由gethostbyname()系统调用返回的IP数字被检查,确保他们解析回到原来 2 ~# x, ~% O* M( n6 v. I
的主机名。这对某些外人通过模仿其它主机获得存取权限变得更难。这个选项也
- O: c2 d) c& `4 [& [增加一些聪明的主机名检查。在MySQL3.21里,选择缺省是关掉的,因为它有时
, _  Z+ O4 w6 H( b! ^' Y$ f6 E它花很长时间执行反向解析。MySQL 3.22缓存主机名并缺省地启用了这个选项。 4 ]3 b% W; B$ K6 |
--skip-grant-tables 5 U% D5 O# G) j7 S! m, S/ B2 j
这个选项导致服务器根本不使用权限系统。这给每个人以完全存取所有的数 & \+ o7 l8 M2 ?2 |5 u9 o3 g, s8 w
据库的权力!(通过执行mysqladmin reload,你能告诉一个正在运行的服务器
. J& p% @4 x5 {- a再次开始使用授权表。)
+ w& X$ {! ?4 s. f--skip-name-resolve
! s4 }8 `( s4 q3 Q; x主机名不被解析。所有在授权表的Host的列值必须是IP数字或localhost。
; B) u1 ~; b. ?# @9 B: ~% I9 N* k# n--skip-networking ! W& s1 ]( o; ^. a5 g% I5 P
在网络上不允许TCP/IP连接。所有到mysqld的连接必须经由Unix套接字进 2 f* Z9 C% A% p
行。这个选项对使用MIT-pthreads的系统是不合适的,因为MIT-pthreads包不 : T& W6 j/ X: X+ L) N! x) M  O6 _
支持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 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
看了一屏就晕了。。。$ v& m$ m( S8 W" f, f
汗。。
1 C* }! ?% C' x# s1 {/ ~/ v6 P4 u水平不够,消化不了。。4 m% T' J6 j% u( o, u9 o
不过还是顶一下
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 顶 踩

本版积分规则

关闭

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

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