下沙论坛

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

QQ登录

QQ登录

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

MySql的权限存取系统

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

# B6 P1 z3 f' ~3 N5 U: V权限系统做什么
# L' b: f2 p4 B8 Y# G$ ?5 LMySQL权限系统的主要功能是证实连接到一台给定主机的一个用户, 7 p4 I4 |- H+ a: d) \% X- ?: k( i
并且赋予该用户在一个数据库上select、 insert、update和delete的
3 E7 A' F; v. t# Y4 s4 h2 b! ^: _权限。
: L( F7 w: S. e2 j- k5 ^5 C9 P, E# P/ }% Q0 r3 U4 }
附加的功能包括有一个匿名的用户和对于MySQL特定的功能例如
3 W& x- q5 `% {) M( TLOAD DATA INFILE进行授权及管理操作的能力。
: I" O. `- {7 S' m. n( @: j: K
5 @9 P! Z/ e/ Q7 `& RMySQL 用户名和口令 4 D3 Y- p3 Y9 K( t# u, R
由MySQL使用用户名和口令的方法与Unix或Windows使用的方式有很
: x" o' m; }8 j; k多不同之处: # ?( E0 V' }1 J6 t$ _0 ^( k
$ z, ~0 W; ]( a/ w& M% I: J9 x; m
MySQL使用于认证目的的用户名,与Unix用户名(登录名字)或 & ?, \, O$ m" H
Windows用户名无关。缺省地,大多数MySQL客户尝试使用当前Unix用户 5 A8 b2 ^4 x' G! E- Q$ s1 q5 u
名作为MySQL用户名登录,但是这仅仅为了方便。客户程序允许用-u或- 1 A1 z' Y- N0 N" {1 O8 R0 Q
-user选项指定一个不同的名字,这意味着无论如何你不能使得一个数据 5 V: @- e- `# m) K
库更安全,除非所有的MySQL用户名都有口令。任何人可以试图用任何名
3 r/ `* i' z+ Y; g" @  I: y! n5 b( P字连接服务器,而且如果他们指定了没有口令的任何名字,他们将成功。 * x- B. l0 a! g
MySQL用户名最长可以是16各字符;典型地,Unix用户名限制为8个字符。
" ^' y1 n! |2 [& \$ \! N$ G( q) QMySQL口令与Unix口令没关系。在你使用登录到一台Unix机器口令和你使 ' J7 k% e' x  I6 U9 B, m
用在那台机器上存取一个数据库的口令之间没有必要有关联。
1 E3 L# q$ C/ |# J4 U6 K5 |MySQL加密口令使用了一个Unix登录期间所用的不同算法。 2 M) |0 t- V$ U# s

, h# Z/ W; j; a7 ?/ s: C' H与MySQL服务器连接
5 d7 V) ~7 x2 @' ~- c0 u当你想要存取一个MySQL服务器时,MySQL客户程序一般要求你指定 3 o' M" Y2 L- v2 o3 |3 f
连接参数:你想要联接的主机、你的用户名和你的口令。例如,mysql ; d/ n" w' ^2 k0 ~0 n
客户可以象这样启动(可选的参数被包括在“[”和“]”之间): # B3 L, O7 E* h1 D& w9 A$ k4 J% o

+ K, n% W$ Q1 _8 ^; [shell> mysql [-h host_name][-u user_name][-pyour_pass ] + w: u$ D# }2 @
-h, -u和-p选项的另一种形式是--host=host_name、--user=
+ U: M' u" U( [! Auser_name和--password=your_pass。注意在-p或--password=与跟随它
6 k- L/ m5 ~0 t# G$ a3 ~# I" ~后面的口令之间没有空格。
  o- R3 e$ C4 b
% X' x. P9 t4 z; k$ G% Z6 ^注意:在命令行上指定一个口令是不安全的!随后在你系统上的任
- z% p* ]9 E& i: k. E何用户可以通过打类似这样的命令发现你的口令:ps auxww。
" f1 z' `6 Z4 o4 @% n; v0 V* w* A+ E$ Z
对于命令行没有的联接参数,mysql使用缺省值:
* d+ z; T* Q; e' C' f7 x: ~
/ W+ c8 H0 |' _" a缺省主机名是localhost。
  k" Z2 S; T2 u! [; W" \& D缺省用户名是你的Unix登录名。
! B3 A/ l1 u) t4 J; Z如果没有-p,则没有提供口令。
* K$ R- T$ v- J8 B% n2 e# ]这样, 对一个Unix用户joe,下列命令是等价的:
6 Q% N1 x% K- B$ y" @
3 |% L% M4 }& fshell>mysql -h localhost -u joe
- ~1 M' E6 C* p/ z* u* x# ?, x6 Q& ishell>mysql -h localhost
7 w# z2 c6 P, R, T0 zshell>mysql -u joe & B1 ]5 I6 `) G& g! m* x2 F
shell>mysql
9 e2 A4 x" p. {+ k6 M: r0 L& f  }4 ~5 E
其它MySQL客户程序有同样表现。
9 `5 E: m" n( P! P, N! L! b  |- V$ I% k! R0 t2 ^
在Unix系统上,当你进行一个连接时,你可以指定要使用的不同的缺
; L  i5 r3 u5 v8 u$ `4 b省值,这样你不必每次在你调用一个客户程序是在命令行上输入他们。这
2 W4 j5 S/ Y3 b# X. W可以有很多方法做到:
. X2 c: P2 d& O
# c, M9 I3 P8 q/ Q. ~' m. o你能在你的主目录下“.my.cnf”的配置文件的[client]小节里指定
! w9 r8 D3 a& ^连接参数。文件的相关小节看上去可能像这样:
$ M( s4 v3 V6 }' x[client]
- M# @" O: T) G) a8 q& dhost=host_name ( i% |3 s# e& l7 S  G8 R/ O3 D
user=user_name
- Y" H7 G' N1 @/ U* l2 _" Dpassword=your_pass 0 m9 _( ]8 }* _; R+ \2 |
( Z' e9 T3 v; Z. b
你可以用环境变量指定连接参数。主机可用MYSQL_HOST指定,MySQL 2 z5 m. C3 q% T' G3 @2 B; l# j( K
用户名字可用USER指定(仅对 Windows),口令可用MYSQL_PWD指定(但是 7 o: `. T2 r$ p; H% L: p0 ^
这不安全) 。
; J" n$ @/ P4 u( d! |( J3 t如果连接参数以多种方法被指定,在命令行上被指定的值优先于在配
( r7 G8 K0 {6 ~3 ~; m( W* o置文件和环境变量中指定的值,而在配置文件指定的值优先于在环境变量 / j, d% N( d$ I' L
指定的值。
# v" C7 t+ |) C* B0 A2 ^% k- c& R  Q: m3 U' C" J
使你的口令安全 ; ]  y, O/ o) W# K
以一种暴露的可被其他用户发现的方式指定你的口令是不妥当的。 & k! t6 @! e' l
当你运行客户程序时,你可以使用下列方法指定你的口令,还有每个方法 . k+ f/ c$ O+ K! q2 l+ Y2 M
的风险评估: 9 y1 s3 c) L* M

- k/ g. @0 ^( ~- V* S使用一个在命令行上-pyour_pass或--password=your_pass的选项。
2 a& ^$ G) a2 f6 T/ l1 Z4 F4 S这很方便但是不安全,因为你的口令对系统状态程序(例如ps)变得可见, # Y9 L( L1 u  p8 E& r, b# B
它可以被其他的用户调用来显示命令行。(一般MySQL客户在他们的初始化
3 X& n! I2 u5 p3 O( w9 I3 f+ H* B顺序期间用零覆盖命令行参数,但是仍然有一个短暂间隔时间内参数值可 3 e& m. e* b- c! B
见的。)
' l1 v, h+ F' H+ b+ _使用一个-p或--password选项(没有指定your_pass值)。在这种情况 & X7 \$ h7 D6 l1 F
下,客户程序请求来自终端的口令:   C4 Z: C0 @9 u. ^2 C* {
" z" m8 W( d. f% o, ?
shell>mysql - u user_name - p 8 H% X) Z3 ^: b- }# p- u
Enter password: ******** " u  ^9 r$ G6 s5 S& j1 P

, J+ m/ w+ j1 N; F& X客户回应“*”字符到作为输入你的口令的终端使得旁观者不能看见 ; w9 `% G* c  m7 U/ p' r
它。因为它对其他用户不可见,与在命令行上指定它相比,这样进入你 - N- N8 q. t' C) {8 A
的口令更安全。然而,这个输入一个口令的方法仅仅为你交互式运行程 ) @8 A6 G6 i9 _. }2 }
序是合适的。如果你想要从非交互式运行的一个脚本调用一个客户,就 ; I7 ^/ V' N* M! B: L2 o
没有从终端输入入口令的机会。 3 w/ ~3 k! G; J5 R! @/ t

! H3 v' a2 f0 f# D在一个配置文件中存储你的口令。例如,你可你的主目录的 " L' t& U1 S8 f3 Z0 R
“.my.cnf”文件中的[client]节列出你的口令:
: d4 |5 {  e2 ]! g[client] 7 E2 H9 r9 ^% M
password=your_pass 5 A) t# C$ z& s0 J: D: m8 J& a' G
# _  |3 Q& e8 Q+ y/ T
如果你在“.my.cnf”里面存储口令,文件应该不是组或世界可读或 # r6 Q$ c0 w8 O
可写的。保证文件的存取模式是400或600。见4.15.4 选项文件。 ' H, |  @- H5 G, f' L
7 t! B6 ]: }  {' q. n0 r7 a2 _
你可在MYSQL_PWD环境变量中存储口令,但是这个方法必须想到是极 % h" z/ L2 [% t  p
不安全的且应该不使用。ps的某些版本包括显示运行进程的环境的选项; - a# w3 K1 `1 C: ~/ ~
如果你设定MYSQL_PWD,你的口令将对所有人是显而易见的,甚至在没有 7 F$ F1 o# ~0 ^- {/ P0 T
这样一个版本的ps系统上,假设没有其他方法观察到进程环境是不明智
7 W# ?1 R; i: M" s" E/ F的。 2 F# J/ M) v$ P5 r  ]( W* G
总之,最安全的方法是让客户程序提示口令或在一个适当保护的“
% @! |; K% j! C. F) S7 p" }7 _2 K.my.cnf”文件中指定口令。
, Y8 l- D- I% b# U
9 s  a1 |& v2 s$ Y2 R: xMySQL提供的权限
- b6 V6 x4 K) V5 T权限信息用user、db、host、tables_priv和columns_priv表被存储
4 d8 m5 n. c; i# ?- I在mysql数据库中(即在名为mysql的数据库中)。在MySQL启动时和在权限
+ x: A  z& [+ H! E2 i5 ^修改何时生效所说的情况时,服务器读入这些数据库表内容。 ) |# }! o3 [& f/ u6 B/ h

