下沙论坛

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

QQ登录

QQ登录

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

MySql的权限存取系统

[复制链接]
rcrun 该用户已被删除
跳转到指定楼层
1
发表于 2003-7-26 16:31:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
MySQL有一个先进但非标准的安全/权限系统。本文描述它的工作原理。
( h# |: S7 T1 I$ c* j' R
1 z- n4 Z+ T' I  |# _权限系统做什么
7 n4 T5 z& `0 t7 k8 vMySQL权限系统的主要功能是证实连接到一台给定主机的一个用户,
% t- R; K$ F( J7 V1 k  `并且赋予该用户在一个数据库上select、 insert、update和delete的
9 K( S8 r3 j: U权限。
7 w  h! V" j1 j& [$ L
9 H. ^4 ]) g! D5 N附加的功能包括有一个匿名的用户和对于MySQL特定的功能例如 4 ^# f$ l" u$ e
LOAD DATA INFILE进行授权及管理操作的能力。 8 T) S% K6 G2 Y' N) z. j
) a( N1 Q2 ?6 v& f/ o* q
MySQL 用户名和口令
% b$ @, q3 \) u/ w由MySQL使用用户名和口令的方法与Unix或Windows使用的方式有很 / g' ~7 q7 j3 K5 h; f4 N4 D) A
多不同之处:
6 x/ z+ j# P/ C3 O) o0 @) m
4 m1 `0 O8 ?$ Q5 u" B2 u/ X* d/ L+ }$ {# UMySQL使用于认证目的的用户名,与Unix用户名(登录名字)或
0 S. a- r- z4 |% E4 N) wWindows用户名无关。缺省地,大多数MySQL客户尝试使用当前Unix用户 0 f5 D- A1 z1 L
名作为MySQL用户名登录,但是这仅仅为了方便。客户程序允许用-u或- / H. g  [# S3 o! K
-user选项指定一个不同的名字,这意味着无论如何你不能使得一个数据 8 i7 P* B% p. _
库更安全,除非所有的MySQL用户名都有口令。任何人可以试图用任何名
, D5 g* }8 Z8 [7 \$ A字连接服务器,而且如果他们指定了没有口令的任何名字,他们将成功。
' v5 c7 L' e5 l  `MySQL用户名最长可以是16各字符;典型地,Unix用户名限制为8个字符。 ' J0 B) a6 v. @) X% c7 m
MySQL口令与Unix口令没关系。在你使用登录到一台Unix机器口令和你使
" t3 }# T. _6 N8 o0 V+ S' \) ?. o( K# ?用在那台机器上存取一个数据库的口令之间没有必要有关联。 & a; E4 j, q6 v
MySQL加密口令使用了一个Unix登录期间所用的不同算法。
1 l/ y4 _  T6 U# l# }
5 i' x/ b: H# {/ r与MySQL服务器连接
! H- P! M  H! u$ S. B( j当你想要存取一个MySQL服务器时,MySQL客户程序一般要求你指定
' F0 h8 i) ]% ?0 X' X连接参数:你想要联接的主机、你的用户名和你的口令。例如,mysql
4 d' j' {, ?* _( U1 D客户可以象这样启动(可选的参数被包括在“[”和“]”之间): 8 V1 p. ^7 q! T: h6 e8 a( q& W; t
- A8 p. k1 l1 Q8 y5 c9 m4 u
shell> mysql [-h host_name][-u user_name][-pyour_pass ] . |2 Q+ `+ e  F  D( v: B
-h, -u和-p选项的另一种形式是--host=host_name、--user= 0 ?% [* ~. O  V
user_name和--password=your_pass。注意在-p或--password=与跟随它
; `% T5 E+ k+ c) t后面的口令之间没有空格。
! O+ l1 ]% ~) d  f/ N$ _# d) F9 B  [8 P# J' r5 B- A
注意:在命令行上指定一个口令是不安全的!随后在你系统上的任
+ H6 W9 H2 S+ K; H4 V4 t何用户可以通过打类似这样的命令发现你的口令:ps auxww。
6 s7 r& \, M/ F; x/ }$ Y" F1 s' G1 j# w
对于命令行没有的联接参数,mysql使用缺省值:
; V- H, t$ p. x0 x; t1 ~: Q8 \. r" w1 X% E& d
缺省主机名是localhost。
- b* J" n2 U" ?* Z缺省用户名是你的Unix登录名。
0 [% J% [8 H. I. X如果没有-p,则没有提供口令。 . y* S8 `! ]/ ~7 i
这样, 对一个Unix用户joe,下列命令是等价的:
" Q( a6 G5 p! E9 I* Z0 i
0 s/ f! X! |! S& \- p0 Nshell>mysql -h localhost -u joe 6 X/ |/ D' ]" b+ i* v
shell>mysql -h localhost 4 L3 N; F+ U. V' c
shell>mysql -u joe % r; _, ^6 F+ e+ L
shell>mysql
& V8 N# P3 C3 m4 n/ S) i+ s7 @- m+ e1 q9 c# e
其它MySQL客户程序有同样表现。
( D( N7 G4 L& ^9 y' V% J7 P2 c% @( g7 T; w  F. y& k2 ]# ^) f
在Unix系统上,当你进行一个连接时,你可以指定要使用的不同的缺 8 r( X) u. ?# Y3 p
省值,这样你不必每次在你调用一个客户程序是在命令行上输入他们。这
1 y0 B4 R) L% j$ }# C" S可以有很多方法做到:
9 k/ q/ `* e( J. P" y! @5 ]0 J. I) t5 X) u. L
你能在你的主目录下“.my.cnf”的配置文件的[client]小节里指定   e3 F* G) z, T9 x  _  Y3 |* y4 y
连接参数。文件的相关小节看上去可能像这样:
3 }5 x) m9 \9 h* i5 r5 T[client]
' ?4 D# X5 O' u/ ~host=host_name 8 M$ ~/ k" _- l, j  i4 k: @
user=user_name
  E; G: I# b1 k2 }password=your_pass 2 m4 b0 r  b% I' k2 F% H