9 b$ V& B; j8 n- z由MySQL提供的权限名称显示在下表,还有在授权表中每个权限的表 1 v' N( p7 P$ u/ Q& W2 k
列名称和每个权限有关的上下文: ; G3 S8 Z. d& S. e2 t! b5 A! B
权限 列 上下文 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 在服务器上的文件存取 + A2 {6 |+ G. w' A) }$ ^$ |
select、insert、update和delete权限允许你在一个数据库现有的 3 F. X' i. `5 ]  o
表上实施操作。
' w' w% H2 {2 r1 k8 k, ^4 ^) T- r: F$ @' G1 R+ ~
SELECT语句只有在他们真正从一个表中检索行是才需要select权限, % g- B$ n1 S& ]1 l! h, Q5 k7 U
你可以执行某个SELECT语句,甚至没有任何到服务器上的数据库里的存
+ L# O/ t! v% R: w; c7 _) b取任何东西的许可。例如,你可使用mysql客户作为一个简单的计算器: ' H& m8 S* U1 v0 i
: m1 f+ b5 Q) B; n
mysql> SELECT 1+1;
/ P- T* W; q# t. E) u: V) b& R" pmysql> SELECT PI()*2;
# w+ O! S+ C7 H* C1 |8 |6 M- I! k1 w. {7 ^
index权限允许你创建或抛弃(删除)索引。
4 E$ x: M& w) U3 g& t: }
" J3 O' A' P1 U! E" N! o$ q* T2 @. E! falter权限允许你使用ALTER TABLE。
6 V9 X8 l1 L/ r4 B
& D' W6 j' t) j* ncreate和drop权限允许你创建新的数据库和表,或抛弃(删除)现存的 9 V, T2 L9 s" L1 I3 N  q6 h' D
数据库和表。
5 A  ?! x/ ^, ?" g) O* c6 Q1 ^4 h- D" f7 N
注意:如果你将mysql数据库的drop权限授予一个用户,该用户能抛弃 2 d6 J8 u' C* H
存储了MySQL存取权限的数据库! ' }' W- M- V2 f0 ^" i. D; A

0 X: Q5 x: Z* v2 c& mgrant权限允许你把你自己拥有的那些权限授给其他的用户。
( C& {* ]% s- X
8 I" O: `1 J3 z+ H; I( `file权限给予你用LOAD DATA INFILE和SELECT ... INTO OUTFILE语句 ( H1 P3 S- q$ _, w. \+ s7 g
读和写服务器上的文件,任何被授予这个权限的用户都能读或写MySQL服务 5 o) R8 x: t, V' ~2 u3 a" z$ J+ ?
器能读或写的任何文件。
) R7 U" W6 d  o$ ?
( h, G" b  w* h其余的权限用于管理性操作,它使用mysqladmin程序实施。下表显示
3 _3 D) s4 [, R+ Cmysqladmin支配每个管理性权限允许你执行的命令: * v2 Q* e, c) e, B; e3 |
优惠 权限拥有者允许执行的命令 reload reload, refresh, flush-privileges, flush-hosts, flush-logs, flush-tables shutdown shutdown precess processlist, kill $ O' T( N8 A) ]$ t$ ]1 p
reload命令告诉服务器再读入授权表,refresh命令清洗所有表并打开
( f+ t( U) E' V- O6 ]7 S8 P' m和关闭记录文件,flush-privileges是reload的一个同义词,其它flush-* 2 \) n- b" S& v# z& Q. W0 v
命令执行类似refresh的功能,但是范围更有限,并且在某些情况下可能更 0 S5 O+ V0 P! H/ m
好用。例如,如果你只是想清洗记录文件,flush-logs比refresh是更好的 1 V) ~& p+ L& A
选择。 # U5 \2 [; e$ ~7 O
( b5 o" h, w( R6 a9 [2 E' Q# {
shutdown命令关掉服务器。
. w- a( i5 v3 K* A6 v5 u% d0 a4 h' J
processlist命令显示在服务器内执行的线程的信息。kill命令杀死服
/ K( s! x5 h; i( h. v务器线程。你总是能显示或杀死你自己的线程,但是你需要process权限来
; f1 _2 v0 d' M+ I显示或杀死其他用户启动的线程。 ! k. u/ b" A* P- F
& S, j4 o0 z; ]
总的说来,只授予权限给需要他们的那些用户是一个好主意,但是你 7 |6 N9 x7 y, b0 ~) {
应该在授予某个权限时试验特定的警告:
% H. Q* s! g) ]+ T7 J& ?' D0 U# w# O+ d5 U2 {3 M- U8 \+ L
grant权限允许用户放弃他们的权限给其他用户。2个有不同的权限并 1 Q9 d5 e4 Q4 e7 p
有grant权限的用户可以合并权限。
- v6 `1 ]$ Y1 D# ]! M' Ealter权限可以用于通过重新命名表来推翻权限系统。
' \! j! c. _& f1 y* m" J! L$ ffile权限可以被滥用在服务器上读取任何世界可读(world-readable,
" h1 {) f, m+ J9 k1 a: {- E即任何人可读)的文件到一张数据库表,然后其内容能用SELECT被存取。
) L5 q! C6 h+ n; s9 h3 n( D+ t: P5 Tshutdown权限通过终止服务器可以被滥用完全拒绝为其他用户服务。 1 W: k- ?7 l" o: d6 w3 v: O- K
precess权限能被用来察看当前执行的查询的普通文本,包括设定或改
5 s" [% m: \; d) s) w6 D变口令查询。
8 D  R1 D6 v" n在mysql数据库上的权限能被用来改变口令和其他存取权限信息。(口
  A+ u  b" J5 Y, [9 ?令被加密存储,所以一个恶意的用户不能简单地读取他们。然而,有足够 & m0 e- q  S6 \9 O
的权限,同一个用户能用不同的一个代替一个口令。)
6 }5 F4 ?" B  ^/ I2 M/ G* u有一些事情你不能用MySQL权限系统做到:
' _1 K7 w$ q6 N* i6 Z+ \
9 |3 O- h) Q" d3 v' V5 K' y你不能明显地指定一个给定用户应该被拒绝存取。即,你不能明显地匹 & d, X, x0 c: x; q% l
配一个用户并且然后拒绝连接。
* J' ~& G  s6 H3 g# Q- f5 {你不能指定一个用户有权创建立或抛弃一个数据库中的表,也不能创建 1 T& t4 \9 }  o9 a; t0 `
或抛弃数据库本身。 % @$ |- F; ^# R/ Z" d
权限系统工作原理
' D: ?: e! k& }MySQL权限系统保证所有的用户可以严格地做他们假定被允许做的事情。
( V$ L* Y" B% T# M当你连接一个MySQL服务器时, 你的身份由你从那连接的主机和你指定的用
* H" S; F/ i. Z) k  @( J户名来决定,系统根据你的身份和你想做什么来授予权限。
( D3 D4 ]6 t. {" N+ v
7 H" w( _( \5 g! YMySQL在认定身份中考虑你的主机名和用户名字,是因为有很小的原因假 , P6 M% F; {6 n; U
定一个给定的用户在因特网上属于同一个人。例如,用户从whitehouse.gov
4 @  ^0 I  v8 j( c, w  R连接的bill不必和从mosoft.com连接bill是同一个人。 MySQL通过允许你区
* }; J9 {6 F" u分在不同的主机上碰巧有同样名字用户来处理它:你可以对从whitehouse.gov 8 u" D5 n$ V# v  `( w
连接授与bill一个权限集,而为从microsoft.com的连接授予一个不同的权限
. c+ o! ~$ c, ]) p/ c) B$ D集。 4 M7 |: `0 o  H9 i# n# t
( ~! g0 `$ a2 U& L
MySQL存取控制包含2个阶段: ; U5 G( |2 s, F8 f/ t

) G7 Q: J1 p( }阶段1:服务器检查你是否允许连接。
" a( E+ i0 _  ~6 n9 H, _6 z, U阶段2:假定你能连接,服务器检查你发出的每个请求。看你是否有足够
  F8 \7 U6 V: f1 w的权限实施它。例如,如果你从数据库中一个表精选(select)行或从数据库抛
/ L+ ]5 R- K% U1 U9 N弃一个表,服务器确定你对表有select权限或对数据库有drop权限。
, t* E. B/ s9 R0 d9 j$ B服务器在存取控制的两个阶段使用在mysql的数据库中的user、db和host
" H/ D; t3 ]+ c/ O3 o! k表,在这些授权表中字段如下: ! z) a$ B, d# F% n- 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 " Q/ V3 P6 @' g% A
对存取控制的第二阶段(请求证实),如果请求涉及表,服务器可以另外
+ Z( e& f& Q4 h# H参考tables_priv和columns_priv表。这些表的 + n( ~; P+ A, ^) m" E2 n
字段如下:
! S2 M) L. }0 D: n1 E. l6 C表名称 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
) d$ Y, f) g/ i; b" U& P2 i1 w  c% I对存取控制的第二阶段(请求证实),如果请求涉及表,服务器可以另外 3 T7 y% B3 P. }* _. X
参考tables_priv和columns_priv表。这些表的字段如下:
. a/ B7 ~$ _6 `  `5 U8 X字段名 类型 Host CHAR(60) User CHAR(16) Password CHAR(16) Db CHAR(64) (tables_priv和columns_priv表为CHAR(60)) 1 ?+ L! L; [: v3 Y) T0 e# p
在user、db和host表中,
0 v4 e; P2 @- E! x所有权限字段被声明为ENUM('N','Y')--每一个都可有值
, g  r: e9 J5 p0 B' C- w9 b: E4 g5 V'N'或'Y',并且缺省值是'N'.
; k! [9 K  R, n$ d1 n在tables_priv和columns_priv表中,权
' L0 X7 q; p' y0 e7 x限字段被声明为SET字段:
& `; `6 m+ {$ b' e+ g表名 字段名 可能的集合成员 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 ]* L, t8 a) E' s3 X- X
每个授权表包含范围字段和权限字段。 - y5 h: Q1 c0 Z8 u% A4 p" Y& I

5 E  a7 L7 U3 ]4 g: `范围字段决定表中每个条目的范围,即,条目适用的上下文。例如, $ M" x. \( X. P9 Y) j
一个user表条目的Host和User值为'thomas.loc.gov'和'bob'将被用于
. J* Y. j& a/ g3 }, z2 [; p证实来自主机thomas.loc.gov的bob对服务器的连接。同样,一个db表条
2 u7 W) p  k0 M4 G3 @目的Host、User和Db字段的值是'thomas.loc.gov'、'bob'和'reports'
& T1 c, {' {1 F* H将用在bob从主机联接thomas.loc.gov存取reports数据库的时候。
/ F/ G: I/ w$ t* E  stables_priv和columns_priv表包含范围字段,指出每个条目适用的表或 2 o9 W$ k% ^/ J/ t7 e& E
表/列的组合。 5 }# f2 z% k, I3 ^

3 H# M) y0 C& m+ s7 L对于检查存取的用途,比较Host值是忽略大小写的。User、Password、
  b! n+ w5 ]  r# h( O( GDb和Table_name值是区分大小写的。Column_name值在MySQL3.22.12或以
# C1 U1 A! j; v" o# ^3 [3 y; y后版本是忽略大小写的。
5 m" c5 n+ |/ Y' Y2 v; f/ U' Z
% c8 L" u' d$ S4 C9 a! F. e& P权限字段指出由一个表条目授予的权限,即,可实施什么操作。服务
: _- s- |. q+ o( r* d- g$ G2 W+ `器组合各种的授权表的信息形成一个用户权限的完整描述。为此使用的规
3 }5 z- y- C4 ]5 W: w5 ^% Z则在6.8 存取控制, 阶段2:请求证实描述。
* @9 u3 |5 r8 V% G# l8 t
( b( Y9 P& Y6 D, R5 j范围字段是字符串,如下所述;每个字段的缺省值是空字符串:
; |( e6 N7 r0 q字段名 类型 Host CHAR(60) User CHAR(16) Password CHAR(16) Db CHAR(64) (tables_priv和columns_priv表为CHAR(60)) 8 i) R; p# I/ Q* h  S6 k
在user、db和host表中,所有权限字段被声明为ENUM('N','Y')--每一 . J" d0 x% @7 D* P7 Z" D+ M, ^
个都可有值'N'或'Y',并且缺省值是'N'.
- t' Y  Y  k+ B( F4 B4 v/ _
4 z* B- s' U( E* R  k, S在tables_priv和columns_priv表中,权限字段被声明为SET字段: 0 I; D8 g1 @/ O, {: b
表名 字段名 可能的集合成员 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' # ]) [+ t' B& o" F5 u
简单地说,服务器使用这样的授权表:
9 o: k4 m7 O1 |- n  Y  s) j' e9 t5 o% z$ V/ Q7 b1 z
user表范围字段决定是否允许或拒绝到来的连接。对于允许的连接, # Y  [2 g- s4 g5 _& u
权限字段指出用户的全局(超级用户)权限。 ; R9 j. \& |2 a
db和host表一起使用: # j, {* u6 u2 m. O& ^- k0 {
db表范围字段决定用户能从哪个主机存取哪个数据库。权限字段决定
6 z/ u# Q) r  R& y2 l# ^" i允许哪个操作。
: V4 V: F& @, H5 S当你想要一个给定的db条目应用于若干主机时,host表作为db表的扩
/ R  X( _6 I7 b9 p. c展被使用。例如,如果你想要一个用户能在你的网络从若干主机使用一个
# Z" s# a  c" y5 @* C数据库,在用户的db表的Host条目设为空值,然后将那些主机的每一个移
+ ^1 ~# ]; L% V8 ~  [9 n3 G入host表。这个机制详细描述在6.8 存取控制, 阶段2:请求证实。
& F- P( h8 t. l7 g9 ctables_priv和columns_priv表类似于db表,但是更精致:他们在表
* G' K: [, P* G  c) y和列级应用而非在数据库级。
. I1 a3 h$ f$ e: ?* @7 B2 m注意管理权限(reload, shutdown, 等等)仅在user表中被指定。这是 4 r8 O0 X/ B+ \( a% K* \
因为管理性操作是服务器本身的操作并且不是特定数据库,因此没有理由 : g+ S( D2 P: @% ^1 ]
在其他授权表中列出这样的权限。事实上,只需要请教user表来决定你是 : b$ e- c; n" {  E, D
否执行一个管理操作。
4 }% s0 t2 q/ ]2 P1 C4 m
' h" G: f7 E1 b( e8 j0 ffile权限也仅在user表中指定。它不是管理性权限,但你读或谢在服 $ ]  h$ o" M  W5 b. U3 o- \
务器主机上的文件的的能力独立于你正在存取的数据库。 7 j7 c9 X, J) m" ~" {
2 S4 `& P) T) \
当mysqld服务器启动时,读取一次授权表内容。
- [; Y" F+ q/ I+ j$ m8 w" w2 |/ @2 l3 T+ J3 ~
当你修改授权表的内容时,确保你按你想要的方式更改权限设置是一
% {5 f/ ?) Y. S个好主意。
; P( @$ {4 y& w% m# J
9 a0 `2 l% h% n9 t0 x: G一个有用的诊断工具是mysqlaccess脚本,由Carlier Yves 提供给 " H( X0 {" ~' z2 d9 l" C
MySQL分发。使用--help选项调用mysqlaccess查明它怎样工作。注意:
; q1 Z1 w; u9 S2 U/ Hmysqlaccess仅用user、db和host表仅检查存取。它不检查表或列级权限。 6 i7 v' [! S/ f% G
0 A4 L! b3 f5 t# V( F* L1 y8 h- ^
存取控制, 阶段1:连接证实 5 ]' m/ U% u0 B* n, h& ]: e
当你试图联接一个MySQL服务器时,服务器基于你的身份和你是否能 ) |: ?/ @/ ^: u0 W9 O
通过供应正确的口令验证身份来接受或拒绝连接。如果不是,服务器完全 . p% Q# b" f" k6 |
具结你的存取,否则,服务器接受连接,然后进入阶段2并且等待请求。
$ T  c! L) I  _. h  @# {  X( r8 i( m) @
你的身份基于2个信息: 0 }9 m% v& p# j6 Q" x0 Q