$ ^( E6 {. v3 _5 F: V* D你可以用环境变量指定连接参数。主机可用MYSQL_HOST指定,MySQL
; e* H0 W9 |6 W# ?用户名字可用USER指定(仅对 Windows),口令可用MYSQL_PWD指定(但是 3 [8 j* ]8 S2 u5 @
这不安全) 。 - ?2 I6 j7 K2 ^. F
如果连接参数以多种方法被指定,在命令行上被指定的值优先于在配 / f* a- Z1 q8 m3 P& j( b& U* D
置文件和环境变量中指定的值,而在配置文件指定的值优先于在环境变量
  F* v0 S0 c& d$ K) r指定的值。
# [+ L$ p3 A; x5 n, s" D7 K. F4 e% d; S% B1 G
使你的口令安全
2 s( b, o7 g- T; q' B. W3 W以一种暴露的可被其他用户发现的方式指定你的口令是不妥当的。
# e/ m/ C, ?+ N. s+ n  b当你运行客户程序时,你可以使用下列方法指定你的口令,还有每个方法 / W& B5 g* d' o/ J, Y  ]4 _
的风险评估:
0 L, X8 r. q& V/ e+ i$ {
7 X( G, M, c- c( \! N; A7 F( y使用一个在命令行上-pyour_pass或--password=your_pass的选项。 & n( }3 i) B1 C/ ~" o. [; J7 V
这很方便但是不安全,因为你的口令对系统状态程序(例如ps)变得可见,
- Z- v# f& p0 s; c$ Z) o它可以被其他的用户调用来显示命令行。(一般MySQL客户在他们的初始化
- M# x/ W" R( b! H顺序期间用零覆盖命令行参数,但是仍然有一个短暂间隔时间内参数值可 - Q+ n5 {/ d  o* Y+ `" s  v" S
见的。) 8 d$ X8 e+ }2 G
使用一个-p或--password选项(没有指定your_pass值)。在这种情况 ( H2 r; _8 k# K8 N2 i* q
下,客户程序请求来自终端的口令:
+ m1 [* q+ a) R+ ]. r
1 b/ o- x4 }5 t1 g+ g  tshell>mysql - u user_name - p ( O' ]4 s: \( g0 `% D
Enter password: ******** 7 t0 D- @# c7 z
# B/ ^& X! \1 D. e" s( D, H
客户回应“*”字符到作为输入你的口令的终端使得旁观者不能看见
: B" Q* z( Q4 m' \  T% f) V2 M它。因为它对其他用户不可见,与在命令行上指定它相比,这样进入你 % c& k' m( e; Z, s. l' r7 q
的口令更安全。然而,这个输入一个口令的方法仅仅为你交互式运行程 1 k1 B& t  P( R+ u, r3 p
序是合适的。如果你想要从非交互式运行的一个脚本调用一个客户,就   y) a. X" n  f0 b+ [4 v& u
没有从终端输入入口令的机会。
( @( N9 i" s* B$ a
4 c2 h* f) C) [1 M, H9 V4 P在一个配置文件中存储你的口令。例如,你可你的主目录的
- N. a/ l6 U6 {/ @6 C8 C0 L4 w“.my.cnf”文件中的[client]节列出你的口令: : v7 S% S9 A7 [9 B3 N* f$ X. _6 S
[client]
% _4 a+ [9 b" \2 o' Kpassword=your_pass $ ~' [5 u0 Z+ X. {
% L5 }7 u# |3 i0 |5 v3 H+ \0 T
如果你在“.my.cnf”里面存储口令,文件应该不是组或世界可读或
$ X/ }/ p7 G; z: T可写的。保证文件的存取模式是400或600。见4.15.4 选项文件。 7 O. {, g& X" n* S0 C& N

* q# [8 f/ D; d) A7 _! S你可在MYSQL_PWD环境变量中存储口令,但是这个方法必须想到是极 # D$ w. y( E2 }* x7 h
不安全的且应该不使用。ps的某些版本包括显示运行进程的环境的选项; # P. i, L7 m5 O% Y/ M( F% a2 p( N+ K
如果你设定MYSQL_PWD,你的口令将对所有人是显而易见的,甚至在没有
: `( }2 I  w: j! n这样一个版本的ps系统上,假设没有其他方法观察到进程环境是不明智
& {0 R# P, y9 F" a的。
7 g8 D5 \' Z3 `" K% M, L( L总之,最安全的方法是让客户程序提示口令或在一个适当保护的“ : ~9 l% t. J( |
.my.cnf”文件中指定口令。 8 R  R4 q4 S1 I' L) d
" [7 B  y3 N2 _1 @) ^3 A
MySQL提供的权限
* V( S2 F' `# |2 s) a0 r权限信息用user、db、host、tables_priv和columns_priv表被存储
/ Q7 S5 Y7 v2 F, |在mysql数据库中(即在名为mysql的数据库中)。在MySQL启动时和在权限
% B  Q. E0 T2 y4 A$ Q! [6 K修改何时生效所说的情况时,服务器读入这些数据库表内容。 . I( R7 _- m/ I$ G

) e+ @$ K0 A& Z$ J  q由MySQL提供的权限名称显示在下表,还有在授权表中每个权限的表
6 t1 \" A& W3 D5 c' F! h0 ~; _列名称和每个权限有关的上下文: ; Q2 ]! f% B1 ^
权限 列 上下文 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 在服务器上的文件存取
1 t& z: U3 y" i- K$ _% Pselect、insert、update和delete权限允许你在一个数据库现有的
% C+ o8 d( s' q表上实施操作。 # |) i: h" t4 j* J8 S, D3 A/ l/ [
& s, `- {" T6 Q$ e; O# w! Q2 p
SELECT语句只有在他们真正从一个表中检索行是才需要select权限,
& w* t4 t% N" O$ V. [; j你可以执行某个SELECT语句,甚至没有任何到服务器上的数据库里的存
8 X1 }# k" Z9 O2 L* i; s+ g1 ^取任何东西的许可。例如,你可使用mysql客户作为一个简单的计算器: ; b9 `. H/ u( k9 D% d( [) [
: y  N7 a: a' V
mysql> SELECT 1+1;
6 w9 E6 S- i& F$ v$ Lmysql> SELECT PI()*2;
6 Z1 C1 D) r+ t7 t1 f6 |4 Z, E6 @
index权限允许你创建或抛弃(删除)索引。 8 ~) G$ n+ {; H5 W; W: o  e; ^
8 B9 C) R+ V$ a
alter权限允许你使用ALTER TABLE。
4 a7 |; s5 U; l6 _6 \% P! _  x4 {! ]# I! F
create和drop权限允许你创建新的数据库和表,或抛弃(删除)现存的
8 W) ~; W% h8 a数据库和表。 ' T* t% a. Q( K+ @

9 j/ L+ ^* P- ]! A. Y' Z注意:如果你将mysql数据库的drop权限授予一个用户,该用户能抛弃
" I& R" _) r' t# a% n2 H存储了MySQL存取权限的数据库! 7 z! A% h( s) Q& O

4 v: z4 R1 E7 d; u% i- E& P8 [grant权限允许你把你自己拥有的那些权限授给其他的用户。
0 L, A/ z- ^# [9 l" r8 o0 c$ c. R6 ?) J" S/ M- o! t/ ]7 q5 d2 J4 K
file权限给予你用LOAD DATA INFILE和SELECT ... INTO OUTFILE语句
) O$ J, M  u* ^1 F- a: k读和写服务器上的文件,任何被授予这个权限的用户都能读或写MySQL服务 + s7 a2 q5 Q4 K2 H! i- A1 J7 }% u! |
器能读或写的任何文件。   D# l: L0 g9 X4 M

8 e$ Q3 O- g1 s+ Y$ G4 u其余的权限用于管理性操作,它使用mysqladmin程序实施。下表显示 / T' Z/ _5 P) p9 V' H* v. s
mysqladmin支配每个管理性权限允许你执行的命令:
9 X% m3 a- t0 p% \( M8 B# `优惠 权限拥有者允许执行的命令 reload reload, refresh, flush-privileges, flush-hosts, flush-logs, flush-tables shutdown shutdown precess processlist, kill
+ M1 ^$ S; ?' `/ F# G0 breload命令告诉服务器再读入授权表,refresh命令清洗所有表并打开 " J% s  ]% g0 N0 Y6 y
和关闭记录文件,flush-privileges是reload的一个同义词,其它flush-*
, `+ B) F4 V/ N( H- t1 S0 D+ l% c命令执行类似refresh的功能,但是范围更有限,并且在某些情况下可能更 1 {* S* }4 k$ E! z3 e
好用。例如,如果你只是想清洗记录文件,flush-logs比refresh是更好的 9 @5 F$ l+ j$ c. `, j
选择。
3 v! \& T9 T0 ^1 R5 E( _' g1 @1 y* o& a$ s/ k% E$ R* `  g
shutdown命令关掉服务器。
) c+ {- L. P, v* j
2 f& f: r! c* _: iprocesslist命令显示在服务器内执行的线程的信息。kill命令杀死服 - h3 F" O- X3 g: ?& v
务器线程。你总是能显示或杀死你自己的线程,但是你需要process权限来
' D) m7 h* a, Z6 S5 f# J显示或杀死其他用户启动的线程。
2 P4 M: V  W8 \) m3 _- p5 @
0 o& F3 [) y' S" f9 Y总的说来,只授予权限给需要他们的那些用户是一个好主意,但是你 $ t$ g, X+ X* t+ n% }% d
应该在授予某个权限时试验特定的警告: 3 K! c! \( t% v, p
) z8 L) M+ f4 j
grant权限允许用户放弃他们的权限给其他用户。2个有不同的权限并 - B# N, I( j$ V3 t# T  T# n$ H
有grant权限的用户可以合并权限。 . u/ d' c0 J$ T0 D' t* x
alter权限可以用于通过重新命名表来推翻权限系统。
! E  P+ y* U- G3 \9 C9 \file权限可以被滥用在服务器上读取任何世界可读(world-readable, * ?2 @* p; e& V& R* O, K; c1 c
即任何人可读)的文件到一张数据库表,然后其内容能用SELECT被存取。
4 n" P( d# v! ]8 b. qshutdown权限通过终止服务器可以被滥用完全拒绝为其他用户服务。 3 l7 G* O. o& r- m) K' }! F
precess权限能被用来察看当前执行的查询的普通文本,包括设定或改
, \. R% X* J$ J3 e  ?% d6 B变口令查询。 8 ~2 ^+ |# i, @& a; X1 W
在mysql数据库上的权限能被用来改变口令和其他存取权限信息。(口   [4 R' w" j+ [4 a7 T, ]
令被加密存储,所以一个恶意的用户不能简单地读取他们。然而,有足够
3 T4 c6 W& ~" P# K4 O6 E. X的权限,同一个用户能用不同的一个代替一个口令。)
# c& \6 E1 ^. N; F有一些事情你不能用MySQL权限系统做到:
0 l3 N3 q. T4 G
" s& @! O3 l! O6 M: l- [8 C2 g你不能明显地指定一个给定用户应该被拒绝存取。即,你不能明显地匹
+ s; N+ M$ y/ U. n* E配一个用户并且然后拒绝连接。
! n  x$ s0 A) n; ^  L  p, Y' K你不能指定一个用户有权创建立或抛弃一个数据库中的表,也不能创建
3 Z' x1 T9 c5 C: C2 _8 c# C  T* ~' U7 N或抛弃数据库本身。 ) a9 ?1 e0 Z; @6 L' a# W
权限系统工作原理 / L" l+ Z% e& e3 I
MySQL权限系统保证所有的用户可以严格地做他们假定被允许做的事情。
1 @7 V# I: N" w当你连接一个MySQL服务器时, 你的身份由你从那连接的主机和你指定的用
: e1 N+ g$ t8 @( t8 Z6 o户名来决定,系统根据你的身份和你想做什么来授予权限。
5 L- U" P( ^) C2 z6 q
& f$ G8 H- u% a6 r6 T( ?MySQL在认定身份中考虑你的主机名和用户名字,是因为有很小的原因假 8 n6 r2 d# j  R6 f" P* L8 B" W, b
定一个给定的用户在因特网上属于同一个人。例如,用户从whitehouse.gov
3 I2 Y, w$ ^1 Z% S, U连接的bill不必和从mosoft.com连接bill是同一个人。 MySQL通过允许你区
# ?" T- d" l9 J/ Y5 o! A分在不同的主机上碰巧有同样名字用户来处理它:你可以对从whitehouse.gov 2 d$ N7 h' Q! I- N% h- T& M% p
连接授与bill一个权限集,而为从microsoft.com的连接授予一个不同的权限
( [: ^% w& l! P/ I# }集。 & b8 k9 s5 Q8 j* K
4 Z  d* u' S$ T" X
MySQL存取控制包含2个阶段:
! r8 v7 s" c5 d) x3 R9 L* x
$ S2 ]% ?& @& n* K, D% x阶段1:服务器检查你是否允许连接。
- e4 W/ z* P5 k( L阶段2:假定你能连接,服务器检查你发出的每个请求。看你是否有足够
) V5 w! q1 g7 x( w& L5 @- @5 H的权限实施它。例如,如果你从数据库中一个表精选(select)行或从数据库抛
! t( i) q! f9 G弃一个表,服务器确定你对表有select权限或对数据库有drop权限。
9 Y. w! o8 D+ J" o9 x8 c服务器在存取控制的两个阶段使用在mysql的数据库中的user、db和host
8 q* }# w" f. w, r表,在这些授权表中字段如下:
( y. L+ a: I& d% L. v2 S表名称 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
4 ]& Y, _+ o8 S1 J. y对存取控制的第二阶段(请求证实),如果请求涉及表,服务器可以另外 1 }7 V2 F8 k- ?: h* s- Y! o) `
参考tables_priv和columns_priv表。这些表的 " ]" l1 O: x) @' |8 ~9 A$ Z
字段如下: 3 k% s% V, ], t# p
表名称 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
8 t% l, x# S/ M& I1 w! k8 p% G: ]' }6 R对存取控制的第二阶段(请求证实),如果请求涉及表,服务器可以另外
2 ]8 R' j4 a* z+ P/ o参考tables_priv和columns_priv表。这些表的字段如下: 9 d% F0 Q6 b8 c* A. E4 J
字段名 类型 Host CHAR(60) User CHAR(16) Password CHAR(16) Db CHAR(64) (tables_priv和columns_priv表为CHAR(60))
- c5 T& q) }$ A* K9 {/ G在user、db和host表中,
. V2 I, n0 P' g4 u, P. b所有权限字段被声明为ENUM('N','Y')--每一个都可有值 3 I4 g6 L, F' `1 T0 A; U, o5 V
'N'或'Y',并且缺省值是'N'.
1 ~9 d: W1 W$ K% j3 H4 u% k在tables_priv和columns_priv表中,权
; S  t/ r: Y; q% d1 J) P8 w& G' y限字段被声明为SET字段:
: |+ T( q2 t6 \9 ^- 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' : l' W$ H6 L7 W  ]+ Z, x5 M
每个授权表包含范围字段和权限字段。 7 l! T( R7 P, m3 V: q
- q+ B& g/ O2 I
范围字段决定表中每个条目的范围,即,条目适用的上下文。例如, 5 _( l. d3 z* T+ [  f4 I
一个user表条目的Host和User值为'thomas.loc.gov'和'bob'将被用于 ( ~- G- Q& y: e, W
证实来自主机thomas.loc.gov的bob对服务器的连接。同样,一个db表条
# p: F& f; G2 U- ~) \目的Host、User和Db字段的值是'thomas.loc.gov'、'bob'和'reports' ; D% y- j7 v0 m# }& p8 v, b
将用在bob从主机联接thomas.loc.gov存取reports数据库的时候。
! i# I" z0 C$ @& G5 C* R1 b1 mtables_priv和columns_priv表包含范围字段,指出每个条目适用的表或
' U8 ]; v/ T6 I) A# C, P5 q表/列的组合。 8 s# G) E6 j4 J8 K3 n

* z  A* i! w8 V" W对于检查存取的用途,比较Host值是忽略大小写的。User、Password、 * f+ _' c" }: I6 \
Db和Table_name值是区分大小写的。Column_name值在MySQL3.22.12或以
1 i0 ]+ Q9 {& h/ N/ ~  i( p' P后版本是忽略大小写的。
2 A9 c5 D/ D9 _4 s" X$ f6 s+ x# T
* H) `, S8 P8 n4 |& Z权限字段指出由一个表条目授予的权限,即,可实施什么操作。服务
* p$ w- U8 u, @, T* w器组合各种的授权表的信息形成一个用户权限的完整描述。为此使用的规 ; G( x$ v6 h% q6 g
则在6.8 存取控制, 阶段2:请求证实描述。 ; P, P% v# I# j/ I+ `& i- L

. o4 O# b- S1 }6 T4 a; ~+ A范围字段是字符串,如下所述;每个字段的缺省值是空字符串:
7 q% C0 B3 A+ T/ y$ ]0 z字段名 类型 Host CHAR(60) User CHAR(16) Password CHAR(16) Db CHAR(64) (tables_priv和columns_priv表为CHAR(60)) ) T9 j2 v& C9 k, {9 s( p
在user、db和host表中,所有权限字段被声明为ENUM('N','Y')--每一 ' K( B4 V$ F/ l5 V1 o& Z6 ]
个都可有值'N'或'Y',并且缺省值是'N'.
& Y+ v: q; t6 X& d' M+ P  m
$ `5 f8 U0 r3 |/ ?  g( s. I0 g在tables_priv和columns_priv表中,权限字段被声明为SET字段: 8 t7 u0 a  N/ d. ~
表名 字段名 可能的集合成员 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 x( Q% e/ R* h3 x' i简单地说,服务器使用这样的授权表: $ {( O. o6 n, A9 _# _# z
7 j  a6 x7 \/ W7 y$ ]2 f& V
user表范围字段决定是否允许或拒绝到来的连接。对于允许的连接,
; T! _' N# K5 C权限字段指出用户的全局(超级用户)权限。 $ y1 h. C* s' F; G' l# y
db和host表一起使用: / X6 s% i. ^% y$ x2 L' k$ M! ?
db表范围字段决定用户能从哪个主机存取哪个数据库。权限字段决定
8 `1 E" Z( w8 e# W2 ^$ ]' l5 S( ]允许哪个操作。 4 N+ U: T4 L- ]4 a% X5 x
当你想要一个给定的db条目应用于若干主机时,host表作为db表的扩
5 D' ]: U$ U" \. [$ }% d展被使用。例如,如果你想要一个用户能在你的网络从若干主机使用一个 - h- h, V8 a4 Y/ E
数据库,在用户的db表的Host条目设为空值,然后将那些主机的每一个移 0 |2 Q' w) p1 r
入host表。这个机制详细描述在6.8 存取控制, 阶段2:请求证实。
2 s9 y, h, ]+ ~! n6 H9 [tables_priv和columns_priv表类似于db表,但是更精致:他们在表 ( G9 ?0 _. ~) @' R
和列级应用而非在数据库级。
6 e# g( H; Q; i( f注意管理权限(reload, shutdown, 等等)仅在user表中被指定。这是 3 G2 i( d! `/ {9 q
因为管理性操作是服务器本身的操作并且不是特定数据库,因此没有理由
4 c' [8 s0 W1 D9 J8 n在其他授权表中列出这样的权限。事实上,只需要请教user表来决定你是 0 k' ?, E" y# W
否执行一个管理操作。 3 f1 J% q: E9 Z0 \& z
6 S; I$ r- o6 `, ^
file权限也仅在user表中指定。它不是管理性权限,但你读或谢在服
: ]0 v1 f8 ?7 v- L3 @* }' M7 A务器主机上的文件的的能力独立于你正在存取的数据库。 4 C% Z  k9 S1 N" e6 C" {( g9 K2 u

  [  b' v, s& N: a当mysqld服务器启动时,读取一次授权表内容。
, ^, P' I% e* {; s( v, U) x' Z3 t5 r, I! H" v/ o
当你修改授权表的内容时,确保你按你想要的方式更改权限设置是一 # W8 ~( H. E- ]8 L
个好主意。
4 I& z" w) O. |# x8 C: a$ U6 `" {/ K2 a9 c
一个有用的诊断工具是mysqlaccess脚本,由Carlier Yves 提供给 % {5 L: O$ B) O& D4 S9 u
MySQL分发。使用--help选项调用mysqlaccess查明它怎样工作。注意:
$ a% `; k- z/ {+ U4 Vmysqlaccess仅用user、db和host表仅检查存取。它不检查表或列级权限。 6 }% [/ r' I( V" a; ?1 X, R$ u

7 f" K; I6 F; y! Q; o% g存取控制, 阶段1:连接证实 - _/ a, g% y8 M' Q
当你试图联接一个MySQL服务器时,服务器基于你的身份和你是否能 ; l0 ~, K  s, O* ^8 g
通过供应正确的口令验证身份来接受或拒绝连接。如果不是,服务器完全 , s# N5 x4 H8 S: V7 w& a  \
具结你的存取,否则,服务器接受连接,然后进入阶段2并且等待请求。
& Q1 U/ P5 K! e9 }. T. f" r6 g0 j( z$ i' {. I. m
你的身份基于2个信息: ! f% i7 ^) E, ^* j2 l+ n
3 N& N, O6 _- P7 b8 k3 E7 {1 P. Y! Q
你从那个主机连接 / |4 Q4 s# z" a& a* a4 ^
你的MySQL用户名
# D/ L( B$ |1 r; F% ]+ @身份检查使用3个user表(Host, User和Password)范围字段执行。服 0 ]5 i* t) g1 h) l
务器只有在一个user表条目匹配你的主机名和用户名并且你提供了正确的
& F/ T, S  Y' P* k& R口令时才接受连接。
, s% s4 h5 i8 W0 e( `
7 e, a  V8 x% R9 [; k3 h在user表范围字段可以如下被指定:
! }6 ]/ {+ F" y- e# n9 |' w) t& F1 T8 t( s* q" q
一个Host值可以是主机名或一个IP数字,或'localhost'指出本地主机。 $ `: f8 M* g7 b% |
你可以在Host字段里使用通配符字符“%”和“_”。 . T0 O$ y$ _! o3 A
一个Host值'%'匹配任何主机名,一个空白Host值等价于'%'。注意这些
! o  x" U  J6 C值匹配能创建一个连接到你的服务器的任何主机! ' k' }3 R5 `2 R
通配符字符在User字段中不允许,但是你能指定空白的值,它匹配任何 , F2 h; ^3 g6 W+ V6 N# ?- W; e% D
名字。如果user表匹配到来的连接的条目有一个空白的用户名,用户被认为 3 |+ |+ z3 \) P0 f+ @
是匿名用户(没有名字的用户),而非客户实际指定的名字。这意味着一个空 . j9 b' p7 F. j, \# \
白的用户名被用于在连接期间的进一步的存取检查(即,在阶段2期间)。
8 W- ?3 M' k7 t. G& U9 ~Password字段可以是空白的。这不意味着匹配任何口令,它意味着用户   z. ?) f& F  L& O
必须不指定一个口令进行连接。
$ I: e; l+ c7 @$ x1 C, S非空白Password值代表加密的口令。 MySQL不以任何人可以看的纯文本
; H. j7 A! S- ^) m4 i  ]格式存储口令,相反,正在试图联接的一个用户提供的口令被加密(使用
* k6 L+ Q' J: _$ lPASSWORD()函数),并且与存储了user表中的已经加密的版本比较。如果他
$ L8 Q5 c9 y/ q5 a: \8 @6 q! x5 c2 V们匹配,口令是正确的。
$ y- v$ |2 X# H; t
$ L/ S5 g- q7 O  g. b下面的例子显示出各种user表中Host和User条目的值的组合如何应用于到来 3 v: Z, S* @& r: _/ h9 s
的连接:
& S/ P6 y$ _: J/ [
  S9 ]+ y% i' J- A0 n2 E# MHost 值 User 值 被条目匹配的连接 0 E8 c5 i& M- f7 Z7 J6 A6 d& J& ^
'thomas.loc.gov' 'fred' fred, 从thomas.loc.gov 连接 * h% s8 L) s4 H- ?+ A4 m
'thomas.loc.gov' '' 任何用户, 从thomas.loc.gov连接
9 t9 N! a" z$ M1 v* }'%' 'fred' fred, 从任何主机连接
- G! m) Q1 P7 x+ G/ p! i'%' '' 任何用户, 从任何主机连接 : f( L3 W& k- X4 b. W
'%.loc.gov' 'fred' fred, 从在loc.gov域的任何主机连接
! V2 h6 @% V, M0 `'x.y.%' 'fred' fred, 从x.y.net、x.y.com,x.y.edu等联接。(这或许
( [0 f  V5 H4 P- ~+ C6 \无用)
, V) k7 n8 V9 p  E'144.155.166.177' 'fred' fred, 从有144.155.166.177 IP 地址的主
& S  M) Y6 {, H6 [' v. X+ m& e& U机连接
" J7 g- k  \8 R, Y'144.155.166.%' 'fred' fred, 从144.155.166 C类子网的任何主机连
* w" h" n1 E0 Q6 h1 |8 f1 I' A) U
$ z. W) h* N. l* ~7 M+ O7 X/ o3 B8 s( B4 U9 i) v6 x1 Z/ R
既然你能在Host字段使用IP通配符值(例如,'144.155.166.%'匹配在一个子
+ p# b7 T. U4 T# y5 N: c网上的每台主机),有可能某人可能企图探究这种能力,通过命名一台主机 & R% T  c, U7 s" p( t5 o# Q
为144.155.166.somewhere.com。为了阻止这样的企图,MySQL不允许匹配以
& k# u' }; ]4 T: A7 ~* r0 \数字和一个点起始的主机名,这样,如果你用一个命名为类似1.2.foo.com的
+ v$ E& A, A, T# A主机,它的名字决不会匹配授权表中Host列。只有一个IP数字能匹配IP通配
1 g, n( W, r  K  C  G+ |" H8 a符值。 7 y* X: i! d( f: `+ G: y1 E

. P' O. ]5 w) e( j/ W( D) y* }9 t一个到来的连接可以被在user表中的超过一个条目匹配。例如,一个由
: V1 o+ m. \+ q; ~: B* F# Q4 afred从thomas.loc.gov的连接匹配多个条目如上所述。如果超过一个匹配, % @2 M/ w. h) W; `
服务器怎么选择使用哪个条目呢?服务器在启动时读入user表后通过排序来 5 M( ~; W6 U! [* L
解决这个问题,然后当一个用户试图连接时,以排序的顺序浏览条目,第一
' q$ ]6 e( h, t+ \/ l: R个匹配的条目被使用。
& ]. D2 H( _& V4 x, {8 l
) F9 U7 ?! ~6 A# iuser表排序工作如下,假定user表看起来像这样: ; I; ]+ B! i9 E
9 q( H# J7 m6 |  [6 d  f$ i

  T5 _$ }  C$ n: B2 P  |6 S! b+-----------+----------+-   v1 S1 R! D; Z& I
│ Host │ User │ ...
  ]. b  z2 T9 _5 D  l# ^! I+-----------+----------+- % d0 ]! x  f. b) T  M
│ % │ root │ ... 0 m. {' o& V+ [; j1 v/ c
│ % │ jeffrey │ ... , ]# N+ A& N: i4 a* s
│ localhost │ root │ ... 8 }% M, y& x' k' J- m( H8 ^
│ localhost │ │ ...
/ C. {, C" H; |4 b* P" N. N+-----------+----------+- 3 y/ q& z. F6 m( ~! `0 l, U+ Q
' Y) T; n: y7 l2 B
当服务器在表中读取时,它以最特定的Host值为先的次序排列('%'在
) f1 O: S5 c' J6 ~" G$ L& kHost列里意味着“任何主机”并且是最不特定的)。有相同Host值的条目以
6 I8 o4 R( b2 q( v2 I最特定的User值为先的次序排列(一个空白User值意味着“任何用户”并且
. [. l2 i& `5 ]3 A  k是最不特定的)。最终排序的user表看起来像这样:
! A, H0 S4 \1 W  U6 Q' v, H. r% Q, ^( Q
1 H  }6 [6 Q9 W5 y+ q. O$ ]
+-----------+----------+-
% @) Y! n- d5 X│ Host │ User │ ... 7 ]7 e. N# J9 x- y4 h- A" c7 A
+-----------+----------+-
) u7 l0 K# T' _: w$ s( k9 K+ ^│ localhost │ root │ ... 4 K! v7 \4 C( `6 ^  n" x
│ localhost │ │ ... . Z8 i4 T8 F( k2 t
│ % │ jeffrey │ ...
$ X/ H; n* H& j( V2 H4 r│ % │ root │ ...
6 v8 n+ J& E2 y0 g+-----------+----------+-
. J! H9 e) X# Q+ S- K( {$ }- B0 _# G% e3 K7 f  k* l, c  G
当一个连接被尝试时,服务器浏览排序的条目并使用找到的第一个匹
8 I5 v9 L* c5 V4 c6 J配。对于由jeffrey从localhost的一个连接,在Host列的'localhost'条目
, R5 d1 v5 l, _3 U% i: b首先匹配。那些有空白用户名的条目匹配连接的主机名和用户名。('%'/ 7 O1 Y# r4 M1 T! H9 O+ s$ I# c& b
'jeffrey'条目也将匹配,但是它不是在表中的第一匹配。) ' ^" ^1 B, M9 M8 I. Q6 i
* V8 p3 t, L9 |  G4 s4 J% w% B
这是另外一个例子。假定user桌子看起来像这样:
2 s3 Q7 h+ z4 _" N' \1 V9 m  x$ n% N' M0 E  U3 @' y/ E! W
1 W# v( x: h: @4 q' o+ o
+----------------+----------+- 2 q9 J( r3 Z2 N! j; v
│ Host │ User │ ...
5 c( }9 D, V* L( O1 z+----------------+----------+-
3 w0 _0 k) o1 d) ~/ F9 A( ~1 p│ % │ jeffrey │ ... : E. O% x: B+ M/ y7 R
│ thomas.loc.gov │ │ ...
1 m  P" N3 r; `+----------------+----------+- ' |0 _" t# m, y0 I. u  o) r

* ^& z" [- H4 \* c6 Y; {排序后的表看起来像这样:
" M9 i; Q9 j# g1 E: y! a& K# D; D5 ^) s
+ Y- h& i7 n& O7 L* `( w7 l0 u- J
+----------------+----------+- ! b" r6 N8 U1 V: ^
│ Host │ User │ ... # S2 G+ y$ J( d" b
+----------------+----------+-
$ x' Z% L; o% F8 p% V# j│ thomas.loc.gov │ │ ...
0 x% g" s" S; _$ I│ % │ jeffrey │ ...
( X% W% F- j) M( i1 u+----------------+----------+-
8 n2 u. v% z/ T9 D* B5 q$ P2 M! x! H
6 f+ X1 S1 e! }0 P一个由jeffrey从thomas.loc.gov的连接被第一个条目匹配,而一个由
4 i! ^7 H7 f3 d" S$ cjeffrey从whitehouse.gov的连接被第二个匹配。 ' M% E! ~4 z3 m3 Q$ E- c& E- L
8 k7 M& S* e3 j: J  @) [
普遍的误解是认为,对一个给定的用户名,当服务器试图对连接寻找 : j3 ]2 m0 }/ P$ l4 _6 j4 y
匹配时,明确命名那个用户的所有条目将首先被使用。这明显不是事实。 * z( q% e) K1 K) L( _
先前的例子说明了这点,在那里一个由jeffrey从thomas.loc.gov的连接没
( `* Z' y" u/ a/ e' Z" l9 a6 ~; P. ]被包含'jeffrey'作为User字段值的条目匹配,但是由没有用户名的题目匹 ' X, I+ T7 c3 o& Q* i+ X
配! # ~/ T, ]' |* L2 K
9 X" V4 K1 q& t; w2 f8 d" j
如果你有服务器连接的问题,打印出user表并且手工排序它看看第一个 7 |7 i6 N3 x, l
匹配在哪儿进行。 8 a$ S2 Q! ?% M
/ B# w4 {3 Q- A5 x: ?/ A7 b
存取控制,阶段2:请求证实
( {" Y  [5 E' R" W( \' h/ I# E/ @一旦你建立了一个连接,服务器进入阶段2。对在此连接上进来的每个 ( {; ]5 b/ O+ \- O! J. I9 B4 Q6 @- a
请求,服务器检查你是否有足够的权限来执行它,它基于你希望执行的操作
8 A' x$ f6 x  s, Z/ }类型。这正是在授权表中的权限字段发挥作用的地方。这些权限可以来子
; ?( U& S7 [. b" n3 q- ?! [user、db、host、tables_priv或columns_priv表的任何一个。授权表用 , v/ c; }! w0 ]* e
GRANT和REVOKE命令操作。见7.26 GRANT和REVOKE 句法。(你可以发觉参
+ {' q; p* R6 Q. V1 R4 ~4 o/ b考6.6 权限系统怎样工作很有帮助,它列出了在每个权限表中呈现的字段。) 3 x9 `4 r, d& V6 s. A

7 b* n6 Z% M% Kuser表在一个全局基础上授予赋予你的权限,该权限不管当前的数据库
* k* G; c) t# t, c是什么均适用。例如,如果user表授予你delete权限, 你可以删除在服务器 & O+ H; s& Q5 f3 \
主机上从任何数据库删除行!换句话说,user表权限是超级用户权限。只把
7 x1 V$ D8 E& A0 x5 L' m) k2 Yuser表的权限授予超级用户如服务器或数据库主管是明智的。对其他用户,
6 d- R7 r& Q. ~7 t0 r& d. K5 p) g你应该把在user表中的权限设成'N'并且仅在一个特定数据库的基础上授权,
5 k! Y, `% M+ [5 Q6 {使用db和host表。
" s' l8 i$ L8 [. l. W- V' d$ D. k' m% ~0 g8 E
db和host表授予数据库特定的权限。在范围字段的值可以如下被指定:
- w! d7 `: ~9 Y: {2 ~% r' E% K3 e. r$ R
通配符字符“%”和“_”可被用于两个表的Host和Db字段。 : O* e2 z1 b3 s3 G" \
在db表的'%'Host值意味着“任何主机”,在db表中一个空白Host值意味
) S  t7 n& Q( v1 l, L着“对进一步的信息咨询host表”。
9 y% y/ {4 G8 C/ a' ]# B8 L2 B在host表的一个'%'或空白Host值意味着“任何主机”。
$ A* ]* ~- T; X8 T8 }6 h8 U在两个表中的一个'%'或空白Db值意味着“任何数据库”。
' F: g9 G6 ^8 v) P1 I/ ?在两个表中的一个空白User值匹配匿名用户。
8 R4 o5 u! j5 _5 Rdb和host表在服务器启动时被读取和排序(同时它读user表)。db表在Host " s+ s( V7 Z5 w4 @
、Db和User范围字段上排序,并且host表在Host和Db范围字段上排序。对于
! j- p7 `, U1 F  }8 x# V& G1 Kuser表,排序首先放置最特定的值然后最后最不特定的值,并且当服务器寻找
, k5 J5 o; e6 F8 @) U% S匹配入条目时,它使用它找到的第一个匹配。
# l) K* @; @) {! ]0 s; b& C# \$ J8 K$ L/ Y9 @6 w# _
tables_priv和columns_priv表授予表和列特定的权限。在范围字段的值可
. q$ k  }" b: e# A3 R  b( `以如下被指定: ' s3 t& d4 V: H# _( g5 h1 C
) i0 a. I/ n0 P; E
通配符“%”和“_”可用在使用在两个表的Host字段。
- o+ X: [* T8 V" p' Q  @在两个表中的一个'%'或空白Host意味着“任何主机”。 , X4 A1 T8 w, s7 I
在两个表中的Db、Table_name和Column_name字段不能包含通配符或空白。 ! b0 D7 m) L6 I  V3 {7 c
tables_priv和columns_priv表在Host、Db和User字段上被排序。这类似于 0 h/ S( d; A  \) B8 m. @
db表的排序,尽管因为只有Host字段可以包含通配符,但排序更简单。 ) ?8 M7 K: T: t0 R- O
0 f3 f. ?, X( B* R. m5 ?5 k( E8 s
请求证实进程在下面描述。(如果你熟悉存取检查的源代码,你会注意到这 . w) C6 p$ l5 D1 |1 @
里的描述与在代码使用的算法略有不同。描述等价于代码实际做的东西;它只是
$ y+ g! a8 d- @( C$ f5 p不同于使解释更简单。)
4 D5 U& K) F2 W* g
6 U" M6 G/ w2 i$ B% V对管理请求(shutdown、reload等等),服务器仅检查user表条目,因为那是 ( M. x. V) z2 w5 [& `6 o+ o6 m+ |
唯一指定管理权限的表。如果条目许可请求的操作,存取被授权了,否则拒绝。 7 ]( L( ]6 W- f3 h& i  Y! i3 d
例如,如果你想要执行mysqladmin shutdown,但是你的user表条目没有为你授 + D! w& K8 o' s( T$ h
予shutdown权限,存取甚至不用检查db或host表就被拒绝。(因为他们不包含
" `, F8 t# z( q6 ]! OShutdown_priv行列,没有这样做的必要。) % |# d. x0 Y7 K

1 r5 G- |6 _) p/ J对数据库有关的请求(insert、update等等),服务器首先通过查找user表
. A! u) @  I% G. }, a条目来检查用户的全局(超级用户)权限。如果条目允许请求的操作,存取被授
; H" V/ X2 N& [, ~& `) P5 O# v权。如果在user表中全局权限不够,服务器通过检查db和host表确定特定的用
* m" @' t; m" }, `* d( u# H户数据库权限:
# i) H+ f) n8 L8 l9 [$ ]
4 Q' [  Q) Q( v) Z服务器在db表的Host、Db和User字段上查找一个匹配。 Host和User对应连
) }5 o! n6 i) u; R% c接用户的主机名和MySQL用户名。Db字段对应用户想要存取的数据库。如果没有 0 U: e2 b% x+ ~& u% ^+ m5 w5 S9 E" S, o
Host和User的条目,存取被拒绝。 * M# l" {  ]& j
如果db表中的条目有一个匹配而且它的Host字段不是空白的,该条目定义用
" f- c/ o7 M4 ?+ i户的数据库特定的权限。 ! Y) ~+ p" e1 Z- s
如果匹配的db表的条目的Host字段是空白的,它表示host表列举主机应该被 ; E; F0 j/ `# @# M
允许存取数据库的主机。在这种情况下,在host表中作进一步查找以发现Host和
/ e9 i" N4 y; z: J! b$ R, N' PDb字段上的匹配。如果没有host表条目匹配,存取被拒绝。如果有匹配,用户数
/ ]& [$ x  b9 ?据库特定的权限以在db和host表的条目的权限,即在两个条目都是'Y'的权限的交
. j4 Z3 r* p& w* _, ~# \8 f6 V集(而不是并集!)计算。(这样你可以授予在db表条目中的一般权限,然后用host + ?& L3 F8 x2 M! e
表条目按一个主机一个主机为基础地有选择地限制它们。)
6 K8 U" P+ W( ]0 @, G- ^  d在确定了由db和host表条目授予的数据库特定的权限后,服务器把他们加到
+ C, B4 I% g& B( N由user表授予的全局权限中。如果结果允许请求的操作,存取被授权。否则,服 # {& m: H4 r% a6 `% H2 A- Y; B
务器检查在tables_priv和columns_priv表中的用户的表和列权限并把它们加到
* Z0 K& S$ `2 d/ t; r, g用户权限中。基于此结果允许或拒绝存取。 ' X$ O% m- B" `

- I/ b3 K$ r! e- t; H用布尔术语表示,前面关于一个用户权限如何计算的描述可以这样总结: - l# Y+ D$ g. \$ t; `+ G1 \# Y
% O/ {5 D- m% T$ k
global privileges
  ~/ U3 A4 Y+ T! K' uOR (database privileges AND host privileges) 3 K: @+ z: G( x
OR table privileges
( b* t8 i" m& f, I' GOR column privileges ; B/ `* G2 N9 T
+ w+ V9 L6 C! D  H4 J
它可能不明显,为什么呢,如果全局user条目的权限最初发现对请求的操作不 8 ?1 Q: h: d0 j; ~5 w- u2 q0 }
够,服务器以后把这些权限加到数据库、表和列的特定权限。原因是一个请求可能 % v( {2 y7 g$ g1 }" M, N
要求超过一种类型的权限。例如,如果你执行一个INSERT ... SELECT语句,你就都 ) l0 W0 k+ e% d. A8 p" t
要insert和select权限。你的权限必须如此以便user表条目授予一个权限而db表条 $ a3 U: h* R5 h9 b6 t
目授予另一个。在这种情况下,你有必要的权限执行请求,但是服务器不能自己把
9 B; S/ X) q5 T2 i6 G: }4 i) L- W两个表区别开来;两个条目授予的权限必须组合起来。
( m5 Y# Q, d; c$ L% b
) I6 ^, M& f4 E' i0 Q" F3 P% Hhost表能被用来维护一个“安全”服务器列表。在TcX,host表包含一个在本 7 K9 f4 n/ T: q! F
地的网络上所有的机器的表,这些被授予所有的权限。
' ^+ d6 ?6 s# Z4 G" o+ I; ^% |) C5 R% S8 E. F3 ^6 s
你也可以使用host表指定不安全的主机。假定你有一台机器public.your. , U! I& j; h8 _, N4 j7 m
domain,它位于你不认为是安全的一个公共区域,你可以用下列的host表条目子允 2 h. j7 ]; |! w" z6 |
许除了那台机器外的网络上所有主机的存取:
: s7 x* ^8 t% G, [" I& ?% J7 ~# U: J! t4 G7 l5 p

2 Y8 H; |" Y8 l& x: V+--------------------+----+-
  P. S8 l" y- i: I; d$ J+ B│ Host │ Db │ ...
# j7 y; E& s& ?" A+--------------------+----+- ; L6 X2 v* Q1 }$ m% h1 b
│ public.your.domain │ % │ ... (所有权限设为 'N')
$ [' u& k/ \+ ?( U9 E: s│ %.your.domain │ % │ ... (所有权限设为 'Y')
! J8 }0 W  V1 G: v. a+ A6 x+--------------------+----+- % r" Q, ^# o7 f8 \5 j
! r0 D  v+ z; ?, H6 T( ?3 v
当然,你应该总是测试你在授权表中的条目(例如,使用mysqlaccess)让你确保 + k+ U/ M7 v# a% P! o! |
你的存取权限实际上以你认为的方式被设置。 * V* p# R( n& P" P
, Z5 I# I& O# ^3 Y/ ]& z2 M8 q
权限更改何时生效 7 E: o) d6 j  n
当mysqld启动时,所有的授权表内容被读进存储器并且从那点生效。 + g9 d/ g7 z' M
1 E6 {  e( D+ u" }7 t( Q
用GRANT、REVOKE或SET PASSWORD对授权表施行的修改会立即被服务器注意到。
; u* L7 r, k0 o3 m4 i+ i$ X& D
: W# n/ o. B% r7 p6 H, v; d1 U" H如果你手工地修改授权表(使用INSERT、UPDATE等等),你应该执行一个FLUSH % W/ G3 g: Y, t
PRIVILEGES语句或运行mysqladmin flush-privileges告诉服务器再装载授权表,否
1 C+ w6 B; M) k, p) V则你的改变将不生效,除非你重启服务器。 $ H8 x: F- R4 P( N0 q  ^
- K" H0 h, k; Y8 X# U$ {9 u/ _: N
当服务器注意到授权表被改变了时,现存的客户连接有如下影响:
0 ^+ m$ s2 p+ t4 s  L/ |! c9 O- k* [( m) Z% P3 Y
表和列权限在客户的下一次请求时生效。 2 o+ [( y( d8 G1 [/ k; A8 i! \
数据库权限改变在下一个USE db_name命令生效。 8 Z2 X+ f0 `3 k2 A* s: L5 R
全局权限的改变和口令改变在下一次客户连接时生效。 5 P4 Y, G1 V; H' Y# ~' a) q( N0 H
  j) ~* D7 U$ x* p; c
建立初始的MySQL权限
. `2 ^6 e. I6 i$ m在安装MySQL后,你通过运行scripts/mysql_install_db安装初始的存取权限。
, u- S+ h  x( c& l8 ?7 rscripts/mysql_install_db脚本启动mysqld服务器,然后初始化授权表,包含下列 ; ?6 L4 m; F' X3 g9 J+ [5 d
权限集合:
& q# K1 z: S/ F$ s& m) K! h; J1 j& t3 |& @6 M
MySQL root用户作为可做任何事情的一个超级用户被创造。连接必须由本地主 3 g: K7 N8 f/ _' n3 L% \9 \
机发出。注意:出世的root口令是空的,因此任何人能以root而没有一个口令进行 ! }: s: e7 i& L' E$ ?6 S0 E  g
连接并且被授予所有权限。
5 l: o% N5 ~# f一个匿名用户被创造,他可对有一个'test'或以'test_'开始的名字的数据库
2 N  Y) M- t$ h% _* c) f( d做任何时期事情,连接必须由本地主机发出。这意味着任何本地用户能连接并且视
' n8 s/ n. b, n  _5 p3 c4 Y% J为匿名用户。 / n& q9 J) g6 X. ~- ]2 a+ W
其他权限被拒绝。例如,一般用户不能使用mysqladmin shutdown或
5 i6 c3 ?* E& E/ G# Tmysqladmin processlist。 " Y' y0 f! F- E* h4 c2 F5 {1 t$ b$ R
注意:对Win32的初始权限是不同的。
  D! f4 U' ^1 V" x3 ^( Z+ t% l1 [0 o3 Y7 S# {
既然你的安装初始时广开大门,你首先应该做的事情之一是为MySQL root用户
. a! s9 u4 ^9 I3 r1 L  e. s指定一个口令。你可以做如下(注意,你使用PASSWORD()函数指定口令): + z+ V/ ?5 O; ]7 r1 f/ W1 `

  G% J+ l9 E0 eshell> mysql -u root mysql
( W( W. _& R. O$ @6 {mysql> UPDATE user SET Password=PASSWORD('new_password') - C8 S# l) S# U' y  {! }( p9 H$ Z7 P
WHERE user='root';
! A+ |4 t; U0 [6 e% Y, s  m# Amysql> FLUSH PRIVILEGES;   w& @$ s  q5 Q  Y3 x7 K+ O3 g
8 F  t3 r+ Q/ }, ~. a, L& a) a
在MySQL 3.22和以上版本中,你可以使用SET PASSWORD语句:
+ n1 C, T1 S# Q4 f: C  z" }2 x8 ]* p
shell> mysql -u root mysql 0 r, r  T8 s( `7 f
mysql> SET PASSWORD FOR root=PASSWORD('new_password'); * p7 x2 d+ X! I( K$ R9 k  o' t2 ?

' r! O) b. g7 v( i* S4 |设置口令的另一种方法是使用mysqladmin命令:
& `1 P* A/ S7 o, I% s
& v: x0 L: w0 ^% K+ _shell> mysqladmin -u root password new_password : v# d2 A7 y' [

! D1 R, r" N0 Q8 I  A注意:如果你使用第一种方法在user表里直接更新口令,你必须告诉服务器 - P" W" s9 W- R' s
再次读入授权表(用FLUSH PRIVILEGES),因为否则改变将不被注意到。 ) q& v) d! t' P5 N5 d! W8 O
, F" r% U( f) f1 G7 }5 ^( c
一旦root口令被设置,此后当你作为root与服务器连接时,你必须供应那个
$ ]  w/ o) U5 }" Y口令。
& s7 _( ?6 f" X. b0 `' f; }2 K& T* ]- C% Z7 E! a7 ]$ t, C
你可能希望让root口令为空白以便当你施行附加的安装时,你不需要指定它
& A( |- X) v  g3 D/ m6 C2 ]或测试,但是保证在任何真实的生产工作中使用你的安装之前,设置它。 " r1 Q, U4 k2 `% B# J0 |4 |7 O
1 U# U5 u' |) c5 t7 x: G7 O7 M0 b1 W
看看scripts/mysql_install_db脚本,看它如何安装缺省的权限。你可用它
8 g6 L$ O0 J) X6 a) B, p' w: A作为一个研究如何增加其他用户的基础。 ' R1 Q# L) J6 M- Y

) M; ], |2 O+ a% p* q如果你想要初始的权限不同于上面描述的那些,在你运行mysql_install_db
% X* [2 P' J- V' D& e之前,你可以修改它。 ! |3 a$ x$ _* q6 g4 O

: o: Z* ^7 `) k! |/ t* S3 j为了完全重建权限表,删除在包含mysql数据库的目录下所有“*.frm”, 5 h7 B# ]) {) W1 [9 T3 w
“*.MYI”和“*.MYD”文件。(这是在数据库目录下面命名为“mysql”的目录,
; S2 C* K: b  t4 N& i当你运行mysqld --help时,它被列出。)然后运行mysql_install_db脚本,可能 ; R1 k7 ]' D! ~: n9 h
在首先编辑它拥有你想要的权限之后。 3 j) {  t5 K; a2 \% {

- |- e4 o# S. x" s, {- T$ K& h7 f* a( i注意:对于比MySQL 3.22.10旧的版本,你不应该删除“*.frm”文件。如果
4 v9 q& ~4 [$ Q6 h+ m' d% E你偶然做了,你应该在运行mysql_install_db之前你的MySQL分发中拷回它们。 " h, u, E7 c8 R( J! Q

: f0 j; m- N: F2 o$ W8 J向MySQL增加新用户权限 & o8 [0 q) v$ ?; e" w' m6 P: A
你可以有2个不同的方法增加用户:通过使用GRANT语句或通过直接操作MySQL授
6 Q1 {$ ]( i8 b5 r权表。比较好的方法是使用GRANT语句,因为他们是更简明并且好像错误少些。 , [( p7 K7 E1 |) {% b1 t
$ `+ r3 B" v5 s: l/ J5 H
下面的例子显示出如何使用mysql客户安装新用户。这些例子假定权限根据以前 + L/ ~1 a) e+ ]& c* i3 i
的章节描述的缺省被安装。这意味着为了改变,你必须在mysqld正在运行同一台 , g0 k; Y: Q, ^( R
机器上,你必须作为MySQL root用户连接,并且root用户必须对mysql数据库有 + S1 S) e! Z5 t- {8 [: e5 @1 l
insert权限和reload管理权限。另外,如果你改变了root用户口令,你必须如下 . X( D$ x/ u7 V( m5 d$ N+ Y% H
的mysql命令指定它。
4 o; I- ^1 k, I4 y( s; n* Y! ?! M( L
你可以通过发出GRANT语句增加新用户:
3 Z* D; {/ J5 f
" H: y  l" @: @  g: Wshell> mysql --user=root mysql
9 w  ^0 p+ }# y, Lmysql> GRANT ALL PRIVILEGES ON *.* TO monty@localhost
% `! o) m2 f: \IDENTIFIED BY 'something' WITH GRANT OPTION; % Z. `1 Z! D7 ^- n7 O6 G7 ]
mysql> GRANT ALL PRIVILEGES ON *.* TO monty@"%"
2 @8 F/ L8 ~& g, B3 dIDENTIFIED BY 'something' WITH GRANT OPTION; : V! N5 w3 m1 W
mysql> GRANT RELOAD,PROCESS ON *.* TO admin@localhost; + x& r" O( S2 t5 k' Q
mysql> GRANT USAGE ON *.* TO dummy@localhost; + `2 e2 Z, c1 n6 V2 d% @' B
  W* W  w( C) [2 c7 R0 ^# G  }
这些GRANT语句安装3个新用户: $ Y+ _$ S* L: b

  Z0 X( `# ]6 Wmonty
$ L, v/ j, |$ x# x4 T5 ^& u" e& z可以从任何地方连接服务器的一个完全的超级用户,但是必须使用一个 7 u# n# z# I* m" |$ S5 m: J
口令('something'做这个。注意,我们必须对monty@localhost和monty@"%"
; n7 T9 k1 I; m: |发出GRANT语句。如果我们增加localhost条目,对localhost的匿名用户条目
3 `- n1 O- ]+ C3 y在我们从本地主机连接接时由mysql_install_db创建的条目将优先考虑,因为 % z' h6 y' d1 N7 P0 d% N, B
它有更特定的Host字段值,所以以user表排列顺序看更早到来。 , t& a6 d' X1 r* ~( q& t
admin
; S; Z% f6 [- o  x可以从localhost没有一个口令进行连接并且被授予reload和process管理
/ X5 }, S7 I; g+ d; ~8 S8 Y权限的用户。这允许用户执行mysqladmin reload、mysqladmin refresh和 # E2 `! d5 E  b- S/ P: x2 o5 c% p8 w
mysqladmin flush-*命令,还有mysqladmin processlist。没有授予数据库有
+ S) V% L( i- [7 w4 w" x3 h关的权限。他们能在以后通过发出另一个GRANT语句授权。   ?* x" I8 {5 c7 Q- n5 p
dummy ) _! G) {6 v6 Y; M) n2 q. u. c
可以不用一个口令连接的一个用户,但是只能从本地主机。全局权限被设
8 A, q# s* N8 c# N6 f置为'N'--USAGE权限类型允许你无需权限就可设置一个用户。它假定你将在以 0 e. `$ }% W! _/ [- E2 r* V
后授予数据库相关的权限。
. G3 ], A( X7 e/ `" x6 R7 ?( n你也可以直接通过发出INSERT语句增加同样的用户存取信息,然后告诉服   h. _) o) P. a" W( ~
务器再次装入授权表: 0 r3 P# a, ?: }) f5 y9 K8 \" C

8 _9 |9 C4 @2 z" `shell> mysql --user=root mysql : `  a6 Q" ?5 h0 i* [
mysql> INSERT INTO user VALUES('localhost','monty',PASSWORD 4 i" x" T, W0 j5 V! }: E6 W  e
('something'), * w" B, Y. x2 I) r
'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y',
8 x8 f+ b2 e1 [( ?'Y','Y')
4 v  A, z' V) B; R% {mysql> INSERT INTO user VALUES('%','monty',PASSWORD('something'),
( t2 I: I3 T' k* L7 v'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y',
' K! \* r2 p9 }) n'Y')
4 W! x, c6 F0 t+ P& V, U/ gmysql> INSERT INTO user SET Host='localhost',User='admin', $ S6 Q5 j4 ]! D2 e
Reload_priv='Y', Process_priv='Y';
9 h3 P" D5 u0 H. P+ I' [mysql> INSERT INTO user (Host,User,Password) 2 s8 h4 R5 w' K1 U5 h/ T
VALUES('localhost','dummy',''); 4 h& }. V$ x& s" m' x% s
mysql> FLUSH PRIVILEGES;
( ^( y2 X. x7 P. m  b$ E1 `. k( v& `# L: X
取决于你的MySQL版本,对上述,你可能必须使用一个不同数目'Y'值(在
; W2 J# O  z% w. _. ~7 H3.22.11以前的版本有更少的权限列)。对admin用户,只用在3.22.11开始的版
' {7 y4 _: [: O3 d1 f* S本具有的更加可读的INSERT扩充的语法。 / F9 I3 d, F9 ]9 |! z2 _
, }  l( d# `1 ^
注意,为了设置一个超级用户,你只需创造一个user表条目,其权限字段设为 : _5 J: d) G4 r$ Q6 r! ]
'Y'。不需要db或host表的条目。 - h; `, n9 ]! Q4 x$ o3 n* _/ e

$ ]5 ?7 }% H% G' F) P" q3 L" T在user表中的权限列不是由最后一个INSERT语句明确设置的(对dummy用户), # M- B  a3 c- P. F
因此那些列被赋予缺省值'N'。这是GRANT USAGE做的同样的事情。
" V" |. u2 ?- z& p
$ G  m* O% o+ _" }7 s# X$ Y, \- f下列例子增加一个用户custom,他能从主机localhost、server.domain和 1 E; q. @; i5 X$ B
whitehouse.gov连接。他只想要从localhost存取bankaccount数据库,从 7 W; E' k, K4 F. `& L- @
whitehouse.gov存取expenses数据库和从所有3台主机存取customer数据库。他 8 w% `* x# Y; @6 `% g. v& W
想要从所有3台主机上使用口令stupid。
. s, n* O4 [' C8 r, T: N0 ^1 V( W, t  F: f# c" v
为了使用GRANT语句设置个用户的权限,运行这些命令:
( O5 o0 V7 ]5 h  `, P. A* r0 w2 v
shell> mysql --user=root mysql * \0 b/ f6 e" p1 u  ]
mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP 4 z0 a. r' r! H/ f1 q  }
ON bankaccount.* 2 Z  S% ?% U& h0 Y6 ]* N
TO custom@localhost
# X# R4 Q2 R+ K' z" RIDENTIFIED BY 'stupid'; : H9 r4 }4 j7 v' p% x2 D9 x! K
mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
+ q* ~2 r$ H* I6 d) N4 _ON expenses.*
4 a- J5 _) N7 c( GTO custom@whitehouse.gov
$ s/ N: K; ~; b4 LIDENTIFIED BY 'stupid';
5 I3 T2 U  u6 P- i& H3 W6 f, t" Dmysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
: c$ O5 N& r: G% uON customer.* + [) {0 N" M. @
TO custom@'%' ' G- T* g2 l4 L+ `+ l! R
IDENTIFIED BY 'stupid';
* _! z) e% R& D& A8 V
$ T3 @1 ]2 |, t" w! c通过直接修改授权表设置用户权限,运行这些命令(注意,在结束时 2 U( `( k3 k( E
FLUSH PRIVILEGES): % D$ h4 }3 N; Z7 t
0 @$ l& m* z1 R7 d$ V
shell> mysql --user=root mysql : w4 j6 x8 r% W8 k: R
mysql> INSERT INTO user (Host,User,Password)
# V6 y* d9 B7 B  c+ L, i* ]. [& h. {VALUES('localhost','custom',PASSWORD('stupid')); 9 Q$ Y" I; i# }
mysql> INSERT INTO user (Host,User,Password) + ^5 z4 W- k7 O
VALUES('server.domain','custom',PASSWORD('stupid')); 2 z5 _  p, T4 H
mysql> INSERT INTO user (Host,User,Password)
4 s/ Z0 F3 [4 J& h  \( z+ _VALUES('whitehouse.gov','custom',PASSWORD('stupid')); $ p, U3 D" ~; l, R6 o
mysql> INSERT INTO db ' J8 _3 _0 _; X: l+ w( D# |2 J
(Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv,
) B, F, ?( F. j2 s3 X! FCreate_priv,Drop_priv) . ]" \5 Q* K) f7 Q8 n7 |) d
VALUES
& A1 e3 w6 d* ?; a/ g('localhost','bankaccount','custom','Y','Y','Y','Y','Y','Y');
- _, y1 h+ P$ f) C" w3 o- {% v5 lmysql> INSERT INTO db
% x3 e; w( N) Z6 j(Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv,
: F: [% r7 s# c4 bCreate_priv,Drop_priv)
. j. Y" o4 R. M6 k2 sVALUES 2 _9 e3 S) i7 F0 d1 k
('whitehouse.gov','expenses','custom','Y','Y','Y','Y','Y','Y');
8 Z5 c- \5 g9 x8 l" Y8 Smysql> INSERT INTO db
+ o0 k9 i$ X5 w# K8 U- s& g(Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv, ( B& E$ V. ]- G8 [1 F+ _: b
Create_priv,Drop_priv) 0 `1 e% ]5 G9 w7 n2 V
VALUES('%','customer','custom','Y','Y','Y','Y','Y','Y'); , B$ y9 @* l3 K* V, |- w( L
mysql> FLUSH PRIVILEGES; ' K* `" r2 _! G& a7 M' D
9 ]1 u" H9 X. H4 g: s- R+ x8 b. y4 w
头3个INSERT语句增加user表条目,允许用户custom用给定口令从不同的主机 * J. s( L- u: ~+ m7 n3 ^
进行连接,但是没有授予任何许可(所有权限被设置为缺省值'N')。后3个INSERT
5 t) u* l1 Q& ^4 o语句增加db表条目,授予custom以bankaccount、expenses和customer数据库权限, 4 O' h* k: W; L% z
但是只能在从正确的主机存取时。通常,在授权表直接被修改时,服务器必须被告 3 O, \- [3 D2 v/ K/ z) U
知再次装入他们(用FLUSH PRIVILEGES)以便使权限修改生效。 / I. i/ u5 j' j' J
9 {7 k& ?- c- Q; ^; E( Y, t9 @6 E
如果你想要给特定的用户从一个给定的域上的任何机器上存取权限,你可以发 3 x* a; U$ b+ L, e5 i
出一个如下的GRANT语句: $ n! A/ ^6 E) F; F0 D
( m0 T. W; x6 w  ]) `* \# w
mysql> GRANT ...
- T+ @5 r3 D0 [! cON *.*
6 ?1 Q) C8 p$ K: A, f1 t7 H' ^/ l6 xTO myusername@"%.mydomainname.com"
( J8 D6 ]1 g3 o1 ^5 E+ G- vIDENTIFIED BY 'mypassword';
2 J6 j7 E/ J* e' X$ e% |# O0 C  {, e
为了通过直接修改授权表做同样的事情,这样做:
* @1 e7 S( ^% r2 q8 h* i/ m$ Q/ y/ {7 E
mysql> INSERT INTO user VALUES ('%.mydomainname.com', 'myusername',
( Q# Z3 E& D! K7 G& {6 P% f: t! u! gPASSWORD('mypassword'),...); & u5 C$ U# Y5 k' k
mysql> FLUSH PRIVILEGES;
7 }; c* G+ X7 V( M0 ?/ R+ L; I; M" I4 p7 `9 ~6 G
你也可以使用xmysqladmin、mysql_webadmin甚至xmysql在授权表中插入、改变
' J9 X+ [+ d% H5 B: n和更新值。你可以在MySQL的Contrib目录找到这些实用程序。 / |8 b. q# g" _# N
( Q" J& ~$ r+ f) {
怎样设置口令 7 S# Q& T( G( `" V& W
在前面小节的例子里说明了一个重要的原则:当你使用INSERT或UPDATE语句存 5 L- ~- j( O- @7 y+ ^+ s2 K' p
储一个非空的口令时,你必须使用PASSWORD()函数加密它。这是因为在user表中以 ! W2 S5 f% N% R5 M
加密形式存储口令,而不是作为纯文本。如果你忘记这个事实,你可能像这样试图
2 W1 n9 q# b: |1 }+ C设置口令:
& |' r6 _5 X: e
1 e% E+ s6 A2 o2 Pshell> mysql -u root mysql ) R- z+ y+ R; M9 |8 F* }0 r% ]
mysql> INSERT INTO user (Host,User,Password) VALUES('%','jeffrey', ! I! N7 k# ~2 ~: I0 m4 U
'biscuit');
) P& A3 I7 t0 h: r1 Y, Imysql> FLUSH PRIVILEGES
( ^) S! W( U' z4 i# t  R: P
1 R. P% M, H& \结果是纯文本值'biscuit'作为口令被存储在user表中。在用户jeffrey试图用
7 _; U9 d( Q' T$ n+ ]' G, Y8 a这个口令连接服务器时,mysql客户用PASSWORD()加密它并且将结果送给服务器,服 1 n; @4 v+ }' S& e
务器比较在user表中的值(它是纯文本值'biscuit')和加密的口令(而不是
. l- @6 ], n/ Y3 p6 D7 i'biscuit'),比较失败并且服务器拒绝连接:
0 d; w4 z8 {9 u) a1 N( e  j
( |: I. ?5 A; c" Kshell> mysql -u jeffrey -pbiscuit test
, P% \* h9 k6 |- v' O$ w5 xAccess denied + z' F% ?9 V3 V; h6 b8 A

! R7 r3 |" D+ {! `  x  w8 q7 `" c因为当他们被插入user表时,口令必须被加密,相反,INSERT语句应该象这样
1 I' \& w3 d. v$ l被指定:
3 B  M7 ?4 e1 V' ?3 o, S/ K& W* {
: z& d; H$ z) i& L. p! e" Dmysql> INSERT INTO user (Host,User,Password)
6 S' G4 q6 r6 y' xVALUES('%','jeffrey',PASSWORD('biscuit'));
: E* f. m# G* f# \4 i/ t& X) V- a. F  _
当你使用SET PASSWORD语句时,你也必须使用PASSWORD()函数:
% Y4 i, _, m& y- D) [& K) y! ~; O+ g6 m; u
mysql> SET PASSWORD FOR jeffrey@"%" = PASSWORD('biscuit');
( ?8 |& W! X5 o* n2 b6 L
( d2 J8 E' e' Y( ~+ m如果你使用GRANT ... IDENTIFIED BY语句或mysqladmin password命令设置口
; F: B. E) [# m% T1 A2 Z- D令,PASSWORD()函数是不必要的。他们都考虑到为你加密口令,多以你可像这样指 * ~% Q4 N7 i* L0 d9 ]
定一个口令'biscuit': 8 g0 I' T, l- k+ Y0 ]2 i

1 ]. G+ L! l# `- Q$ _mysql> GRANT USAGE ON *.* TO jeffrey@"%" IDENTIFIED BY 'biscuit'; 7 S; \* S- @( n+ y! E
! D5 ~' ~8 [8 V' ^- X, z& s) s( q

2 J! c" }& K3 M3 c0 E6 R% d" D# m
: t8 X$ y2 |, o- E4 pshell> mysqladmin -u jeffrey password biscuit
  ^3 U, W& x! W" }) U/ U4 C( e注意: PASSWORD()不是以在Unix口令加密的同样方法施行口令加密。你不应
& N1 ^9 v- C. c- ~该假定如果你的Unix口令和你的MySQL口令是一样的,PASSWORD()将导致与在Unix
; O% i% {" f% s9 t% [. q口令文件被存储的同样的加密值。见6.2 MySQL 用户名和口令。
. {9 K5 O+ l, @' D: s. }* p8 U
& _* L/ m( e6 A( B4 }6 d( G6 XAccess denied错误的原因 # k; C6 F2 t- r9 G/ ^$ O
当你试着联接MySQL服务器时,如果你碰到Access denied错误,显示在下面 9 a6 ^. x- y' J; u( u* F* |: `
的表指出一些你能用来更正这个问题的动作: " m1 a/ Z8 i. A1 f' _, s
, @, H6 }3 e8 \$ V/ H; D
你是在安装MySQL以后运行mysql_install_db的脚本,来设置初始授权表内容 , t- ]! }% O* j8 @/ Q
吗?如果不是,这样做。见6.10 设置初始MySQL权限。通过执行这个命令测试初
/ s0 i  z- a) j2 x2 E始权限: ; b3 d0 }/ h% s5 `2 [& Y; k; K0 X
shell> mysql -u root test : Y, \* O8 `9 k. q$ ]1 C

" X2 k( J  a& f5 Y8 G* M服务器应该让你无误地连接。你也应该保证你在MySQL数据库目录有一个文件 ( E4 r# }9 I" o5 N$ S
“user.MYD”。通常,它是“PATH/var/mysql/user.MYD”,在此PATH是MySQL安
, l6 L! B: X* p% y, D; a- W  {: @" ?装根目录的路径。
. y' J+ s7 z/ C6 \; v/ ^9 F
& ]: j. n) ^( e! n! [" \, z在一个新的安装以后,你应该连接服务器并且设置你的用户及其存取许可:
$ T$ M% l- {. \1 `8 G- Nshell> mysql -u root mysql 4 J' f5 O5 J/ K( \4 [! J

5 Y. r0 f" X' J$ `, ~! C7 N服务器应该让你连接,因为MySQL root用户初始时没有口令。既然那也是一个
9 S' E, X5 ^0 [* L安全风险,当你正在设置其他MySQL用户时,设定root口令是一件重要的事请。如
7 @' B+ m2 }% q' f2 K果你作为root尝试连接并且得到这个错误:   K$ o  _/ i  H' X9 T3 H3 m, S- S
1 ~+ r+ q( u" T5 p  M* U
Access denied for user: '@unknown' to database mysql
: a6 Q1 T4 u  d. M4 h0 h  S$ ^( B4 s+ @, A( n1 K
这意味着,你没有一个条目在user表中的一个User列值为'root'并且mysqld
. k$ Q& D* V5 u! x不能为你的客库解析主机名。在这种情况下,你必须用--skip-grant-tables选项
" G9 z9 d3 L$ M- P- S$ Y' e重启服务器并且编辑你的“/etc/hosts”或“\windows\hosts”文件为你的主机 4 v. c  o$ \+ c+ X; B* q: U
增加一个条目。 3 [0 |& b4 _5 N' `! C
5 C; n" y. t" `" D* P
如果你从一个3.22.11以前的版本更新一个现存的MySQL安装到3.22.11版或以 - ~3 j8 q+ B- ]" }; s
后版本,你运行了mysql_fix_privilege_tables脚本吗?如果没有,运行它。在 4 `% s9 n0 c4 N5 ~9 @8 {# W7 s
GRANT语句变得能工作时,授权表的结构用MySQL 3.22.11修改 。 & A' g' `/ r- a+ X' g, t
如果你直接对授权表做修改(使用INSERT或UPDATE语句)并且你的改变似乎被
7 T; g" |; J: [) G' J9 h4 s忽略,记住,你必须发出一个FLUSH PRIVILEGES语句或执行一个mysqladmin 1 \; {8 k# U6 o
flush-privileges命令导致服务器再次读入表,否则你的改变要道下一次服务器被
6 j% p) @& K0 E重启时再生效。记住在你设定root口令以后,你将不需要指定它,直到在你清洗
4 i. p9 D6 W& k2 F# O(flush)权限以后,因为服务器仍然不会知道你改变了口令!
% I, \5 o9 O+ q* ~+ S8 c: E如果你的权限似乎在一个会话(session)当中改变了,可能是一个超级用户改变 * I6 `5 X. z1 \+ ]
了他们。再次装入授权表作用于新客户连接,但是它也影响现存的连接,如6.9 权
9 T; U1 R3 r) j: r限改变何时生效小节所述。
4 v% t& X! N- F0 v4 R为了测试,用--skip-grant-tables选项启动mysqld守护进程,然后你可以改变
9 h" T/ H% {( q+ TMySQL授权表并且使用mysqlaccess脚本检查你的修改是否有如期的效果。当你对你的 / z: |5 {9 M3 D$ o3 M
改变满意时,执行mysqladmin flush-privileges告诉mysqld服务器开始使用新的权   S& [5 f* U0 n
限表。注意:再次装入授权表覆盖了--skip-grant-tables选项。这允许你告诉服务 % U. v9 C0 J3 h% U0 }- u) [
器开始使用授权表,而不用停掉并重启它。 / d4 ~9 o# O0 u
如果你有一个Perl、Python或ODBC程序的存取问题,试着用mysql -u user_name 5 s0 B5 C, L% \5 G: X
db_name或mysql -u user_name -pyour_pass db_name与服务器连接。如果你能用
$ t8 M: ?1 F+ P3 V! t- Lmysql客户连接,这是你程序的一个问题而不是存取权限的问题。(注意在-p和口令
# O: x1 F1 I8 Q6 ?2 b1 u之间没有空格;你也能使用--password=your_pass句法指定口令。) ) J/ }" H: b3 z- W& F4 v. i! b
如果你不能让口令工作,记得如果你用INSERT, UPDATE或SET PASSWORD语句
% \% K3 V+ ]- u% U6 l3 P1 ^3 [4 Q设置口令,你必须使用PASSWORD()函数。如果你用GRANT ... INDENTIFIED BY语 1 Y0 Z9 g$ h- t4 S" C6 d
句或mysqladmin password命令指定口令,PASSWORD()函数是不需要的。 : \/ f  O% S) j
localhost是你本地主机名的一个同义词,并且也是如果你不明确地指定主机 ; i! h3 e1 Q& e# {
而客户尝试连接的缺省主机。然而,如果你正在运行于一个使用MIT-pthreads的系 6 J3 t( v: M( C3 Z% h4 a7 W
统上,连接localhost是不行的(localhost连接使用Unix套接字进行,它没被 MIT 2 `( O% @& o1 S+ b% S2 v3 |# W
-pthreads支持),为了在这样的系统上避免这个问题,你应该使用--host选项明确
5 E. z0 I: i% r0 _& j$ R3 X8 `地命名服务器主机,这将做一个 TCP/IP连接到mysqld服务器。在这种情况下,你
6 Y1 v( s. C' z! Y3 p& Y  C, C  i3 h必须有在服务器主机上的user表中条目的你真实的主机名。(即使你在服务器同一
% A9 r2 I$ w1 W" }0 x1 S* F9 z1 I, I台的主机上运行一个客户程序,这也是真的。) - w0 r2 ^6 Y4 c7 u
当尝试用mysql -u user_name db_name与数据库连接时,如果你得到一个 , W# v7 r+ r! r9 w- p" m
Access denied错误,你可能有与user桌有关的问题,通过执行mysql -u root & r2 A+ m5 w# V$ S5 X! F3 r) q
mysql并且发出下面的SQL语句检查: 6 I4 [$ z: q  e* c% M- d7 _
mysql> SELECT * FROM user;
2 O& E8 {( f+ c, I" \, A0 ]
/ D, Z- ~  [+ _0 ~% A0 `& b) k2 K结果应该包含一个有Host和User列的条目匹配你的计算机主机名和你的MySQL用户
( I' @0 i6 Q% E% b" E+ D! G5 i名。
, b: _- Q" l* \1 A2 r' T. I4 O3 K7 A, O; o$ n9 X* @$ W% F
Access denied错误消息将告诉你,你正在用哪个用户尝试登录,你正在试图
% u& G( D8 s$ K" ?/ i# ~用连接哪个主机,并且你是否正在使用一个口令。通常,你应该在user表中有一 7 |8 U, ~% u* t3 L4 T
个条目,正确地匹配在错误消息给出的主机名和用户名。
. c$ M5 O- Y7 o! E5 c/ n如果当你试着从一个不是MySQL服务器正在运行的主机上连接时,你得到下列
1 F( Q+ _1 D5 R: g) Q" D) K6 J5 C错误,那么在user表中没有匹配那台主机行: 8 g1 l0 q4 S3 Q( m
Host ... is not allowed to connect to this MySQL server
$ b6 d# ~) |3 q
/ F* j4 _) N# W你可以通过使用mysql命令行工具(在服务器主机上!)修正它,把你正在试
. k/ a; {9 Z$ _) C* i图连接的用户/主机名组合新加一行到user表中。如果你不在运行MySQL 3.22并且
9 R8 G3 f4 E5 y$ S0 I你不知道你正在从它连接的机器的IP数字或主机名,你应该把一个'%'条目作为 + R, a+ C& L1 k6 i0 t
Host列值放在user表中并且在服务器机器上使用--log选项重启mysqld。在试图从 5 y) g% Z1 Z2 ^. o9 Z5 E
客户机器连接以后,在MySQL记录文件中的信息将显示你如何真正进行连接。( 7 d& ?1 h$ a& D. T  N6 I
然后用在记录文件上面显示出的实际的主机名代替user表中的'%'条目。否则, 2 c2 h$ `1 p, ?
你将有一个不安全的系统。) " [' m# O4 j8 ~; Y) w

- o7 D! |' N! ]9 s5 u) j如果mysql -u root test工作但是mysql -h your_hostname -u root test
: o/ ^8 t) u1 T1 e( K. p" F导致Access denied,那么在user表中你可能没有你的主机的正确名字。这里的 % R+ o. ]$ G& V$ w+ p7 o+ H
一个普遍的问题是在user表条目中的Host值指定一个唯一的主机名,但是你系统
- H2 G  C3 C4 s8 X6 q# M' E的名字解析例程返回一个完全正规的域名(或相反)。例如,如果你在user表中有
! L, v6 B, f* M: y( g9 e- M一个主机是'tcx'的条目,但是你的 DNS告诉MySQL你的主机名是'tcx.subnet. - j6 O! z# \  t+ W: u
se',条目将不工作。尝试把一个条目加到user表中,它包含你主机的IP数字作 + H9 M6 a% X$ J. c/ I8 I* e3 m, V9 n
为Host列的值。(另外,你可以把一个条目加到user表中,它有包含一个通配符
. D( R2 d7 J9 s% F如'tcx.%'的Host值。然而,使用以“%”结尾的主机名是不安全的并且不推荐!)
7 r" e  W- R- d# z  Y' |如果mysql -u user_name test工作但是mysql -u user_name other_db_name 5 Z/ C9 l3 k" X' a- G, r" _
不工作,对other_db_name,你在db表中没有没有一个条目列出。 % N0 D! {" t9 ^
当在服务器机器上执行mysql -u user_name db_name时,它工作,但是在其
( k' ?- Z% {8 s9 T( @* n它客户机器上执行mysql -h host_name -u user_name db_name时,它却不工作,
! {  _4 X5 A$ q- m你没有把客户机器列在user表或db表中。
3 {% j" I7 o- W! d1 b: j6 h5 K  ?如果你不能弄明白你为什么得到Access denied,从user表中删除所有Host 1 R- E+ x0 d. g' o: J
包含通配符值的条目(包含“%”或“_”的条目)。一个很普遍的错误是插入用 , Q$ j/ s, {+ _2 [
Host='%'和User='some user'插入一个新条目,认为这将允许你指定localhost
7 }3 x: Y2 B: E/ @' o从同一台机器进行连接。它不工作的原因是缺省权限包括一个有Host='localhost' " E( o% i3 N1 ]' v, p: N. P5 o- F# _/ `
和User=''的条目,因为那个条目一个比'%'更具体的Host值'localhost',当从 + N3 _6 k  L6 I( a, Z6 _+ [
localhost连接时,它用于指向新条目!正确的步骤是插入Host='localhost'和
6 P* `& A- C4 U: T3 P! PUser='some_user'的第2个条目,或删除Host='localhost'和User=''条目。
' }' Y, w7 a' j' i9 k  r0 @如果你得到下列错误,你可以有一个与db或host表有关的问题: ) B' Q) d. d# z1 e9 l
Access to database denied 4 }3 j- W! ]9 B% G* |

  W1 u9 |( O) l$ I如果从db表中选择了在Host列有空值的条目,保证在host表中有一个或多
, m3 A. k% g7 W% X个相应的条目,指定运用db表中的哪些主机。如果在使用SQL命令SELECT ... " u$ F' m; y% F) u/ L
INTO OUTFILE或LOAD DATA INFILE时,你得到错误,在user表中的你的条目可 5 w9 [3 Q+ u( w7 b* b
能启用file权限。
3 i) ]' Q; @$ F: v9 U9 c+ Z' q5 R  z  a
记住,客户程序将使用在配置文件或环境变量被指定了的连接参数。如果 ! l1 q4 ]. z" N# ^
当你不在命令行上指定他们时,一个客户似乎正在发送错误的缺省连接参数,
) h* s& {" z; M/ p2 O检查你的环境和在你的主目录下的“.my.cnf”文件。你也可以检查系统范围 . k0 u6 c. ^. E6 A; |
的MySQL配置文件,尽管更不可能将在那里指定那个客户的连接参数。如果当 2 d. I0 a: K% G- i+ k) ?# l; o
你没有任何选项运行一个客户时,你得到Access denied,确认你没在任何选 - a4 B' h2 M/ f8 b1 R6 p& D
项文件里指定一个旧的口令!见4.15.4 选项文件。
1 _9 s4 N4 e4 S7 T9 Y& ?0 j# b, @  I4 \如果任何其它事情失败,用调试选项(例如,--debug=d,general,query)
' `7 I% \; R  X/ s* ?启动mysqld守护进程。这将打印有关尝试连接的主机和用户信息,和发出的每
  J$ f; a, _% L: g; @3 r, j7 B# X, I个命令的信息。见G.1 调试一个MySQL服务器。 # p4 z$ P7 q7 n8 e' c: a( X, I3 f
如果你有任何与MySQL授权表的其它问题,而且觉得你必须邮寄这个问题 / l9 F4 |) s+ N4 T6 Z6 c
到邮寄表,总是提供一个MySQL授权表的倾倒副本(dump)。你可用mysqldump   X' v1 i+ \* j' R0 R3 p# b+ z
mysql命令倾倒数据库表。象平时一样,用mysqlbug脚本邮寄你的问题。在一 $ E& g/ c- L  c
些情况下你可能用--skip-grant-tables重启mysqld以便能运行mysqldump。
& B( O. S9 ~2 f' C怎样使MySQL安全以对抗解密高手 . P: g% M: }7 B
当你连接一个MySQL服务器时,你通常应该使用一个口令。口令不以明文 2 g) B' v! O* D. Z
在连接上传输。 , e) w8 V7 z% n1 N
: [3 P1 Q9 l5 b, s+ ]+ D
所有其它信息作为能被任何人读懂的文本被传输。如果你担心这个,你可
5 k) o: J- v# L+ T4 D( R9 c使用压缩协议(MySQL3.22和以上版本)使事情变得更难。甚至为了使一切更安全
/ j4 _2 p: O  X,你应该安装ssh(见http://www.cs.hut.fi/ssh)。用它,你能在一个MySQL服 * t  H6 k0 K% E* O
务器与一个MySQL客户之间得到一个加密的TCP/IP连接。 - A+ o( h; }, k' |
" |. d* {* g+ ]5 G. Y9 S. S/ l0 e
为了使一个MySQL系统安全,强烈要求你考虑下列建议:
- I2 h/ @. J; f# o9 H6 p  \/ P! [# d1 m' Q2 k& q
对所有MySQL用户使用口令。记住,如果other_user没有口令,任何人能简
0 X5 y# t7 \7 ?9 F单地用mysql -u other_user db_name作为任何其它的人登录。对客户机/服务器
8 r0 d' ^. [1 L应用程序,客户可以指定任何用户名是常见的做法。在你运行它以前,你可以通
1 g, H; e7 x% o5 L! R! _  `过编辑mysql_install_db脚本改变所有用户的口令,或仅仅MySQL root的口令, / o4 }( T0 @5 g. `( k) y: x
象这样:
8 s8 f! |3 I1 N2 {1 A8 Sshell> mysql -u root mysql
% Y$ d# m2 w; c+ \3 B! Y3 @mysql> UPDATE user SET Password=PASSWORD('new_password')
' Y) b# u( M( @5 H; x0 s' _WHERE user='root'; % h4 D( I; A3 o, n
mysql> FLUSH PRIVILEGES; $ L! H4 W8 L) [5 A* R
" j9 k6 P9 u2 S5 {) D$ E
不要作为Unix的root用户运行MySQL守护进程。mysqld能以任何用户运行,
; Y4 A1 S! b. |8 `' H你也可以创造一个新的Unix用户mysql使一切更安全。如果你作为其它Unix用户 * N+ ^: C& f5 V0 l
运行mysqld,你不需要改变在user表中的root用户名,因为MySQL用户名与Unix , `6 G# W, v7 a. a& d
用户名没关系。你可以作为其它Unix用户编辑mysql.server启动脚本mysqld。   F# K$ w" Q# s0 b+ {
通常这用su命令完成。对于更多的细节,见18.8 怎样作为一个一般用户运行
* V% t- [4 N. D0 d+ m" w" EMySQL。 . g  w+ y$ q( p+ {+ @" k
如果你把一个Unix root用户口令放在mysql.server脚本中,确保这个脚本
0 H; {" U/ m3 a只能对root是可读的。 " I! S, {) M( A9 H7 [( ?
检查那个运行mysqld的Unix用户是唯一的在数据库目录下有读/写权限的用
7 I1 G% n6 `% E' {, i: b户。
6 K0 u7 L! A7 H5 @不要把process权限给所有用户。mysqladmin processlist的输出显示出当
6 R/ p; z- G& z0 p/ f前执行的查询正文,如果另外的用户发出一个UPDATE user SET password= , `' x: C, F- e8 l5 ~% n: G4 }
PASSWORD('not_secure')查询,被允许执行那个命令的任何用户可能看得到。 1 z, Q4 `* J4 ?
mysqld为有process权限的用户保留一个额外的连接, 以便一个MySQL root用
9 m- S" l' [% h7 C4 I% \户能登录并检查,即使所有的正常连接在使用。 . Z& [0 g+ [7 s' U' `8 h# |  r
不要把file权限给所有的用户。有这权限的任何用户能在拥有mysqld守护
6 o7 |5 m% W& v# K9 x进程权限的文件系统那里写一个文件!为了使这更安全一些,用SELECT ...
- c# c/ ^7 L, a5 d5 w" T: SINTO OUTFILE生成的所有文件对每个人是可读的,并且你不能覆盖已经存在的 # |9 s! P! L- H. s% @
文件。file权限也可以被用来读取任何作为运行服务器的Unix用户可存取的文 2 w& k5 g9 {( B) Y
件。这可能被滥用,例如,通过使用LOAD DATA装载“/etc/passwd”进一个数
& Z. _$ f6 s5 R, O8 g据库表,然后它能用SELECT被读入。 $ Z2 L( F1 @( P* \# v; X) j
如果你不信任你的DNS,你应该在授权表中使用IP数字而不是主机名。原则 / n, o8 k/ g' O
上讲,--secure选项对mysqld应该使主机名更安全。在任何情况下,你应该非常 & x( ]' H: `3 V" }
小心地使用包含通配符的主机名! ! u1 x9 z9 r/ {- W$ T3 g
下列mysqld选项影响安全: . k' z! ^* }$ H' H- D! _! n
# o* ~# e8 f; e) E
--secure
  B" x/ S& d- t, I( A由gethostbyname()系统调用返回的IP数字被检查,确保他们解析回到原来 9 K: A0 q, \' t6 o4 _- L
的主机名。这对某些外人通过模仿其它主机获得存取权限变得更难。这个选项也
+ T, E( H5 Y% h% Y/ d( m; _# `增加一些聪明的主机名检查。在MySQL3.21里,选择缺省是关掉的,因为它有时
; s# t: p; _6 w& z7 b6 a  N# ]( A它花很长时间执行反向解析。MySQL 3.22缓存主机名并缺省地启用了这个选项。 ( w4 [( q3 D& Q6 i! I2 s. A/ f
--skip-grant-tables 7 K, H: D" d- T0 i
这个选项导致服务器根本不使用权限系统。这给每个人以完全存取所有的数
6 `2 g' C$ _( l6 }7 R据库的权力!(通过执行mysqladmin reload,你能告诉一个正在运行的服务器
9 x- m' z; T* Y6 V1 a7 r% N再次开始使用授权表。)
$ S& w3 H- o  W+ \4 R9 L) f1 K--skip-name-resolve
- [5 R7 N9 q2 w! C  K7 [. D+ q主机名不被解析。所有在授权表的Host的列值必须是IP数字或localhost。 ) P3 S2 R* a& V5 ~+ ?
--skip-networking 7 R$ r2 k; D% D4 g
在网络上不允许TCP/IP连接。所有到mysqld的连接必须经由Unix套接字进
7 U4 G! c' p# }: P& z. E行。这个选项对使用MIT-pthreads的系统是不合适的,因为MIT-pthreads包不
8 A" p* |5 ?+ X- o6 q4 h支持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 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
看了一屏就晕了。。。
: `9 z5 [6 T1 Y( K9 a/ X汗。。# f" |$ p0 O4 K5 q6 m8 q* y1 }
水平不够,消化不了。。
: K7 a3 C9 V% h5 J) _1 O' R7 }8 S6 N' a不过还是顶一下
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 顶 踩

本版积分规则

关闭

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

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