: Q* x0 Y( N& W" K8 v2 R你从那个主机连接
2 b9 U+ Q0 ]0 u  R9 s你的MySQL用户名 % R* g  o# f- c, `  h
身份检查使用3个user表(Host, User和Password)范围字段执行。服 9 L, z# f% a) X1 m' B( v' b4 v
务器只有在一个user表条目匹配你的主机名和用户名并且你提供了正确的 + U$ b1 k9 l% ~. c/ W0 V
口令时才接受连接。 . [" v. Z- f0 |: B' k
2 f8 z+ C/ N* z: T5 `/ Q
在user表范围字段可以如下被指定: , W5 z  Y, c9 I) U

, ?$ b$ y) y' x6 a- X9 Q) ~一个Host值可以是主机名或一个IP数字,或'localhost'指出本地主机。
0 S5 E7 B# w6 W# h3 {; ~2 c: J* r2 `' B你可以在Host字段里使用通配符字符“%”和“_”。
) N) b' K6 k9 b7 d7 X5 |* Z( \: t一个Host值'%'匹配任何主机名,一个空白Host值等价于'%'。注意这些 ' V: X) P& M  \8 _3 _# V" C
值匹配能创建一个连接到你的服务器的任何主机!
9 [6 A. X! j$ n# q+ M$ V通配符字符在User字段中不允许,但是你能指定空白的值,它匹配任何 7 q1 U( O9 Z4 _9 A' ^+ g
名字。如果user表匹配到来的连接的条目有一个空白的用户名,用户被认为
& g, Y' {$ K9 O5 a是匿名用户(没有名字的用户),而非客户实际指定的名字。这意味着一个空 $ U  E% _( {$ F
白的用户名被用于在连接期间的进一步的存取检查(即,在阶段2期间)。
5 _- P; x2 e( E8 }+ ]; N9 EPassword字段可以是空白的。这不意味着匹配任何口令,它意味着用户
  a* o8 q2 G" I. `' T; |) n必须不指定一个口令进行连接。 - y$ N, z( K8 |& y9 W
非空白Password值代表加密的口令。 MySQL不以任何人可以看的纯文本 1 L9 J, X- B2 E
格式存储口令,相反,正在试图联接的一个用户提供的口令被加密(使用
  Z, P/ f( K8 mPASSWORD()函数),并且与存储了user表中的已经加密的版本比较。如果他   s, S( e! V3 A! |
们匹配,口令是正确的。
( E3 B8 I* S# P3 C$ X+ T9 |
4 q" s1 g" L; R8 W( r4 R0 r下面的例子显示出各种user表中Host和User条目的值的组合如何应用于到来 $ c  f( U* S' c, e7 R! e; |1 z
的连接:
0 l1 E- Z( ~9 x! A
# S# `3 ^; h* s" H: l# I: `Host 值 User 值 被条目匹配的连接 8 U1 l, f! D% L. [
'thomas.loc.gov' 'fred' fred, 从thomas.loc.gov 连接
' e' N6 q0 x- \2 M; Y'thomas.loc.gov' '' 任何用户, 从thomas.loc.gov连接 9 b$ @' p5 A2 u9 Y
'%' 'fred' fred, 从任何主机连接 ) n# }  b. ?$ e1 M4 u- ~
'%' '' 任何用户, 从任何主机连接
) T( K9 i8 `  c2 H'%.loc.gov' 'fred' fred, 从在loc.gov域的任何主机连接
$ V: y  l7 F: X6 h$ {'x.y.%' 'fred' fred, 从x.y.net、x.y.com,x.y.edu等联接。(这或许 4 V* J! ?+ }$ `$ @0 ]* [8 y! g
无用) + n* |4 D; h; W
'144.155.166.177' 'fred' fred, 从有144.155.166.177 IP 地址的主
# N7 _$ Z: Z9 q0 K3 w! K0 B机连接
5 t, @, Q& e5 O9 J/ U& v" ?6 H# J'144.155.166.%' 'fred' fred, 从144.155.166 C类子网的任何主机连 ; G6 a3 j7 w3 a" ]( {

% d+ n. s" M7 S) Q$ K; m1 X  U' ^+ ^7 z
既然你能在Host字段使用IP通配符值(例如,'144.155.166.%'匹配在一个子 5 n! o9 y5 f! Y% ]
网上的每台主机),有可能某人可能企图探究这种能力,通过命名一台主机
# Z/ h4 x0 b% o5 }/ r8 h( J3 l' X$ b+ l为144.155.166.somewhere.com。为了阻止这样的企图,MySQL不允许匹配以 ( v+ h. U, m$ _- y: z8 b+ @) T
数字和一个点起始的主机名,这样,如果你用一个命名为类似1.2.foo.com的 2 P/ i1 c6 \* I% J5 A6 ^
主机,它的名字决不会匹配授权表中Host列。只有一个IP数字能匹配IP通配 , ^5 a9 g% C/ I
符值。
" N- m9 n3 p" [1 x) O4 ^+ M/ z: \% k. I+ x, t" J' V
一个到来的连接可以被在user表中的超过一个条目匹配。例如,一个由
3 [: ?0 W8 M4 W! M' Lfred从thomas.loc.gov的连接匹配多个条目如上所述。如果超过一个匹配, 4 D0 f: j1 Q1 N( e
服务器怎么选择使用哪个条目呢?服务器在启动时读入user表后通过排序来
/ N4 o( E2 e1 v0 }" p* k解决这个问题,然后当一个用户试图连接时,以排序的顺序浏览条目,第一 / t4 R2 v' Z7 d' a. @$ }% W& A, V
个匹配的条目被使用。
9 z0 ^9 Z2 k* F. K# ]% G. F& `; i5 M2 `# [6 w$ ?2 H% u: F3 Z
user表排序工作如下,假定user表看起来像这样:
3 d! {% W1 K/ A( `
. t! M$ I$ p5 P& D( u6 H& X6 @  `" u- l/ [: y9 }6 J
+-----------+----------+-
' w; Y3 x* U8 T! Z* C9 q│ Host │ User │ ...
$ A' F5 u* z2 X& G1 X3 j+-----------+----------+- 2 h* a! L6 }8 n% g+ O
│ % │ root │ ... / Z. |: n' I3 r- w7 X% c
│ % │ jeffrey │ ...
  ~1 I" B4 W" r& S" ?' d- S│ localhost │ root │ ...
( M$ B  s/ p# F3 v3 Z* e│ localhost │ │ ... 3 B4 W0 q/ w1 l" s6 F/ h( @/ `
+-----------+----------+- 4 M. W8 N$ Y  W: b2 ^3 @

; f3 P% B2 W$ J  i# |$ Y7 X5 F* F当服务器在表中读取时,它以最特定的Host值为先的次序排列('%'在 ! h9 [# V. N6 D4 B. E3 b6 ]
Host列里意味着“任何主机”并且是最不特定的)。有相同Host值的条目以
8 I5 l5 Y* B4 y% J! N. i; w最特定的User值为先的次序排列(一个空白User值意味着“任何用户”并且
+ f5 N0 f4 x2 ^3 u2 Y! S是最不特定的)。最终排序的user表看起来像这样:
9 D* c% i0 O( J0 E+ y3 X9 k' U1 a5 h' H2 j; X+ d
/ f) B4 r/ w9 T) j
+-----------+----------+-
; C3 x& H, q8 J3 {( X; `8 S, ?, O│ Host │ User │ ...
9 O$ f% |2 a- t$ e5 l& I+-----------+----------+- 2 n6 Y" }7 m" V4 d4 A& O
│ localhost │ root │ ... # \5 C1 g% W2 X
│ localhost │ │ ... 5 j* s  d. N3 k4 A/ i/ \- e" {% p
│ % │ jeffrey │ ...
! b& B8 U( i7 W" ~6 d│ % │ root │ ... * X% f$ @! z( L2 @* j
+-----------+----------+- 6 r6 E' w6 X+ ^4 I" [0 x' O& E
9 @! y! P( ~& ~3 O' o
当一个连接被尝试时,服务器浏览排序的条目并使用找到的第一个匹
' |. C) i, R/ i/ U2 e# G& T. D  a配。对于由jeffrey从localhost的一个连接,在Host列的'localhost'条目
5 r4 d- U( _8 ^3 ?; D: t首先匹配。那些有空白用户名的条目匹配连接的主机名和用户名。('%'/
. S  I& L. K) b1 G% M$ y+ q'jeffrey'条目也将匹配,但是它不是在表中的第一匹配。)
% Z# Y4 p1 f. ^1 m, \
) x3 P/ _9 ?6 l# m这是另外一个例子。假定user桌子看起来像这样: 3 o& W% `) Y+ A& S3 K

1 t' ?$ i$ h' l; _( X2 ]  ]* C% y! t5 B1 D4 K8 a
+----------------+----------+-
( d( P1 F& w3 O8 D, R" L7 d6 }│ Host │ User │ ... , G5 M' z4 `$ Q  G8 E) q* D) M/ Y
+----------------+----------+- . L$ h( d' x' @, l5 ?( U, z2 N
│ % │ jeffrey │ ... 1 u$ U+ q% X0 ^, g* [
│ thomas.loc.gov │ │ ...
' @: ?1 t. O6 Q* F& a! Q3 m) g: M5 {+----------------+----------+- 1 D$ z( K1 M$ i- K5 m7 g' s, D# Z

2 G2 l) n  Q/ {" e( r7 q7 R& y排序后的表看起来像这样:
- W& w, V) s3 M, q0 y- h3 j  E+ J( H
0 `- A9 s. o/ Y6 }. j+ v: J+ v* y6 S. B2 ^9 W$ K2 w, `7 g+ j
+----------------+----------+- 5 M+ Z! N3 v+ U$ T) Z" Z
│ Host │ User │ ... % P5 _+ ^: V( Z9 c8 ]: A$ e
+----------------+----------+- 9 R6 Z: M; K% v4 F* Z2 F
│ thomas.loc.gov │ │ ...
7 U+ y) f0 y- X3 T' @│ % │ jeffrey │ ... ; t+ u7 x# V: K; E8 c& T( l
+----------------+----------+-
% k0 \) B/ E: O7 d6 ]8 Y( b2 g4 u: A" I, K7 m. q" ~
一个由jeffrey从thomas.loc.gov的连接被第一个条目匹配,而一个由
7 f0 A) S& \3 O: c+ K: _- ^. qjeffrey从whitehouse.gov的连接被第二个匹配。
: j' l/ |9 Y3 r" I2 N) Z  J! p6 e/ [5 ?; |2 Y( L9 _, Y
普遍的误解是认为,对一个给定的用户名,当服务器试图对连接寻找
! ~+ U; q7 @/ G7 |8 y; J匹配时,明确命名那个用户的所有条目将首先被使用。这明显不是事实。
5 @0 ?. Z# E: q( W5 f1 `先前的例子说明了这点,在那里一个由jeffrey从thomas.loc.gov的连接没
  F  l/ o1 p: U+ E1 F9 `9 I- K* W被包含'jeffrey'作为User字段值的条目匹配,但是由没有用户名的题目匹
/ c8 V- K' _* b' ?" y1 O配! , w3 ]& R* O; y8 z9 v# ~

5 d6 r* C: V' c8 w如果你有服务器连接的问题,打印出user表并且手工排序它看看第一个 1 g1 w8 U5 y) Z0 l3 w7 _, f( [
匹配在哪儿进行。
# N7 l  e* o8 w4 v% o' N+ T: |; ~7 X' j/ A) c- W' ]: w
存取控制,阶段2:请求证实
) N# A' ?2 u6 {5 F& I一旦你建立了一个连接,服务器进入阶段2。对在此连接上进来的每个 ; c" T, X* X& Z8 c) A( Q5 h
请求,服务器检查你是否有足够的权限来执行它,它基于你希望执行的操作
8 |/ q, _8 x: C9 L类型。这正是在授权表中的权限字段发挥作用的地方。这些权限可以来子
* u# k% P9 |% n5 Juser、db、host、tables_priv或columns_priv表的任何一个。授权表用
- m4 G6 @7 J' V; RGRANT和REVOKE命令操作。见7.26 GRANT和REVOKE 句法。(你可以发觉参   z; S# F! J+ r
考6.6 权限系统怎样工作很有帮助,它列出了在每个权限表中呈现的字段。) - P8 m* t) U- F6 I2 j
* n. Y% E" j8 N, N  l
user表在一个全局基础上授予赋予你的权限,该权限不管当前的数据库
' c2 {2 Q3 h# F  k9 K0 c! R; ^是什么均适用。例如,如果user表授予你delete权限, 你可以删除在服务器
7 {7 A" W6 G8 c主机上从任何数据库删除行!换句话说,user表权限是超级用户权限。只把
& f) b7 P6 i) Kuser表的权限授予超级用户如服务器或数据库主管是明智的。对其他用户, 3 A6 a: ^- t! @, `" v' O+ k
你应该把在user表中的权限设成'N'并且仅在一个特定数据库的基础上授权,
# C5 \# M" M; t. T/ S3 t使用db和host表。
7 ^( R; o( n! W6 u2 x5 ?
: f1 E2 h6 s* k6 T4 ddb和host表授予数据库特定的权限。在范围字段的值可以如下被指定: . H) P$ S9 C$ ~

( w% J# w1 U" H7 N6 U4 |  B  H( B5 C通配符字符“%”和“_”可被用于两个表的Host和Db字段。
/ E$ f5 I) @( E在db表的'%'Host值意味着“任何主机”,在db表中一个空白Host值意味
- e- [0 W/ c- B9 U4 J/ ~3 I9 r5 ^% |% F( z着“对进一步的信息咨询host表”。
7 s) O- n; T+ M9 N8 ^8 d" V: a在host表的一个'%'或空白Host值意味着“任何主机”。
7 U: V' G6 i1 D* z+ Q/ T7 I在两个表中的一个'%'或空白Db值意味着“任何数据库”。 8 n4 W/ G& I: X6 [! f/ g
在两个表中的一个空白User值匹配匿名用户。   H& b3 U# ~6 k+ P' f
db和host表在服务器启动时被读取和排序(同时它读user表)。db表在Host
( D5 l; m: v+ e1 j、Db和User范围字段上排序,并且host表在Host和Db范围字段上排序。对于 ; E; y; l5 r% h9 o; Y( g  R
user表,排序首先放置最特定的值然后最后最不特定的值,并且当服务器寻找 7 H. {) d7 ~: R3 y
匹配入条目时,它使用它找到的第一个匹配。
7 v0 H3 x; L( F+ O* G% |- ~" Y+ G  f
tables_priv和columns_priv表授予表和列特定的权限。在范围字段的值可
5 p2 i' n3 m: d以如下被指定: 3 |2 I$ Z+ i5 q; H/ K
! u+ t/ I# f5 c' P8 Q( s
通配符“%”和“_”可用在使用在两个表的Host字段。
. f( Q! {2 h, U, B! i# X, O/ C在两个表中的一个'%'或空白Host意味着“任何主机”。
% v' M0 M: G+ I: ]  Z) F2 f5 z在两个表中的Db、Table_name和Column_name字段不能包含通配符或空白。
, ^) _# @$ J: g; j( A1 o2 F- ^tables_priv和columns_priv表在Host、Db和User字段上被排序。这类似于 0 E! R" W5 U1 D  R2 b
db表的排序,尽管因为只有Host字段可以包含通配符,但排序更简单。 * m9 n4 C7 u! g
  L$ F0 O. h( n; x! T
请求证实进程在下面描述。(如果你熟悉存取检查的源代码,你会注意到这
" D$ K- t3 L" w! @里的描述与在代码使用的算法略有不同。描述等价于代码实际做的东西;它只是
, N; e2 S! w4 q1 Y  [# n' D0 b不同于使解释更简单。) ! Z' f8 _. ?" c& g2 h! T  c7 N

$ A: u! [/ V9 w+ p! N% B4 b对管理请求(shutdown、reload等等),服务器仅检查user表条目,因为那是 " K) B$ y- o4 v9 T! R& o
唯一指定管理权限的表。如果条目许可请求的操作,存取被授权了,否则拒绝。
6 S1 t3 m$ n2 A* p+ e, C: X! S& K1 D例如,如果你想要执行mysqladmin shutdown,但是你的user表条目没有为你授 4 s1 p6 K: [/ b+ |9 S0 _2 h
予shutdown权限,存取甚至不用检查db或host表就被拒绝。(因为他们不包含 3 b! r6 w" J+ {" b
Shutdown_priv行列,没有这样做的必要。) & z, K" j4 `% D* W5 v( e8 K7 O

# K5 P8 a- x9 ~& N! d  r5 b对数据库有关的请求(insert、update等等),服务器首先通过查找user表 8 M# Z% o* J* \+ `; I
条目来检查用户的全局(超级用户)权限。如果条目允许请求的操作,存取被授
. }9 P3 T+ s3 Z  n+ Q权。如果在user表中全局权限不够,服务器通过检查db和host表确定特定的用
! W  K  {$ a8 t+ G( |$ ]7 e; U户数据库权限:
# o2 X6 l) |8 ^5 F+ H, d# Y# z# Y; T) u# ~
服务器在db表的Host、Db和User字段上查找一个匹配。 Host和User对应连 0 C7 h7 k7 r( ^9 {" h
接用户的主机名和MySQL用户名。Db字段对应用户想要存取的数据库。如果没有 ( e% A; ]" A' Q! j5 l
Host和User的条目,存取被拒绝。
8 R$ O0 A, o5 T& \6 |5 r% f如果db表中的条目有一个匹配而且它的Host字段不是空白的,该条目定义用 7 y& P- A' i& m9 B
户的数据库特定的权限。 6 F) G' ]3 K0 h1 Q2 F- @. p8 o
如果匹配的db表的条目的Host字段是空白的,它表示host表列举主机应该被
* ?- W9 a  Z1 L, j9 e" v允许存取数据库的主机。在这种情况下,在host表中作进一步查找以发现Host和 + _/ P- R6 _0 u! w& j; d
Db字段上的匹配。如果没有host表条目匹配,存取被拒绝。如果有匹配,用户数 + b$ r) s' p; S7 Y$ R9 o1 D
据库特定的权限以在db和host表的条目的权限,即在两个条目都是'Y'的权限的交
# O! u+ g, D$ g9 i- Q1 E- p' D集(而不是并集!)计算。(这样你可以授予在db表条目中的一般权限,然后用host # H" U2 Q8 g5 x5 c& ~! F
表条目按一个主机一个主机为基础地有选择地限制它们。)
( n( q, E( z3 L) @2 h) u& r& O在确定了由db和host表条目授予的数据库特定的权限后,服务器把他们加到
! C" P5 w, f5 M5 i3 L/ r: ?由user表授予的全局权限中。如果结果允许请求的操作,存取被授权。否则,服 & Q+ {  m0 L) @' k  @8 {
务器检查在tables_priv和columns_priv表中的用户的表和列权限并把它们加到
9 @0 U) J7 h* c5 n用户权限中。基于此结果允许或拒绝存取。
& D! Y+ \7 {! j0 O9 v
4 ~! |0 G" X' t( ]% m4 q$ S5 w用布尔术语表示,前面关于一个用户权限如何计算的描述可以这样总结: , ]8 p; J/ }: g
+ g& M; ?4 e( ^% ]( f
global privileges ' z" @0 t" w( y% W& q! H; S2 g
OR (database privileges AND host privileges)
# Y8 Z; y8 X- \2 L" gOR table privileges
' h2 z0 O2 @+ \6 dOR column privileges
# I/ ~6 j, k7 ?4 D
: g( N2 w- w" h  P4 d它可能不明显,为什么呢,如果全局user条目的权限最初发现对请求的操作不 7 Q- V$ C' E! ?( x
够,服务器以后把这些权限加到数据库、表和列的特定权限。原因是一个请求可能
, O+ I" `- }1 v* Z7 z# q2 U" S要求超过一种类型的权限。例如,如果你执行一个INSERT ... SELECT语句,你就都
) A) I5 K0 ^. Z4 k" ]要insert和select权限。你的权限必须如此以便user表条目授予一个权限而db表条 $ |6 _" Y% a/ x( c! P3 u6 ?
目授予另一个。在这种情况下,你有必要的权限执行请求,但是服务器不能自己把
) N* ^: e9 @  p; y/ m5 A两个表区别开来;两个条目授予的权限必须组合起来。
' A/ q: p. L$ R" ?
4 v( s% S. u5 e" bhost表能被用来维护一个“安全”服务器列表。在TcX,host表包含一个在本
3 x+ ]  K. m* k  A) ~) }/ l3 a/ B$ i地的网络上所有的机器的表,这些被授予所有的权限。 7 D; g, a3 a9 r7 G9 _8 \
8 v( A! F1 K" N' R" t% ^1 |
你也可以使用host表指定不安全的主机。假定你有一台机器public.your.
0 b* F, A1 J6 k3 T+ {domain,它位于你不认为是安全的一个公共区域,你可以用下列的host表条目子允 ; K2 H6 b' N+ p. n$ D  R
许除了那台机器外的网络上所有主机的存取: 2 a9 j9 `0 {, E8 p/ D4 v& [9 E: X

, t% `$ h8 `& d) ]4 q0 ?" H# w, H) i- F* c/ _; ~. r, O# v% H1 D1 H
+--------------------+----+-
( n' z' P' A! Y( j  f& |│ Host │ Db │ ...
8 k/ P) Y  j- ^& i4 I+--------------------+----+- ; e# Z5 d6 W* m% E
│ public.your.domain │ % │ ... (所有权限设为 'N') ( n! Z3 x. M4 X2 l1 Z" A
│ %.your.domain │ % │ ... (所有权限设为 'Y')
* Q6 }, Y* y& I8 Z+--------------------+----+- 4 T; b1 p7 b9 k# D

5 p8 O, u$ Q+ k当然,你应该总是测试你在授权表中的条目(例如,使用mysqlaccess)让你确保
7 b- x0 E& f1 r+ h你的存取权限实际上以你认为的方式被设置。
$ T& F+ |& c4 \3 k/ s' s" [8 T" G. Y- Y" U9 [. f, L6 U0 Y4 i
权限更改何时生效
! @! ?& |# t' \( N当mysqld启动时,所有的授权表内容被读进存储器并且从那点生效。 . }$ `1 A0 d7 p0 J4 A# f( b4 z

2 \9 k+ m$ U' u& ^9 F- \: j! D用GRANT、REVOKE或SET PASSWORD对授权表施行的修改会立即被服务器注意到。
$ V. Q' _- _6 i8 W& w
5 A$ R$ S) O9 Y6 w1 B0 e( k如果你手工地修改授权表(使用INSERT、UPDATE等等),你应该执行一个FLUSH ) J6 T: D  X2 [; g( E  y
PRIVILEGES语句或运行mysqladmin flush-privileges告诉服务器再装载授权表,否
" y; G  g9 Z: ]' t  ^" A则你的改变将不生效,除非你重启服务器。 2 R: F" Z) r  f( C; d

, r) X+ c( a; `当服务器注意到授权表被改变了时,现存的客户连接有如下影响:
* _& n; k4 i, t' ~3 g& m9 u- ?* \6 \6 E
表和列权限在客户的下一次请求时生效。 8 x' T* d( x# `) [: O8 Q( X
数据库权限改变在下一个USE db_name命令生效。 - w$ B- [% e: t  H
全局权限的改变和口令改变在下一次客户连接时生效。
# D7 o/ z* ]8 U; _0 f3 l
% k; p. u6 j2 d! y& d建立初始的MySQL权限 % V( u9 ~$ p0 d6 T6 o
在安装MySQL后,你通过运行scripts/mysql_install_db安装初始的存取权限。 , T2 [- c. k, W7 b" i* o
scripts/mysql_install_db脚本启动mysqld服务器,然后初始化授权表,包含下列
) f1 j7 b' Q7 s权限集合: ' y1 I4 M0 h, j. \

$ \. l9 a1 d. q( rMySQL root用户作为可做任何事情的一个超级用户被创造。连接必须由本地主 7 }0 C* ^- u1 t: L+ c- z1 R
机发出。注意:出世的root口令是空的,因此任何人能以root而没有一个口令进行 7 u7 @& N0 |. W, O: F+ j! N
连接并且被授予所有权限。 / v) j- g1 @5 t" F: G
一个匿名用户被创造,他可对有一个'test'或以'test_'开始的名字的数据库
: h) d: R) h( h7 Q( n% S做任何时期事情,连接必须由本地主机发出。这意味着任何本地用户能连接并且视
+ o$ A2 s, E: E8 V为匿名用户。
% d4 J' r6 k/ J, i其他权限被拒绝。例如,一般用户不能使用mysqladmin shutdown或 # r3 g6 B' I9 z6 d9 U
mysqladmin processlist。
' U& t& V3 _$ [' T注意:对Win32的初始权限是不同的。 * L' T7 b- e$ G3 ?" \" Y
; O7 k% _1 M2 [  o$ b) g5 b
既然你的安装初始时广开大门,你首先应该做的事情之一是为MySQL root用户 $ f' z- x! V; w8 A* |
指定一个口令。你可以做如下(注意,你使用PASSWORD()函数指定口令): . J  Z5 Y3 @8 F9 n# L3 D

4 C, u, u& `: E* t/ [+ ]* ]shell> mysql -u root mysql 9 u  {" w0 m) K
mysql> UPDATE user SET Password=PASSWORD('new_password') - t% _9 t+ l7 Y1 c9 [
WHERE user='root'; 0 Y1 F& E* K/ l  y
mysql> FLUSH PRIVILEGES; " ^! d& C# R, t& R- k
' ?( `) ^7 Q7 A! c) J3 @
在MySQL 3.22和以上版本中,你可以使用SET PASSWORD语句:
9 N$ j  q) I9 G( d
+ H7 O/ `8 y  C8 r) Fshell> mysql -u root mysql
# _: [! ~0 g5 X4 v6 r9 [$ N9 Zmysql> SET PASSWORD FOR root=PASSWORD('new_password'); 8 b$ |( q0 V1 c1 G8 n5 F- H3 J
! s1 ~' V- n$ h* K. |
设置口令的另一种方法是使用mysqladmin命令:
6 w. u9 R- y6 T6 y
# Q8 S$ m- K6 b7 Dshell> mysqladmin -u root password new_password $ q4 H; ^! ^6 X5 T3 o

' G" m' Z3 c8 q7 C3 _5 L# J' C注意:如果你使用第一种方法在user表里直接更新口令,你必须告诉服务器
9 U/ ^( h$ c. o$ T0 E再次读入授权表(用FLUSH PRIVILEGES),因为否则改变将不被注意到。
' G+ Y. I$ `8 \! D
$ B6 F  _. [  D4 [一旦root口令被设置,此后当你作为root与服务器连接时,你必须供应那个
- j# T5 F/ i, }) J口令。
* z: ~2 o6 \3 ~  D# ]" A
: {, w( R2 _0 _, f你可能希望让root口令为空白以便当你施行附加的安装时,你不需要指定它
2 O  w/ b/ S5 ?# R3 g或测试,但是保证在任何真实的生产工作中使用你的安装之前,设置它。 $ J4 l6 D: Q8 u8 S# J

  v" m! V( y/ ]. r看看scripts/mysql_install_db脚本,看它如何安装缺省的权限。你可用它
  E9 Y. Q+ T+ h3 y5 C3 G0 G作为一个研究如何增加其他用户的基础。 ( Q' _3 X0 E4 b+ W

! N- {/ G$ d8 W# t! r5 B0 ^如果你想要初始的权限不同于上面描述的那些,在你运行mysql_install_db
1 w, X8 n9 t0 f7 h" g之前,你可以修改它。
: @4 A8 w1 g+ N4 P. c) A% t
9 I6 k6 H' Z/ Y  S1 O' }) Q; W为了完全重建权限表,删除在包含mysql数据库的目录下所有“*.frm”, ' D* l+ i% o# q5 F
“*.MYI”和“*.MYD”文件。(这是在数据库目录下面命名为“mysql”的目录, 0 W3 y7 D" ]% v* v, |7 ^
当你运行mysqld --help时,它被列出。)然后运行mysql_install_db脚本,可能
  f" z6 Q' G# I在首先编辑它拥有你想要的权限之后。
* I: j" b. W) Q1 f) m1 l6 c
; v% F3 C0 w% z$ k( P! a注意:对于比MySQL 3.22.10旧的版本,你不应该删除“*.frm”文件。如果 & h$ N/ `4 X; U$ Q3 P6 i2 a) C3 h
你偶然做了,你应该在运行mysql_install_db之前你的MySQL分发中拷回它们。 ' o" Q+ U- t7 e& j6 x  e. S
5 ^, A/ `% l- [4 o5 y
向MySQL增加新用户权限
: [  [) u4 X1 w  }3 ]& r' c* b你可以有2个不同的方法增加用户:通过使用GRANT语句或通过直接操作MySQL授
6 D; y. }+ F6 G4 ^: {; U# J权表。比较好的方法是使用GRANT语句,因为他们是更简明并且好像错误少些。 * f" ^# }6 T& Q& @: Q
2 u& |- t8 _9 j6 Q$ a7 ^) m
下面的例子显示出如何使用mysql客户安装新用户。这些例子假定权限根据以前
$ f4 y  T  V" ^的章节描述的缺省被安装。这意味着为了改变,你必须在mysqld正在运行同一台
/ r2 b- T& e  e7 [/ _# b- [机器上,你必须作为MySQL root用户连接,并且root用户必须对mysql数据库有
  b! d5 ]- l1 u6 @insert权限和reload管理权限。另外,如果你改变了root用户口令,你必须如下 & z7 q4 Y6 F+ O! ^
的mysql命令指定它。 $ k$ P& H7 c# D, I' W7 R+ I
+ m! Z+ `8 b  U3 {+ W
你可以通过发出GRANT语句增加新用户:
6 t+ |1 a4 `2 f( a8 l
) ^: D1 c# P' r* m8 T; vshell> mysql --user=root mysql
) f1 P  {2 M* `8 ?8 emysql> GRANT ALL PRIVILEGES ON *.* TO monty@localhost
8 S; J' x6 t/ \( t& Z2 QIDENTIFIED BY 'something' WITH GRANT OPTION;
/ a1 W" v, O6 y$ }! p+ smysql> GRANT ALL PRIVILEGES ON *.* TO monty@"%"
) }+ @. l- K. [6 p, }IDENTIFIED BY 'something' WITH GRANT OPTION;
: W; |& B% G* U$ q/ Umysql> GRANT RELOAD,PROCESS ON *.* TO admin@localhost; 6 B2 i5 b+ k# |6 l  h) l
mysql> GRANT USAGE ON *.* TO dummy@localhost;
% n( R0 V+ X1 K" E7 t! N
: ?8 \4 d+ O6 K8 S* o; f这些GRANT语句安装3个新用户:
9 z" t3 f$ _5 p; q1 p/ E8 g( M9 |# n  J+ C- t) W
monty
$ d$ g& \' h; g$ _可以从任何地方连接服务器的一个完全的超级用户,但是必须使用一个 3 v2 Q1 i  e1 r5 r* E3 U
口令('something'做这个。注意,我们必须对monty@localhost和monty@"%"
: W# P+ S# z3 p1 y$ F' c- P6 s发出GRANT语句。如果我们增加localhost条目,对localhost的匿名用户条目 8 [" I4 B1 `9 t8 ~& P* r
在我们从本地主机连接接时由mysql_install_db创建的条目将优先考虑,因为
1 G" |! y0 X8 B- t它有更特定的Host字段值,所以以user表排列顺序看更早到来。 6 N  |, u+ @) F  Q. r3 [; t( v
admin
: Y, [9 x1 Z) t- Q可以从localhost没有一个口令进行连接并且被授予reload和process管理 " n2 X: x6 A) ^  M) @
权限的用户。这允许用户执行mysqladmin reload、mysqladmin refresh和
2 W& L. K# E5 j" emysqladmin flush-*命令,还有mysqladmin processlist。没有授予数据库有 " u8 g3 q5 y" N4 Z6 J1 i; ?
关的权限。他们能在以后通过发出另一个GRANT语句授权。
, d, w- A" Z% ldummy , Z& O3 @& o, t) d6 P& k& `8 s
可以不用一个口令连接的一个用户,但是只能从本地主机。全局权限被设
8 Z- Z: P& z, A. L5 A" L1 e置为'N'--USAGE权限类型允许你无需权限就可设置一个用户。它假定你将在以 / q/ f1 d  A" b: h7 W" W
后授予数据库相关的权限。
4 R, y* I/ D! a, l8 J; ~7 X你也可以直接通过发出INSERT语句增加同样的用户存取信息,然后告诉服
- q: d, v1 O' d1 R1 @务器再次装入授权表:
. C6 x. C3 E2 X$ j% [2 Q6 [  [
9 E* s+ T# u8 p! [shell> mysql --user=root mysql
6 A6 z& X5 E6 v( p8 ~/ r3 d% b) _mysql> INSERT INTO user VALUES('localhost','monty',PASSWORD
& v/ L3 ?5 h! H, U* A& l' T* C('something'), 0 v% Z9 W1 n$ F9 O( @
'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y',
% j% l$ O/ h  }! @* g'Y','Y')
/ r: g9 U) H! `4 C' rmysql> INSERT INTO user VALUES('%','monty',PASSWORD('something'), 0 J7 Q3 A' l: v' b, }
'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y', ' O. G8 J1 c6 b* T
'Y')
1 o' H9 C0 g. S: L/ \9 q( h. ^mysql> INSERT INTO user SET Host='localhost',User='admin', / E4 o+ E, N9 g; }
Reload_priv='Y', Process_priv='Y'; ( D) ^8 G7 H; U' @" d
mysql> INSERT INTO user (Host,User,Password)
6 m8 V* r. H3 o6 N. j0 UVALUES('localhost','dummy',''); " K. Q2 c! B/ o5 i) x
mysql> FLUSH PRIVILEGES;
* h" R# l- l9 r% b' B5 _7 L3 a. B0 Q2 q5 `" |
取决于你的MySQL版本,对上述,你可能必须使用一个不同数目'Y'值(在
0 ?3 t( R5 _/ h- E6 g( m3.22.11以前的版本有更少的权限列)。对admin用户,只用在3.22.11开始的版
. E: D! S% ^2 b3 i, h& h本具有的更加可读的INSERT扩充的语法。
5 S- F$ i3 r# m. ]' H1 z" S" `/ z9 v' [5 [( \+ ^
注意,为了设置一个超级用户,你只需创造一个user表条目,其权限字段设为 8 P# o+ O8 p. M) d: H3 l
'Y'。不需要db或host表的条目。
. U7 L* E4 e/ Q4 a2 t# G# E3 b2 c7 P7 E1 e* z
在user表中的权限列不是由最后一个INSERT语句明确设置的(对dummy用户),
, R: W. M* p2 K0 ^+ q8 o( u因此那些列被赋予缺省值'N'。这是GRANT USAGE做的同样的事情。
6 s2 g: Z2 [. u  e3 r' @
8 j7 B/ \" ^( F: A0 T# U, N下列例子增加一个用户custom,他能从主机localhost、server.domain和
! A8 Y1 Q: M- o7 f  z5 Lwhitehouse.gov连接。他只想要从localhost存取bankaccount数据库,从
* M4 |: D4 K- k- cwhitehouse.gov存取expenses数据库和从所有3台主机存取customer数据库。他
4 u0 {! k3 Y$ L; V1 ~想要从所有3台主机上使用口令stupid。
' e) q& t% A) j2 r- R: f( v# O- f6 |5 F$ L/ K' u
为了使用GRANT语句设置个用户的权限,运行这些命令:
7 L' N6 H; m1 y/ K5 w+ |: _, ~: a, E" H2 \
shell> mysql --user=root mysql 6 M8 G  y1 z4 N4 V+ U
mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP ) Z, a5 @; p  D" r& z5 {# j' ^! ^
ON bankaccount.* 0 V* h# g3 R/ H/ P; z
TO custom@localhost ! T+ h9 ^$ M3 X9 y5 O
IDENTIFIED BY 'stupid';
, G% ]! e5 Z8 s' Fmysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP * S. s& f5 h, u. f) L0 E
ON expenses.*
9 X6 W5 d; y6 x1 p8 Y: {2 c8 H. LTO custom@whitehouse.gov 3 I3 x3 z7 F" [, X
IDENTIFIED BY 'stupid';
+ e1 |+ e5 U6 Pmysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
# E9 {3 Q% _( }8 t; pON customer.*
# v6 h6 @- v0 O. T, T; V# STO custom@'%'
4 F- I5 G3 f, V/ A8 UIDENTIFIED BY 'stupid'; 4 O; c' [- N! E, ~* W
" k$ j+ G" G' o! c
通过直接修改授权表设置用户权限,运行这些命令(注意,在结束时
$ A1 g2 T6 {' s" wFLUSH PRIVILEGES): ' K) ]! k: e* Z; r7 X8 L

3 o8 J, d0 I) Dshell> mysql --user=root mysql ! b" z. ?  R6 x5 X4 i! I
mysql> INSERT INTO user (Host,User,Password)
9 J1 c  |" C: Z( C) lVALUES('localhost','custom',PASSWORD('stupid'));
8 b* o- r/ H* ~5 J7 Y" g6 Q% y- O/ Ymysql> INSERT INTO user (Host,User,Password)
0 i$ b& m; \0 ]! c0 zVALUES('server.domain','custom',PASSWORD('stupid')); 8 N. T- w) K0 a6 W0 D
mysql> INSERT INTO user (Host,User,Password) 1 x! n/ U/ q& C7 c% D" @: E
VALUES('whitehouse.gov','custom',PASSWORD('stupid')); $ o; U$ D0 d- A2 p6 q/ b* Q
mysql> INSERT INTO db
& z& h) K8 e& S  A, n8 ?, `(Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv,
2 q5 D+ @! z0 k5 z1 ]Create_priv,Drop_priv)
* l- B9 R, n- \+ i3 `% RVALUES 8 i) V  f" c% F; }9 t
('localhost','bankaccount','custom','Y','Y','Y','Y','Y','Y'); ' s4 @" g$ K7 m, ^% W. P
mysql> INSERT INTO db " b$ q2 w! _: x& Y
(Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv, / \2 m% d4 X! S; U# A  _: C
Create_priv,Drop_priv) " j" e! u( u2 X8 L/ W& g1 P
VALUES
  x( @5 R3 O" ]# w: c' O; |& p: r('whitehouse.gov','expenses','custom','Y','Y','Y','Y','Y','Y');
7 B7 `5 _. A3 q8 Y: V' c( Emysql> INSERT INTO db
/ x6 U6 |/ n" n% L* R(Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv,
3 {0 U0 w  k7 m- s& dCreate_priv,Drop_priv)
' z6 v+ j; [6 d* K- o/ {' u: GVALUES('%','customer','custom','Y','Y','Y','Y','Y','Y');
3 Z& z. Z8 B/ r/ m' c3 \# z$ I' j- mmysql> FLUSH PRIVILEGES;
- f, Z5 i1 M( [* T) F5 B% K
7 \5 ^( K& A: \* N5 y头3个INSERT语句增加user表条目,允许用户custom用给定口令从不同的主机 ) n. S/ [6 y; r
进行连接,但是没有授予任何许可(所有权限被设置为缺省值'N')。后3个INSERT ! k: Y6 r& w( b, y% X' i
语句增加db表条目,授予custom以bankaccount、expenses和customer数据库权限,
) A6 B% w; L8 ~9 h2 C' X6 _但是只能在从正确的主机存取时。通常,在授权表直接被修改时,服务器必须被告 , }9 W& V$ M  f- k- a4 f# U" U
知再次装入他们(用FLUSH PRIVILEGES)以便使权限修改生效。 5 e2 K6 l' Z  y6 P% B& M2 h6 q

! p4 v  @4 A) M! i. q0 V8 q. w6 Z" o如果你想要给特定的用户从一个给定的域上的任何机器上存取权限,你可以发
3 S+ T. K9 G. S1 z: u: B出一个如下的GRANT语句: " y0 ^' B% a0 J
, [8 h' S9 e0 p
mysql> GRANT ...
7 n5 U$ [1 `, Q, a6 yON *.* # t6 P" N: ^7 [. Z" E
TO myusername@"%.mydomainname.com" ' p* h* A& q* O1 g- }- l9 @
IDENTIFIED BY 'mypassword';
# M: Y4 V* @: T. L, l/ i# ?/ A9 c! q+ K9 x8 x
为了通过直接修改授权表做同样的事情,这样做: ; _6 N( c# x( V7 J. J: s

1 k9 a, x" j# e( T1 P0 @# e" |mysql> INSERT INTO user VALUES ('%.mydomainname.com', 'myusername', 6 O3 z' B4 t8 W  P
PASSWORD('mypassword'),...); ( _  E- ~# N5 D) b( P
mysql> FLUSH PRIVILEGES; ) V4 X* b2 E) w, u& u

. W. b$ e# R" M' _: z4 p你也可以使用xmysqladmin、mysql_webadmin甚至xmysql在授权表中插入、改变 ; ~- Q# U* x* }$ p' V
和更新值。你可以在MySQL的Contrib目录找到这些实用程序。 - [) [( H% F0 ~: ]
& E" @& e  ~8 s" [/ C& ^
怎样设置口令
2 l& S4 ?' G9 d6 q! p6 S6 H( n在前面小节的例子里说明了一个重要的原则:当你使用INSERT或UPDATE语句存
# l# e: u& \: e# z储一个非空的口令时,你必须使用PASSWORD()函数加密它。这是因为在user表中以 # J( D. b4 T( A& \* @5 \
加密形式存储口令,而不是作为纯文本。如果你忘记这个事实,你可能像这样试图 ! b; s3 }' \. I0 A
设置口令: ' G$ }( ]) Q! T3 W4 A$ Q- p# ?
2 W9 h$ G3 h8 i( o& m* }
shell> mysql -u root mysql
. V# K4 ^, e8 t% [- Amysql> INSERT INTO user (Host,User,Password) VALUES('%','jeffrey',
4 q; H! r3 Q: @$ g5 s! |) V& ^'biscuit');
% e- c1 p, K  @( w% L! u* B  L7 \mysql> FLUSH PRIVILEGES
, f2 q1 I- X. V/ x: G- X
2 \5 c2 W# ]5 x% I结果是纯文本值'biscuit'作为口令被存储在user表中。在用户jeffrey试图用 ! V! M' @! Q% E/ W4 }
这个口令连接服务器时,mysql客户用PASSWORD()加密它并且将结果送给服务器,服 & G1 j& C1 K. `$ k. z) r; s$ U
务器比较在user表中的值(它是纯文本值'biscuit')和加密的口令(而不是 * P2 v% o/ j7 V+ ~# O
'biscuit'),比较失败并且服务器拒绝连接:
* p  u) K( l0 z2 L$ I' o. |3 R, f
! o& L1 W2 V/ [8 C5 jshell> mysql -u jeffrey -pbiscuit test
* N; F$ J7 u( XAccess denied
, u# f8 B* J0 @- d; r2 }
8 i0 V9 z+ W4 ^$ c% |( {* ?因为当他们被插入user表时,口令必须被加密,相反,INSERT语句应该象这样
5 T1 J& ~5 s5 A/ C! Z: a3 H9 A! G被指定: * w% d* g* I# O  W# w) [. Y' }

" d0 ~  k5 S( ?1 z4 Smysql> INSERT INTO user (Host,User,Password)
9 `% S6 m( h( F1 P$ M5 M# g* LVALUES('%','jeffrey',PASSWORD('biscuit'));
( x! }+ o6 Q( a( w$ `. X% E2 l) a, |1 {# E
- R. g  P3 }6 @4 L5 V. t当你使用SET PASSWORD语句时,你也必须使用PASSWORD()函数:
+ d% v5 T4 C" L/ ]
2 e6 n% P6 R" u. W/ Amysql> SET PASSWORD FOR jeffrey@"%" = PASSWORD('biscuit');
, U) J& v% t& i- t1 {9 T/ L' H% ^& L+ p6 j4 C5 ~
如果你使用GRANT ... IDENTIFIED BY语句或mysqladmin password命令设置口
8 g% {+ x: \0 c, |令,PASSWORD()函数是不必要的。他们都考虑到为你加密口令,多以你可像这样指
# p0 P7 s. y1 w4 }定一个口令'biscuit':
' j0 B6 h' M" m( U2 j1 S% B- a! d1 a. y, u# j$ V
mysql> GRANT USAGE ON *.* TO jeffrey@"%" IDENTIFIED BY 'biscuit';
% ~' M/ E' `/ T' A) e' |8 p1 G+ B- e% V+ V

, G3 A9 J4 c& U. ^4 s. J" j4 k, z9 o5 Q) U; d! B0 V6 K8 d
shell> mysqladmin -u jeffrey password biscuit ! r. G8 G- p6 Q; W
注意: PASSWORD()不是以在Unix口令加密的同样方法施行口令加密。你不应
, f# C6 e" l) R. X( z该假定如果你的Unix口令和你的MySQL口令是一样的,PASSWORD()将导致与在Unix ( q' M; N- H3 S( G* V" h' E
口令文件被存储的同样的加密值。见6.2 MySQL 用户名和口令。
' C7 g1 `7 U) D/ Y3 c7 l# L# F7 \
Access denied错误的原因 2 M! @# I4 e; }# _  b5 I, ]
当你试着联接MySQL服务器时,如果你碰到Access denied错误,显示在下面
5 W  V5 d  x- O+ f的表指出一些你能用来更正这个问题的动作:
' K7 @" p3 {0 b( Z" G) }
3 U0 @: _1 Y$ X3 ^; |0 M8 m# F/ s" B) d你是在安装MySQL以后运行mysql_install_db的脚本,来设置初始授权表内容 : x+ n+ C6 K; d' y8 C
吗?如果不是,这样做。见6.10 设置初始MySQL权限。通过执行这个命令测试初
' \% s; U: Z( L1 i始权限:   P+ b# P. t$ y. \8 c
shell> mysql -u root test
2 t+ Y3 @$ y( M2 V, q5 Q7 Y2 Q0 K# d: \9 G, F* k9 }7 a+ I
服务器应该让你无误地连接。你也应该保证你在MySQL数据库目录有一个文件 : Y; p% o: i/ W' n: W7 l
“user.MYD”。通常,它是“PATH/var/mysql/user.MYD”,在此PATH是MySQL安
/ T* V: n: ]  p4 p装根目录的路径。
; F- W' ~  r) @, z4 q; n, A
" K. Y2 J3 A5 Y% l在一个新的安装以后,你应该连接服务器并且设置你的用户及其存取许可:
# a( O- c7 F, z; ^$ @3 oshell> mysql -u root mysql
7 v6 j+ W) y/ g- A2 G" H; X2 P! v4 I8 L3 Z6 `9 Q
服务器应该让你连接,因为MySQL root用户初始时没有口令。既然那也是一个
2 i: N4 `* m0 X3 n安全风险,当你正在设置其他MySQL用户时,设定root口令是一件重要的事请。如
& k+ z$ Z* i  z+ l果你作为root尝试连接并且得到这个错误: , w% v5 x; [9 Y+ j( N8 V2 |
) E9 M7 d1 w: X1 d
Access denied for user: '@unknown' to database mysql
9 R7 K3 d9 s5 ?. P. c+ H, a5 X, D9 Q0 P- G
这意味着,你没有一个条目在user表中的一个User列值为'root'并且mysqld 9 A- t. `# `' y5 ?7 Z( b
不能为你的客库解析主机名。在这种情况下,你必须用--skip-grant-tables选项 ' }# C; g0 e7 l# J
重启服务器并且编辑你的“/etc/hosts”或“\windows\hosts”文件为你的主机
* P/ O4 [/ n& j# \' k& ?增加一个条目。
& N" v+ r( x; H$ t* [5 R' P& k/ I
如果你从一个3.22.11以前的版本更新一个现存的MySQL安装到3.22.11版或以 0 K$ Q. n& x$ p
后版本,你运行了mysql_fix_privilege_tables脚本吗?如果没有,运行它。在 - U& h' g4 ~7 X* u7 \
GRANT语句变得能工作时,授权表的结构用MySQL 3.22.11修改 。 $ A& R$ S! k0 ^6 _
如果你直接对授权表做修改(使用INSERT或UPDATE语句)并且你的改变似乎被 9 }: f. T' S: G$ T- t+ e9 c
忽略,记住,你必须发出一个FLUSH PRIVILEGES语句或执行一个mysqladmin
& R( h, V. {' K" M# ^flush-privileges命令导致服务器再次读入表,否则你的改变要道下一次服务器被
% s' p5 b) e1 f0 M4 ~/ i  k重启时再生效。记住在你设定root口令以后,你将不需要指定它,直到在你清洗
7 P8 Q  h  c# D- }" X' F  Q' s3 K(flush)权限以后,因为服务器仍然不会知道你改变了口令!
  w/ n& c2 A+ {  l3 m' U如果你的权限似乎在一个会话(session)当中改变了,可能是一个超级用户改变
: y8 l2 ?. G2 s" c; ?了他们。再次装入授权表作用于新客户连接,但是它也影响现存的连接,如6.9 权
5 V! `0 r4 o" ?7 P限改变何时生效小节所述。 8 z, P" g3 B9 B9 f2 R% S
为了测试,用--skip-grant-tables选项启动mysqld守护进程,然后你可以改变 ; h6 W1 m3 O' S9 y. L' G$ \) M
MySQL授权表并且使用mysqlaccess脚本检查你的修改是否有如期的效果。当你对你的 9 n2 a) t5 `5 @6 c% u3 f6 P
改变满意时,执行mysqladmin flush-privileges告诉mysqld服务器开始使用新的权 3 H! V! Q- u6 b/ T& a
限表。注意:再次装入授权表覆盖了--skip-grant-tables选项。这允许你告诉服务 8 m/ u$ x2 C" e, `6 w$ d8 i) {/ {1 Y
器开始使用授权表,而不用停掉并重启它。 - K) x  U& Y/ D7 e* D! l) F
如果你有一个Perl、Python或ODBC程序的存取问题,试着用mysql -u user_name $ v( e* E- b" w
db_name或mysql -u user_name -pyour_pass db_name与服务器连接。如果你能用 , t) L' l8 U% |( J; M2 P: t
mysql客户连接,这是你程序的一个问题而不是存取权限的问题。(注意在-p和口令
7 Y" p3 N+ Y7 [2 k" q之间没有空格;你也能使用--password=your_pass句法指定口令。)
+ f' ?- T7 H$ T9 t如果你不能让口令工作,记得如果你用INSERT, UPDATE或SET PASSWORD语句 * R( z' K9 ^1 {6 v9 T6 [, {1 k2 z
设置口令,你必须使用PASSWORD()函数。如果你用GRANT ... INDENTIFIED BY语
3 U- |) _, p) {) s+ U* o# \. E0 U句或mysqladmin password命令指定口令,PASSWORD()函数是不需要的。 * `8 _( a$ l3 R
localhost是你本地主机名的一个同义词,并且也是如果你不明确地指定主机 - E2 r- E# x0 [+ E  u( ?! o" F* F6 e
而客户尝试连接的缺省主机。然而,如果你正在运行于一个使用MIT-pthreads的系
4 m; J  Y+ P$ p; |# Z统上,连接localhost是不行的(localhost连接使用Unix套接字进行,它没被 MIT 0 |6 @" D& \; O# _( S( q
-pthreads支持),为了在这样的系统上避免这个问题,你应该使用--host选项明确 6 \- h7 x* N$ ~
地命名服务器主机,这将做一个 TCP/IP连接到mysqld服务器。在这种情况下,你 . s* D9 @# e1 e9 g1 s" a
必须有在服务器主机上的user表中条目的你真实的主机名。(即使你在服务器同一
/ G' f0 i+ l' y3 F0 e0 `8 l! z7 |台的主机上运行一个客户程序,这也是真的。) 9 d4 F) C% O4 X& b
当尝试用mysql -u user_name db_name与数据库连接时,如果你得到一个 ) v& U$ ]/ R. D. u
Access denied错误,你可能有与user桌有关的问题,通过执行mysql -u root * l. X0 H6 I1 K! R5 M1 k; M3 @, u$ k
mysql并且发出下面的SQL语句检查: # v) @/ y# b. l) B8 U' b1 I
mysql> SELECT * FROM user;
/ b8 L2 Z" b6 {) Y. v( M7 g7 a: T: r1 W- d- k. Y, K
结果应该包含一个有Host和User列的条目匹配你的计算机主机名和你的MySQL用户
/ B2 G4 p$ E( U- j名。 8 x4 x% v2 P8 `; K; x. _
) b% j# h' i( B) A6 O- M
Access denied错误消息将告诉你,你正在用哪个用户尝试登录,你正在试图
+ z7 ~1 A- G. G1 B# f6 n用连接哪个主机,并且你是否正在使用一个口令。通常,你应该在user表中有一 1 G+ G( v/ {5 F* w0 ~
个条目,正确地匹配在错误消息给出的主机名和用户名。 * H" d5 l7 M0 v" B. ?4 U4 j
如果当你试着从一个不是MySQL服务器正在运行的主机上连接时,你得到下列 0 I* `1 q8 R0 i8 ^- X( M2 r1 u
错误,那么在user表中没有匹配那台主机行: + {( i8 c( X& x: S4 }
Host ... is not allowed to connect to this MySQL server
4 R! T( Q2 K6 y/ M, F3 D! H( C* i3 Z' f, \3 d1 ]& H; b
你可以通过使用mysql命令行工具(在服务器主机上!)修正它,把你正在试
% |8 B! i8 S) U3 K0 g图连接的用户/主机名组合新加一行到user表中。如果你不在运行MySQL 3.22并且
! R# K7 r: m9 n你不知道你正在从它连接的机器的IP数字或主机名,你应该把一个'%'条目作为
3 T  o& [0 w: |( x! B' ]8 y. UHost列值放在user表中并且在服务器机器上使用--log选项重启mysqld。在试图从
" N& v' i2 j* D( Y) G5 m客户机器连接以后,在MySQL记录文件中的信息将显示你如何真正进行连接。(
4 ^( n: @1 g3 r. q$ e/ ?+ |: y然后用在记录文件上面显示出的实际的主机名代替user表中的'%'条目。否则,
4 f) ~- t! w! W; N* A" J5 G1 y( C你将有一个不安全的系统。)
1 i$ ]4 V3 C. o6 a3 @9 l5 t! x9 [0 z3 M, T2 S+ ?  p4 }
如果mysql -u root test工作但是mysql -h your_hostname -u root test ; E7 Y: y: p6 l. a+ E- D, ]' z$ n
导致Access denied,那么在user表中你可能没有你的主机的正确名字。这里的
6 e5 `! r9 _9 j* s) `# e一个普遍的问题是在user表条目中的Host值指定一个唯一的主机名,但是你系统
- v0 \0 F( z. w2 j# R6 t的名字解析例程返回一个完全正规的域名(或相反)。例如,如果你在user表中有
- B: ~3 {5 E. W4 K: F) s一个主机是'tcx'的条目,但是你的 DNS告诉MySQL你的主机名是'tcx.subnet.
. u( \) |+ m" t3 t% ]se',条目将不工作。尝试把一个条目加到user表中,它包含你主机的IP数字作   `6 j( O2 I2 R7 I
为Host列的值。(另外,你可以把一个条目加到user表中,它有包含一个通配符 " g7 D+ t3 @1 o( N
如'tcx.%'的Host值。然而,使用以“%”结尾的主机名是不安全的并且不推荐!) * `% i  I. n2 v0 {) ]+ u2 b
如果mysql -u user_name test工作但是mysql -u user_name other_db_name
& T& r0 z( @$ i& M! `' G% B$ N$ M不工作,对other_db_name,你在db表中没有没有一个条目列出。
! i. d& k( R% @1 y4 T当在服务器机器上执行mysql -u user_name db_name时,它工作,但是在其
: o2 |3 d& H1 Q( H# y+ }它客户机器上执行mysql -h host_name -u user_name db_name时,它却不工作, ; ^. }) C. j; b/ L
你没有把客户机器列在user表或db表中。
7 }7 D2 w' y/ _. }) r# ~8 r如果你不能弄明白你为什么得到Access denied,从user表中删除所有Host . p: T+ `5 c: h; C. H/ h7 |
包含通配符值的条目(包含“%”或“_”的条目)。一个很普遍的错误是插入用
2 R/ q! M7 z+ a# Q/ ]Host='%'和User='some user'插入一个新条目,认为这将允许你指定localhost . g0 _* b! E2 U5 x/ V
从同一台机器进行连接。它不工作的原因是缺省权限包括一个有Host='localhost' % t7 D: r3 @- q. I$ V+ }- S, ^# x
和User=''的条目,因为那个条目一个比'%'更具体的Host值'localhost',当从 * l4 S) Q- p! @& h
localhost连接时,它用于指向新条目!正确的步骤是插入Host='localhost'和 6 L3 @5 l5 r! o0 g' g2 J2 {, Y
User='some_user'的第2个条目,或删除Host='localhost'和User=''条目。
* J7 S( ~1 `4 o& ^如果你得到下列错误,你可以有一个与db或host表有关的问题:
3 k1 x4 l4 l3 NAccess to database denied - G3 A2 E4 y5 h2 q( b5 l2 R

6 A! R4 v2 y' b2 f6 Z( A- a如果从db表中选择了在Host列有空值的条目,保证在host表中有一个或多 - V* H  A# S/ Q1 D
个相应的条目,指定运用db表中的哪些主机。如果在使用SQL命令SELECT ...
0 P( e% Y" |' PINTO OUTFILE或LOAD DATA INFILE时,你得到错误,在user表中的你的条目可
; B2 i( R4 }" `9 ]$ T% U2 S能启用file权限。 ) z2 M/ V2 P2 v# R. [. L
- {3 {6 O$ I$ d+ U! L/ s+ y
记住,客户程序将使用在配置文件或环境变量被指定了的连接参数。如果 - Y+ m$ `- d! i; D5 ^2 F2 U# F
当你不在命令行上指定他们时,一个客户似乎正在发送错误的缺省连接参数,
) r' k# h+ T( ]% K$ O6 [2 |6 W  Q检查你的环境和在你的主目录下的“.my.cnf”文件。你也可以检查系统范围 * ?# I( j' X$ g$ I
的MySQL配置文件,尽管更不可能将在那里指定那个客户的连接参数。如果当 ( Y& F( B0 H3 f9 r6 D
你没有任何选项运行一个客户时,你得到Access denied,确认你没在任何选
0 x& b8 w/ _0 a* z$ V3 E项文件里指定一个旧的口令!见4.15.4 选项文件。
7 V2 b! }( r" k1 P如果任何其它事情失败,用调试选项(例如,--debug=d,general,query)
, a! y3 [/ B$ k( I$ s) T启动mysqld守护进程。这将打印有关尝试连接的主机和用户信息,和发出的每
$ B% D; _4 A9 A" T% l1 {个命令的信息。见G.1 调试一个MySQL服务器。 3 T# {/ K7 l4 Q* c+ d* S5 \) {
如果你有任何与MySQL授权表的其它问题,而且觉得你必须邮寄这个问题 7 n8 m0 p+ S/ A; q3 m( x; K. |; U3 u
到邮寄表,总是提供一个MySQL授权表的倾倒副本(dump)。你可用mysqldump : J5 C0 S# A/ J! Z, `$ Z) v. _
mysql命令倾倒数据库表。象平时一样,用mysqlbug脚本邮寄你的问题。在一
* @. [8 D- y% o  l些情况下你可能用--skip-grant-tables重启mysqld以便能运行mysqldump。
3 V! ~# z6 {/ Z# T0 v3 S怎样使MySQL安全以对抗解密高手
/ V+ X( r* y; h( T: f8 B当你连接一个MySQL服务器时,你通常应该使用一个口令。口令不以明文 ' y5 q2 E3 w, l, ?
在连接上传输。
: ^- J1 c: @7 r5 Z5 L2 ]) S5 v5 \0 \# \& l0 C3 P3 N
所有其它信息作为能被任何人读懂的文本被传输。如果你担心这个,你可 0 u9 C, i  a7 G1 t1 D" w0 ^+ K3 \- _
使用压缩协议(MySQL3.22和以上版本)使事情变得更难。甚至为了使一切更安全 : e" j) n) u& q; D! ^! E! ~1 @
,你应该安装ssh(见http://www.cs.hut.fi/ssh)。用它,你能在一个MySQL服 ( T7 z/ y* ~) n- h' p' B5 g; d
务器与一个MySQL客户之间得到一个加密的TCP/IP连接。
1 ?; g+ P5 `9 c) i: ^- h, a
/ K6 }. P0 S+ ^0 M为了使一个MySQL系统安全,强烈要求你考虑下列建议:
, @2 y, L( \' _' M# {# }' r* g+ D+ @. Q8 W! p
对所有MySQL用户使用口令。记住,如果other_user没有口令,任何人能简 : v9 Z) }. i/ G8 s# a+ i
单地用mysql -u other_user db_name作为任何其它的人登录。对客户机/服务器
( c4 A! C( ^5 ]应用程序,客户可以指定任何用户名是常见的做法。在你运行它以前,你可以通
8 \. l# w. w. \; t& c过编辑mysql_install_db脚本改变所有用户的口令,或仅仅MySQL root的口令,
. a* m7 U3 h/ \( ~% ?' t象这样: 4 o( w. Y, S6 i  F
shell> mysql -u root mysql
6 t2 l( p) Y7 H; Pmysql> UPDATE user SET Password=PASSWORD('new_password') 3 J+ Y7 @" P* J5 [" W
WHERE user='root'; 6 u: {  g8 c6 f6 Q, }" @* N9 a
mysql> FLUSH PRIVILEGES; , @2 r- r7 E4 `) n. S4 o

# a- v5 J$ J8 O+ a4 P0 ]" c# W5 c不要作为Unix的root用户运行MySQL守护进程。mysqld能以任何用户运行, 0 [' \# d9 ~7 y
你也可以创造一个新的Unix用户mysql使一切更安全。如果你作为其它Unix用户
8 _  z# p! W( o5 f7 A2 m0 W运行mysqld,你不需要改变在user表中的root用户名,因为MySQL用户名与Unix 7 V* n! F1 w/ ^' q$ |
用户名没关系。你可以作为其它Unix用户编辑mysql.server启动脚本mysqld。 " X. @8 x4 {! u+ G
通常这用su命令完成。对于更多的细节,见18.8 怎样作为一个一般用户运行 ( B9 Y" u6 y$ b6 H$ n' J
MySQL。
  g0 [6 M. a6 L: L* `- r0 t+ Z: x如果你把一个Unix root用户口令放在mysql.server脚本中,确保这个脚本 - p% F/ M8 u$ o& q2 t
只能对root是可读的。   y$ z, G7 n- |0 N$ I2 c6 h9 e) q, ^
检查那个运行mysqld的Unix用户是唯一的在数据库目录下有读/写权限的用 ; t, l1 Z. a0 u5 Q
户。
6 G9 X+ I6 Q0 N: f* c不要把process权限给所有用户。mysqladmin processlist的输出显示出当 : D, W7 S3 S3 T( }+ ~# |
前执行的查询正文,如果另外的用户发出一个UPDATE user SET password=
, f; p' Y% N1 F- g* \2 W% _. yPASSWORD('not_secure')查询,被允许执行那个命令的任何用户可能看得到。 ; d1 p' u. L0 T, @2 A3 z; l& _
mysqld为有process权限的用户保留一个额外的连接, 以便一个MySQL root用 . R1 b2 N$ a( v0 k, v* z3 I( o
户能登录并检查,即使所有的正常连接在使用。 : f& R# C% w/ p% b! m
不要把file权限给所有的用户。有这权限的任何用户能在拥有mysqld守护
6 q6 Q8 Y7 r3 ]! i进程权限的文件系统那里写一个文件!为了使这更安全一些,用SELECT ... * D7 z9 T. P4 K. A6 Z$ y
INTO OUTFILE生成的所有文件对每个人是可读的,并且你不能覆盖已经存在的 0 }# `# D( L- v5 l( h6 r1 r! x
文件。file权限也可以被用来读取任何作为运行服务器的Unix用户可存取的文
) h3 o$ Z' `5 U% h" B件。这可能被滥用,例如,通过使用LOAD DATA装载“/etc/passwd”进一个数 & ]/ N' V& o% Q2 f2 u1 n4 U1 L8 n! |
据库表,然后它能用SELECT被读入。   K9 K) p1 F& k& O6 K* a$ k
如果你不信任你的DNS,你应该在授权表中使用IP数字而不是主机名。原则 2 j: s  G, A% l: F& t
上讲,--secure选项对mysqld应该使主机名更安全。在任何情况下,你应该非常
$ T6 l$ O5 z# \- ~7 [  X# X小心地使用包含通配符的主机名!
9 J4 o8 ?8 \# R7 f# L下列mysqld选项影响安全:
0 \9 J- ]5 G( ?, Y0 E7 E# |7 F/ k* B3 T8 J  {9 ^9 O- Y3 t; n
--secure
, }0 {; ^% {1 Q5 R8 a) T5 m% ]由gethostbyname()系统调用返回的IP数字被检查,确保他们解析回到原来 4 Z; V6 q! A: A
的主机名。这对某些外人通过模仿其它主机获得存取权限变得更难。这个选项也
5 K9 h3 _+ \. ^增加一些聪明的主机名检查。在MySQL3.21里,选择缺省是关掉的,因为它有时
+ ^$ ?0 ?8 k" ]" |+ r  d1 l它花很长时间执行反向解析。MySQL 3.22缓存主机名并缺省地启用了这个选项。 + n& n9 O, H' a( W
--skip-grant-tables ! Z7 T; Q9 g4 w  V$ k
这个选项导致服务器根本不使用权限系统。这给每个人以完全存取所有的数 * `- f' T3 u% w/ w) k' x
据库的权力!(通过执行mysqladmin reload,你能告诉一个正在运行的服务器
% ?$ h: R0 N; j* u' B  L再次开始使用授权表。) + E$ b/ I) V  t2 a" Z# t  M" G! h
--skip-name-resolve 9 m4 ?+ _2 J9 t/ ?$ [
主机名不被解析。所有在授权表的Host的列值必须是IP数字或localhost。
) D! f7 L  a/ V  A1 u; J9 q--skip-networking
" P* O6 H& g1 L在网络上不允许TCP/IP连接。所有到mysqld的连接必须经由Unix套接字进
  F0 B* R, ?9 }# D, z* B3 [$ }1 H行。这个选项对使用MIT-pthreads的系统是不合适的,因为MIT-pthreads包不
) a7 A1 J: s& m+ K支持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 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
看了一屏就晕了。。。1 s+ e1 P) E1 V0 ^5 y7 `$ G
汗。。4 U+ w1 ]# L  l/ `0 E
水平不够,消化不了。。# R; ~3 i& o3 R' B: V. L5 D+ o6 o
不过还是顶一下
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 顶 踩

本版积分规则

关闭

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

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