下沙论坛

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

用新浪微博连接

一步搞定

QQ登录

QQ登录

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

MySql的权限存取系统

[复制链接]
rcrun 该用户已被删除
跳转到指定楼层
1
发表于 2003-7-26 16:31:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
MySQL有一个先进但非标准的安全/权限系统。本文描述它的工作原理。
6 V; s; {# Y. J7 L
, P, \* e  C$ v  B) q权限系统做什么   |5 W4 @* u6 L) {! i$ E
MySQL权限系统的主要功能是证实连接到一台给定主机的一个用户, 8 Z0 w8 b, ?# x6 a7 S
并且赋予该用户在一个数据库上select、 insert、update和delete的 % n( h& E9 Q% m
权限。 1 ^! @1 n, d9 C2 r: o' R# l: V4 \
5 g: |) N3 b& P
附加的功能包括有一个匿名的用户和对于MySQL特定的功能例如 6 \9 a1 }, b- Q1 C
LOAD DATA INFILE进行授权及管理操作的能力。
& P7 B; s( u# h  E. t" u  X( N& G8 J  y, V- l% [
MySQL 用户名和口令
$ \" ?' Q! t# C9 @5 m  M6 H由MySQL使用用户名和口令的方法与Unix或Windows使用的方式有很 5 g) d, g  F5 v
多不同之处: * I9 \! D* P4 S- }
: d1 i- X7 e) A& Q1 d: g: Y) O) \. d
MySQL使用于认证目的的用户名,与Unix用户名(登录名字)或
1 c. a+ u% i; i7 y- rWindows用户名无关。缺省地,大多数MySQL客户尝试使用当前Unix用户
+ }6 N" Z- a8 d. Y* |6 y# q) X; }5 a0 Z9 L名作为MySQL用户名登录,但是这仅仅为了方便。客户程序允许用-u或-
) r( y; E+ @  ^! g( t2 v-user选项指定一个不同的名字,这意味着无论如何你不能使得一个数据 4 @& W+ u8 M2 V2 \( t0 Y1 a4 J
库更安全,除非所有的MySQL用户名都有口令。任何人可以试图用任何名
- d8 m. H$ g6 y7 b* U$ ]7 G字连接服务器,而且如果他们指定了没有口令的任何名字,他们将成功。 , l' H% h& d! w- q6 A  T4 O, x
MySQL用户名最长可以是16各字符;典型地,Unix用户名限制为8个字符。 ' W4 |+ F( e/ N0 V% r$ {+ K& }4 n
MySQL口令与Unix口令没关系。在你使用登录到一台Unix机器口令和你使
( W7 J( ~! p% _$ n$ M用在那台机器上存取一个数据库的口令之间没有必要有关联。
4 _5 z/ g  Z8 |1 |2 W( D; BMySQL加密口令使用了一个Unix登录期间所用的不同算法。 & h; f, Q; r9 d; i% a
! ?1 `0 \- J6 O; R1 t
与MySQL服务器连接 # q7 o9 x3 S2 V3 p6 {+ R8 b! O
当你想要存取一个MySQL服务器时,MySQL客户程序一般要求你指定
$ D5 ?8 R* B2 \: x$ j$ w连接参数:你想要联接的主机、你的用户名和你的口令。例如,mysql
! f. m& t9 _6 W* R* s客户可以象这样启动(可选的参数被包括在“[”和“]”之间):
& p& z+ W6 T/ _
2 `! W1 @6 g7 l; o) N) Ishell> mysql [-h host_name][-u user_name][-pyour_pass ] 7 ~: a: n0 p; T; d6 ]
-h, -u和-p选项的另一种形式是--host=host_name、--user=   @+ Q$ @; [9 ~% h2 E5 Y1 U
user_name和--password=your_pass。注意在-p或--password=与跟随它 9 K. f! X, ^; Z4 k! ?$ R* q. I
后面的口令之间没有空格。
, D4 ?2 o& l9 r. o7 n/ s
: C" Q; Z0 z+ e3 V$ i注意:在命令行上指定一个口令是不安全的!随后在你系统上的任
/ h+ n. |& @1 R2 C何用户可以通过打类似这样的命令发现你的口令:ps auxww。
4 m( Y8 L4 A5 G+ ?% Z4 V5 @" {5 u+ B& Y2 t6 T' X
对于命令行没有的联接参数,mysql使用缺省值: 0 j- K( ]9 K9 {  l9 x0 o2 e1 |  L
% F# E2 b' _  {- J  Z9 X5 o
缺省主机名是localhost。
% e6 s3 ~3 y& [2 }2 o  g缺省用户名是你的Unix登录名。
8 @3 t  M6 l6 i+ Q. R如果没有-p,则没有提供口令。
2 w( Y/ z! g5 c这样, 对一个Unix用户joe,下列命令是等价的: ( x7 Y" {# W+ E' |" h/ R
( e. @  d* l3 W" w; O1 |9 C& v
shell>mysql -h localhost -u joe 2 ?1 A: x9 I5 B: o
shell>mysql -h localhost
, H" O" o5 L0 b/ hshell>mysql -u joe 9 X7 Z! |% l# h; n- s
shell>mysql + r9 k+ \. S# {8 J

0 A  Z: T: z9 d* F8 a' c2 B# l其它MySQL客户程序有同样表现。 + R, Y" w, F% h

! J% V6 w5 B% v7 Y. U0 T在Unix系统上,当你进行一个连接时,你可以指定要使用的不同的缺 : Y; S: B7 P# O5 A
省值,这样你不必每次在你调用一个客户程序是在命令行上输入他们。这
" F) D- w) |7 _' n% T) ]: s2 d可以有很多方法做到:
4 k. L4 @+ d% e
- I1 m* ?$ B4 c你能在你的主目录下“.my.cnf”的配置文件的[client]小节里指定
, j# p3 t4 c- n# A6 N连接参数。文件的相关小节看上去可能像这样: 5 W- w) X$ r' B* [, O) U
[client]
8 g3 [6 E4 `  N$ M0 chost=host_name
0 X. q6 j  x1 ^& `( duser=user_name
, |1 z6 t( s# ~password=your_pass
1 y" @$ g+ c7 }& Q  S( j+ C1 L* N) B& I( ~6 n+ G; O
你可以用环境变量指定连接参数。主机可用MYSQL_HOST指定,MySQL * y" s6 R' }/ D' P; ^- K9 _
用户名字可用USER指定(仅对 Windows),口令可用MYSQL_PWD指定(但是
- U( I/ y& _6 E& J: Q+ s+ }) ?这不安全) 。 + g  _* u7 t& r3 Q) i
如果连接参数以多种方法被指定,在命令行上被指定的值优先于在配
# Q% U  k4 K% M. I; \置文件和环境变量中指定的值,而在配置文件指定的值优先于在环境变量 . M3 v- f. g- |/ p! L
指定的值。
0 q* c7 V0 \* V+ a) y) ^
8 v9 Z4 q( H, D$ D( G1 u% n使你的口令安全
; x3 D" P* K/ x, Y+ X) [: m8 Y以一种暴露的可被其他用户发现的方式指定你的口令是不妥当的。
8 b% A  `/ d, V4 P: K* _" [: Y% W当你运行客户程序时,你可以使用下列方法指定你的口令,还有每个方法   c: {" @& n( e+ e" a' A
的风险评估: " }! y2 z3 n0 Y* j; q
" Z4 \1 t3 U) Y/ j* o
使用一个在命令行上-pyour_pass或--password=your_pass的选项。 * p' |' T1 P' {" J" _0 e
这很方便但是不安全,因为你的口令对系统状态程序(例如ps)变得可见,
% _& f* ^: B' j" e  I它可以被其他的用户调用来显示命令行。(一般MySQL客户在他们的初始化
4 J  g1 W8 d: X  E8 n, l顺序期间用零覆盖命令行参数,但是仍然有一个短暂间隔时间内参数值可 7 r8 _) X1 t$ `* L5 w2 H; ~
见的。)
0 ^2 @" w; T4 m5 b/ }8 e+ u; A使用一个-p或--password选项(没有指定your_pass值)。在这种情况
9 C  ]: G2 `1 z1 ~2 |1 y6 F下,客户程序请求来自终端的口令: 3 u3 k2 o. r: ?' K' `

! a0 F. v5 {  T2 J' i) b9 ~: \( Ushell>mysql - u user_name - p ! p7 }. p8 z6 S' R6 C' r: S
Enter password: ******** , Z% G: i5 S2 c: z0 r

, g3 Z' Z( y: `4 b: V% |& [% n客户回应“*”字符到作为输入你的口令的终端使得旁观者不能看见 7 t& s/ j; f3 H$ r5 w
它。因为它对其他用户不可见,与在命令行上指定它相比,这样进入你 ( z7 v6 r7 P; z3 Q
的口令更安全。然而,这个输入一个口令的方法仅仅为你交互式运行程 5 W$ s6 s9 e& h9 A; d7 ^
序是合适的。如果你想要从非交互式运行的一个脚本调用一个客户,就 ! g$ R+ B/ u4 B# b7 R- G
没有从终端输入入口令的机会。 * |# B3 B5 ?9 V7 \; u

8 e  E8 N. J: C" H" s1 ]  P在一个配置文件中存储你的口令。例如,你可你的主目录的
5 e6 ]) n: p& O6 ^% Y2 }“.my.cnf”文件中的[client]节列出你的口令:
3 i3 @; J7 p8 O7 C+ l) v5 n! f[client]
4 Z7 P8 n+ g9 m9 E: Z" mpassword=your_pass
- e! B# N6 `# O3 l& L
2 ^  S2 t" [. n6 [如果你在“.my.cnf”里面存储口令,文件应该不是组或世界可读或
+ X, U4 f8 F# ]* }/ X0 E/ @可写的。保证文件的存取模式是400或600。见4.15.4 选项文件。
: h# M& b& B+ Y) e/ W1 C
: r% U" d& p8 W! k" ]/ |你可在MYSQL_PWD环境变量中存储口令,但是这个方法必须想到是极 2 E' S! S, F8 r! o1 C' D
不安全的且应该不使用。ps的某些版本包括显示运行进程的环境的选项; 5 @+ H9 T) ?# z+ d- F' T
如果你设定MYSQL_PWD,你的口令将对所有人是显而易见的,甚至在没有 # t7 M6 V( B: a+ o8 K& ?5 }
这样一个版本的ps系统上,假设没有其他方法观察到进程环境是不明智   q+ D9 y% F8 _1 |  g
的。 3 m& Q5 h) k9 o6 K4 P% w* `, K
总之,最安全的方法是让客户程序提示口令或在一个适当保护的“
% r1 \& H/ w3 G.my.cnf”文件中指定口令。
5 m: I; N0 a" @2 K6 l* h. ]) L) m/ p
MySQL提供的权限
, P9 j  c/ i  y/ n0 T' D权限信息用user、db、host、tables_priv和columns_priv表被存储
% Y# t7 L6 l  [0 ~+ _7 P在mysql数据库中(即在名为mysql的数据库中)。在MySQL启动时和在权限 # O$ e! F3 |' k& ^9 t1 D0 C2 c
修改何时生效所说的情况时,服务器读入这些数据库表内容。 8 F3 o9 J+ b8 v* K5 }, G
) N% ]$ E2 \# @) N
由MySQL提供的权限名称显示在下表,还有在授权表中每个权限的表
" d) Y5 |% h" b# n& o列名称和每个权限有关的上下文: 7 i$ i, ]' x: ^+ p
权限 列 上下文 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 P. j. F9 I( l5 s3 f# t: rselect、insert、update和delete权限允许你在一个数据库现有的   _4 g' J7 p2 H( Y) m
表上实施操作。
. k1 V5 \  P3 q* Q% O  A, Q& ]- d* n3 z/ d2 ~9 ]' D' s
SELECT语句只有在他们真正从一个表中检索行是才需要select权限, , a- t# A- ~7 I9 B9 p$ I
你可以执行某个SELECT语句,甚至没有任何到服务器上的数据库里的存
6 |8 c" `. Y- z  K) ]  B1 s取任何东西的许可。例如,你可使用mysql客户作为一个简单的计算器:
! d# d; w1 ]6 @0 ?" k4 t0 P+ t6 \
mysql> SELECT 1+1;
" B. Y2 ^% W9 y; Zmysql> SELECT PI()*2;
$ B4 E9 l1 K5 |* j- n
, d8 q* c0 E4 ^" y0 i* @; uindex权限允许你创建或抛弃(删除)索引。
! m1 L% C3 N" `3 U" Y0 \) G2 O" ?( S' a, W" o' k
alter权限允许你使用ALTER TABLE。
. @5 \2 ~: F; \+ H! q; U  @9 L  ?- S" _9 Z; j0 T9 R
create和drop权限允许你创建新的数据库和表,或抛弃(删除)现存的
/ l5 h! N4 T' M; g: w2 i数据库和表。 0 `. i0 @6 q2 H' x: n4 A  r# {3 r

; _; a3 d' W0 l' y# {! b' z: X. b; w  ]注意:如果你将mysql数据库的drop权限授予一个用户,该用户能抛弃 ' w  ~8 @4 x# B- K' c
存储了MySQL存取权限的数据库!
) G1 x9 a* v, k% T" Y/ }+ ]5 ~
5 N- u2 M( W6 R: s2 R6 Sgrant权限允许你把你自己拥有的那些权限授给其他的用户。
5 F: I& |$ p" ^: N
2 N4 }! C+ ^" |! j' ]2 `file权限给予你用LOAD DATA INFILE和SELECT ... INTO OUTFILE语句 " g( q7 V' I3 @6 A& _" h2 r2 `
读和写服务器上的文件,任何被授予这个权限的用户都能读或写MySQL服务
' ~0 j  x4 B4 N6 `, X0 T! S器能读或写的任何文件。 1 Z3 E# r1 i" p( |3 D

* G! j9 K* p$ M* K: M. a! m其余的权限用于管理性操作,它使用mysqladmin程序实施。下表显示 ( \1 q9 q+ C) X0 l4 j7 w
mysqladmin支配每个管理性权限允许你执行的命令: & i7 G1 U$ B2 ~" b
优惠 权限拥有者允许执行的命令 reload reload, refresh, flush-privileges, flush-hosts, flush-logs, flush-tables shutdown shutdown precess processlist, kill # t3 S1 [( Z. H1 ~0 J
reload命令告诉服务器再读入授权表,refresh命令清洗所有表并打开
/ q  I3 f. U6 v$ D和关闭记录文件,flush-privileges是reload的一个同义词,其它flush-*
8 [, z7 |3 ~2 m! G2 X  m  _% I* B命令执行类似refresh的功能,但是范围更有限,并且在某些情况下可能更 1 _2 \: O6 v/ R8 f3 S4 }9 D
好用。例如,如果你只是想清洗记录文件,flush-logs比refresh是更好的
  U! H  q1 ?$ D2 t0 Z2 w' n选择。 + j* }6 I0 ]+ ~" p6 J5 `6 j
2 D! L3 O# i' }* Z5 |* m2 u
shutdown命令关掉服务器。 7 K. H9 k3 P( B- m! t

- |, A. k' q1 [* ~processlist命令显示在服务器内执行的线程的信息。kill命令杀死服
! g3 o& n/ S6 f. v/ o; J) A% s务器线程。你总是能显示或杀死你自己的线程,但是你需要process权限来
2 I6 p" F8 o: w+ R! ^- l( g显示或杀死其他用户启动的线程。
" t5 q! G+ a4 j% U! g4 a9 ^; u! G9 u& F
总的说来,只授予权限给需要他们的那些用户是一个好主意,但是你
) r0 [6 M! i& D% N应该在授予某个权限时试验特定的警告:
5 N: v- r+ a/ P# X+ V. Y2 w4 @6 \' j0 v4 v; X3 e2 j0 ]# V; c4 I
grant权限允许用户放弃他们的权限给其他用户。2个有不同的权限并
) N, a% k( N3 D7 g  W6 R- O有grant权限的用户可以合并权限。
7 Q, T+ U; T6 ]2 V/ oalter权限可以用于通过重新命名表来推翻权限系统。
6 m: C/ |. T! L3 y( S1 ]7 m0 Xfile权限可以被滥用在服务器上读取任何世界可读(world-readable, , |' |! L* m& k8 v; T
即任何人可读)的文件到一张数据库表,然后其内容能用SELECT被存取。
: Q+ I' }/ E6 y" p6 M8 S1 tshutdown权限通过终止服务器可以被滥用完全拒绝为其他用户服务。
+ f9 Q5 I. \( O4 }& C7 ?* [precess权限能被用来察看当前执行的查询的普通文本,包括设定或改
3 ~8 L0 a+ M+ B# y+ ~4 C! S7 ^变口令查询。 3 l; A& Z* N) X/ G1 o0 K2 y' z
在mysql数据库上的权限能被用来改变口令和其他存取权限信息。(口
0 W6 `& C, e  E* |令被加密存储,所以一个恶意的用户不能简单地读取他们。然而,有足够   U. `9 V# K3 X* ~3 O$ G+ U: k, }
的权限,同一个用户能用不同的一个代替一个口令。) & H7 o2 k9 }& V& s! q: G
有一些事情你不能用MySQL权限系统做到:
* y( R7 p: I5 y0 }5 K  k- z: q! d- W9 D
你不能明显地指定一个给定用户应该被拒绝存取。即,你不能明显地匹   C4 ~: c* i, [2 ?! t; A5 z
配一个用户并且然后拒绝连接。 " c  O. |0 i5 t! W1 C+ `" ^/ l
你不能指定一个用户有权创建立或抛弃一个数据库中的表,也不能创建
& {6 ]. N  @/ E. @$ U或抛弃数据库本身。 - i9 V- @! f6 o8 i7 S+ P
权限系统工作原理 0 \8 n" W" ?8 A  O- w5 x1 k
MySQL权限系统保证所有的用户可以严格地做他们假定被允许做的事情。
  c2 M9 C8 g: z+ B  F当你连接一个MySQL服务器时, 你的身份由你从那连接的主机和你指定的用 - e3 G& c0 z! X0 y
户名来决定,系统根据你的身份和你想做什么来授予权限。
2 |# t; H5 ]7 L, [; l" q0 ~
7 U5 e3 J+ y0 I# JMySQL在认定身份中考虑你的主机名和用户名字,是因为有很小的原因假
4 M& E; i3 a; u6 s( K" @定一个给定的用户在因特网上属于同一个人。例如,用户从whitehouse.gov
6 @7 V7 ?! O) c" Q$ ?连接的bill不必和从mosoft.com连接bill是同一个人。 MySQL通过允许你区
8 H# S. v( V4 l分在不同的主机上碰巧有同样名字用户来处理它:你可以对从whitehouse.gov
2 Q7 T8 N( J# l" W连接授与bill一个权限集,而为从microsoft.com的连接授予一个不同的权限 $ |8 b7 [; M* O2 Z
集。 # o. Z; _- a1 r- r; I4 _

# P# B" n1 k" k  BMySQL存取控制包含2个阶段:
: ]5 V4 h5 F  L+ g7 z& E4 Q  G2 S! J6 a; ^5 z7 v$ u( d" q3 |
阶段1:服务器检查你是否允许连接。
7 w. L+ D0 L, T阶段2:假定你能连接,服务器检查你发出的每个请求。看你是否有足够
( |2 G! H6 z: S9 s: I; h的权限实施它。例如,如果你从数据库中一个表精选(select)行或从数据库抛
6 N# c2 p' @- [5 Y* i7 ]: ^: K弃一个表,服务器确定你对表有select权限或对数据库有drop权限。
, D4 }" g; p% h服务器在存取控制的两个阶段使用在mysql的数据库中的user、db和host
; `6 ?7 w- C! c7 w" r0 B( Q表,在这些授权表中字段如下:
* J1 ?# U: V0 {0 A8 a表名称 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 * G; N- [  ]; j9 p& {6 v
对存取控制的第二阶段(请求证实),如果请求涉及表,服务器可以另外
' ~2 ^, z' g* h5 m7 k( a参考tables_priv和columns_priv表。这些表的
  R! n* G9 e) l& c+ w% _字段如下: * U% c4 c0 u7 M% ]" l: w3 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 7 I6 ]. u2 r; R) T
对存取控制的第二阶段(请求证实),如果请求涉及表,服务器可以另外 0 K& _1 w$ g. v
参考tables_priv和columns_priv表。这些表的字段如下: % r, c7 B- ?; ^
字段名 类型 Host CHAR(60) User CHAR(16) Password CHAR(16) Db CHAR(64) (tables_priv和columns_priv表为CHAR(60)) & X2 O0 z6 F5 V
在user、db和host表中,
' n5 Y0 X& @' v所有权限字段被声明为ENUM('N','Y')--每一个都可有值
% k% ~5 k1 a. V: y) f7 y  E  J' T'N'或'Y',并且缺省值是'N'.
6 A, s. E2 d: q9 Y; c在tables_priv和columns_priv表中,权 7 n$ p: J+ t/ W
限字段被声明为SET字段: 0 J7 E0 t) d! Y8 U- b; e
表名 字段名 可能的集合成员 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' ; j6 X: I0 I( a: p) X; U/ T6 e
每个授权表包含范围字段和权限字段。 ; N9 u/ r$ t# D& D, u

/ m5 l: T6 V: d8 S' w. q范围字段决定表中每个条目的范围,即,条目适用的上下文。例如,
, G6 |3 j9 Z( K1 V一个user表条目的Host和User值为'thomas.loc.gov'和'bob'将被用于
6 Q! U3 d- Z0 X0 T证实来自主机thomas.loc.gov的bob对服务器的连接。同样,一个db表条 ) q! y3 m% T0 s4 X0 O1 z0 S
目的Host、User和Db字段的值是'thomas.loc.gov'、'bob'和'reports'
0 \% l8 w5 Z# E4 d7 x将用在bob从主机联接thomas.loc.gov存取reports数据库的时候。
( r# Y- T6 o+ K5 P8 z  ktables_priv和columns_priv表包含范围字段,指出每个条目适用的表或
" d. L' y( o- Z6 p3 G  `表/列的组合。 & K; y, e% ^* F7 |$ S5 q( I
# V- |4 @0 p6 B; r
对于检查存取的用途,比较Host值是忽略大小写的。User、Password、
. I4 I7 ?/ Y+ VDb和Table_name值是区分大小写的。Column_name值在MySQL3.22.12或以
# R3 @! K& G# Z1 o( d$ T8 O( s0 K后版本是忽略大小写的。   l4 B7 R4 t1 T# a8 V

) l7 z+ @* a& a, P" L) M" q权限字段指出由一个表条目授予的权限,即,可实施什么操作。服务
# n% }4 i6 N: E% e7 l器组合各种的授权表的信息形成一个用户权限的完整描述。为此使用的规 * }& u/ E; a/ s" v+ B
则在6.8 存取控制, 阶段2:请求证实描述。 / h. e4 o: O6 {( R: O; P

9 e) t# g1 l6 E! Z7 a2 ]; \范围字段是字符串,如下所述;每个字段的缺省值是空字符串:
* k' j% c; F1 Q" L+ X5 ]* q字段名 类型 Host CHAR(60) User CHAR(16) Password CHAR(16) Db CHAR(64) (tables_priv和columns_priv表为CHAR(60))
2 A# w2 e9 I, D5 P在user、db和host表中,所有权限字段被声明为ENUM('N','Y')--每一 2 l" f1 B7 D  z0 s. S/ s! c3 O
个都可有值'N'或'Y',并且缺省值是'N'. ' j" i7 g7 v& K: }- p
2 H1 S3 b( g, D/ p
在tables_priv和columns_priv表中,权限字段被声明为SET字段: 5 J/ K3 |2 u6 d3 P
表名 字段名 可能的集合成员 tables_priv Table_priv 'Select', 'Insert', 'Update', 'Delete', 'Create', 'Drop', 'Grant', 'References', 'Index', 'Alter' tables_priv Column_priv 'Select', 'Insert', 'Update', 'References' columns_priv Column_priv 'Select', 'Insert', 'Update', 'References' $ C3 z( K) o! K# f' j( U# d
简单地说,服务器使用这样的授权表: , |' i2 p+ j9 ?; i3 t) U
! E- A9 }- j! A) r
user表范围字段决定是否允许或拒绝到来的连接。对于允许的连接,
9 t: }3 p  g8 N- N权限字段指出用户的全局(超级用户)权限。 7 e( m7 [) q0 D  ^# Y. r8 _
db和host表一起使用:
2 h4 i/ D: V2 ]8 I" hdb表范围字段决定用户能从哪个主机存取哪个数据库。权限字段决定
: i$ J% y# I  B% X3 k$ r允许哪个操作。
* m) r: p3 |% B$ ~8 b; C当你想要一个给定的db条目应用于若干主机时,host表作为db表的扩 & }: R) l- T( b; q
展被使用。例如,如果你想要一个用户能在你的网络从若干主机使用一个 6 w' p! C- Z. Z
数据库,在用户的db表的Host条目设为空值,然后将那些主机的每一个移 " P) n9 {; Q4 V. ^( f7 u# G" u
入host表。这个机制详细描述在6.8 存取控制, 阶段2:请求证实。 / x+ q& o  M8 B' r, k  c
tables_priv和columns_priv表类似于db表,但是更精致:他们在表 / x! `" Y% m+ l8 ?. i$ g9 D" d
和列级应用而非在数据库级。 8 m" |4 |6 m' K% }4 i
注意管理权限(reload, shutdown, 等等)仅在user表中被指定。这是
: j  l2 O% c$ A6 ^因为管理性操作是服务器本身的操作并且不是特定数据库,因此没有理由
' L; y; q0 w+ A( g* t# J在其他授权表中列出这样的权限。事实上,只需要请教user表来决定你是   n% J6 w' A* T+ H7 h$ E' p' R
否执行一个管理操作。
# m9 ^/ u# e- L0 P- ~  w7 d
7 B1 h! x8 E0 n* c/ ]2 l8 cfile权限也仅在user表中指定。它不是管理性权限,但你读或谢在服 2 X/ @- L1 ?# J1 w. T. d* L
务器主机上的文件的的能力独立于你正在存取的数据库。 9 B; o" F" [& U5 ~
) m* c0 G5 x0 e4 F3 E
当mysqld服务器启动时,读取一次授权表内容。 9 j9 S' ]0 B% G3 l! I6 w! y. o
( [) c: J- \0 A2 w: o
当你修改授权表的内容时,确保你按你想要的方式更改权限设置是一 * r: ^) E$ E% T# e. n3 I
个好主意。 ! ?- D+ ~. S( M2 r. p

+ M; N1 `/ A' X; h/ g一个有用的诊断工具是mysqlaccess脚本,由Carlier Yves 提供给 2 B; B( K' o, W- k* W5 T6 C+ T
MySQL分发。使用--help选项调用mysqlaccess查明它怎样工作。注意:   D5 H/ f4 q3 L* m7 r% r
mysqlaccess仅用user、db和host表仅检查存取。它不检查表或列级权限。
# u6 ~# A2 ?$ v8 K$ @2 T% Q5 K5 J& g0 h4 \( Z
存取控制, 阶段1:连接证实
2 C; d* o$ I' h( u/ j8 C1 X当你试图联接一个MySQL服务器时,服务器基于你的身份和你是否能 ( F( V  R, P' S! \8 R% u' c
通过供应正确的口令验证身份来接受或拒绝连接。如果不是,服务器完全 4 u' f- h+ C+ f; u9 o: z
具结你的存取,否则,服务器接受连接,然后进入阶段2并且等待请求。 + p9 G, q) p* t: |% X4 E. s* G

9 Z7 u; [- A/ K9 J你的身份基于2个信息: & ~4 }# {5 V9 _- v' I9 [& t  a+ N
2 z  @/ F4 W# Q: O: q8 }8 }
你从那个主机连接
/ e& ]- P  H+ b# v你的MySQL用户名 # E: @8 _& ^0 p
身份检查使用3个user表(Host, User和Password)范围字段执行。服 ; Z' _  k" [/ z- S3 j# h7 B
务器只有在一个user表条目匹配你的主机名和用户名并且你提供了正确的 4 H4 Q6 _7 E( }
口令时才接受连接。 2 d+ E: w1 e1 V+ r& w3 M" R

( f* [7 F* C4 D3 S1 _' D6 W* `( w在user表范围字段可以如下被指定:
: F+ ?/ t3 p" S+ G. S; @$ n, g. ]6 ~! T4 w4 X6 m; O! y9 F2 h  e
一个Host值可以是主机名或一个IP数字,或'localhost'指出本地主机。
( x4 x) j- Q  c8 L2 A你可以在Host字段里使用通配符字符“%”和“_”。 4 u6 e* Y$ ^) k' @: l5 I+ W4 Z
一个Host值'%'匹配任何主机名,一个空白Host值等价于'%'。注意这些
2 B" N* J# }: |4 [+ N( E; ]5 Z值匹配能创建一个连接到你的服务器的任何主机! 7 u+ X: H1 i2 w3 i7 F# k
通配符字符在User字段中不允许,但是你能指定空白的值,它匹配任何
. G$ y/ O& ^# B6 q$ g! f& T3 v名字。如果user表匹配到来的连接的条目有一个空白的用户名,用户被认为
& [5 l3 P  x) {* ]: m! @是匿名用户(没有名字的用户),而非客户实际指定的名字。这意味着一个空
: L# i* ]7 N" F/ h: F白的用户名被用于在连接期间的进一步的存取检查(即,在阶段2期间)。 7 Q! }/ X! T7 A& @  o' c
Password字段可以是空白的。这不意味着匹配任何口令,它意味着用户
7 q- ^" h0 L$ x1 N必须不指定一个口令进行连接。 " \1 `/ g% D; V( n0 o
非空白Password值代表加密的口令。 MySQL不以任何人可以看的纯文本
) i. o+ A8 r+ s' Q: g格式存储口令,相反,正在试图联接的一个用户提供的口令被加密(使用
9 u% m( D! x* b% M# tPASSWORD()函数),并且与存储了user表中的已经加密的版本比较。如果他 $ F: k' C% l' ~$ m) g  U4 V
们匹配,口令是正确的。
: f* x' u1 w/ w* \
5 Z% y3 t; S0 V9 M下面的例子显示出各种user表中Host和User条目的值的组合如何应用于到来
& h* _3 |$ T" Z6 y1 F的连接:
. x& H* X4 U8 d1 k) d% {! M/ f  O5 a9 z0 e- P" L7 p
Host 值 User 值 被条目匹配的连接 6 F& i8 t& q4 x& h
'thomas.loc.gov' 'fred' fred, 从thomas.loc.gov 连接 , l$ s* y# g/ L; [5 b" p+ O
'thomas.loc.gov' '' 任何用户, 从thomas.loc.gov连接 $ u/ p! t3 a5 S
'%' 'fred' fred, 从任何主机连接
& d( M% p9 H# x* @  f'%' '' 任何用户, 从任何主机连接
/ h" Q; o3 d6 l! p8 T'%.loc.gov' 'fred' fred, 从在loc.gov域的任何主机连接
2 b; P% L3 N. W'x.y.%' 'fred' fred, 从x.y.net、x.y.com,x.y.edu等联接。(这或许 1 i7 r8 ?  Z6 Q. @8 x8 |
无用)
% r! S; I/ u& H, M4 E" k'144.155.166.177' 'fred' fred, 从有144.155.166.177 IP 地址的主 1 K# {) N6 ^# n7 E, m
机连接 - R5 f/ Q" t* `7 O
'144.155.166.%' 'fred' fred, 从144.155.166 C类子网的任何主机连 $ q3 a" O' G5 P' m% f  ]

8 G; W" z& M& m  C  C& ~8 @- m: e- s" P/ t1 L4 A1 p
既然你能在Host字段使用IP通配符值(例如,'144.155.166.%'匹配在一个子
+ u: {5 ?3 B( n' y6 T8 {网上的每台主机),有可能某人可能企图探究这种能力,通过命名一台主机
8 E& I9 n" v$ b+ k% o7 c为144.155.166.somewhere.com。为了阻止这样的企图,MySQL不允许匹配以
" G1 l" R4 `2 E  m" s: I' p数字和一个点起始的主机名,这样,如果你用一个命名为类似1.2.foo.com的
/ j4 f  r+ h* ~$ e" H主机,它的名字决不会匹配授权表中Host列。只有一个IP数字能匹配IP通配
. S9 m' ~& k3 q8 [' y符值。
4 t4 G* u4 x- g, P4 b1 r7 B: z& c1 n: ?2 p+ f9 Z, a
一个到来的连接可以被在user表中的超过一个条目匹配。例如,一个由 1 }4 Q* E- O, u, P
fred从thomas.loc.gov的连接匹配多个条目如上所述。如果超过一个匹配,
( v7 t  e) B# J6 [8 b- {; x; N服务器怎么选择使用哪个条目呢?服务器在启动时读入user表后通过排序来 % y$ h4 H% _, O9 l  @, w
解决这个问题,然后当一个用户试图连接时,以排序的顺序浏览条目,第一
8 T* J& Q8 n7 R; Y7 X. Q个匹配的条目被使用。 1 b% C* z3 w  B, c; [2 g2 ^1 e

  P% z, X7 y+ r# L5 vuser表排序工作如下,假定user表看起来像这样:
, Q! J; b7 S% g9 Q+ F2 s4 H
7 k; j* e! T7 }6 B" y: N
8 _2 A: m/ b# {7 `& Z) ^2 T" l+-----------+----------+-
/ u* Y# C; ^/ h  H│ Host │ User │ ... 8 k; y) a0 G; u% R8 L( A/ O0 T* Y
+-----------+----------+-
6 q" F3 K# H9 ?│ % │ root │ ...
$ @$ {& b; Q' L' t, ?│ % │ jeffrey │ ...
3 X2 j  r8 l( \# \8 k' [│ localhost │ root │ ...
; @( }3 n7 A# M+ q/ f│ localhost │ │ ...
& `& {0 b9 K& ~" W/ E1 }+-----------+----------+- - q7 g5 l" b/ A; T! a6 p" [, G$ P

0 C9 `: G7 y+ Y; h当服务器在表中读取时,它以最特定的Host值为先的次序排列('%'在
, I$ L; L. F6 q# L" MHost列里意味着“任何主机”并且是最不特定的)。有相同Host值的条目以 % j& [' w& ^$ K2 m
最特定的User值为先的次序排列(一个空白User值意味着“任何用户”并且
, K/ e2 y/ ?0 N- u是最不特定的)。最终排序的user表看起来像这样: ; \) f3 D0 c  w6 {' E# \7 r
6 z$ p0 G& O! B7 l& K5 T  U% E- }
: U. Y, Z% u, ~7 x3 g' X) U6 p
+-----------+----------+- % ?3 s7 Z+ p. _7 w% Y
│ Host │ User │ ... ( n# `' W/ W, j. K6 Z" r
+-----------+----------+-
% }! n5 h4 U4 e- d: X' Y" ^│ localhost │ root │ ...
4 @0 d( B) D+ d, c* n1 v% P8 n│ localhost │ │ ... . b: x* p6 W" n- _& P% B% }
│ % │ jeffrey │ ... 0 p  Q4 I3 s" ^  }# }6 [
│ % │ root │ ...
: b0 f2 z8 N  X; K5 v8 t+-----------+----------+- 8 X4 m1 r' V7 P: j" T7 O" B6 L/ q' w
& D/ q: G2 |' n( Y' g/ q" x
当一个连接被尝试时,服务器浏览排序的条目并使用找到的第一个匹 % [7 m# V& ?' j7 H. x# O
配。对于由jeffrey从localhost的一个连接,在Host列的'localhost'条目 , Z0 r2 c2 s1 Q  Y. O2 W
首先匹配。那些有空白用户名的条目匹配连接的主机名和用户名。('%'/
3 O: }7 r+ l$ V- N; m'jeffrey'条目也将匹配,但是它不是在表中的第一匹配。)
5 e* j+ [0 ~- d" V" y4 Y1 o1 c9 |9 V( ~: ]* n9 _, B
这是另外一个例子。假定user桌子看起来像这样: " n7 R, j; Q. x8 i! [

& ~6 w% N' }( W" \6 m! |: L3 x) Y
0 L  e9 Q$ E% t& B% T2 Q+----------------+----------+- ; s, J/ d/ B5 `& W8 N
│ Host │ User │ ...
( v' @+ j9 u! n8 L$ c+----------------+----------+- % C- W5 J7 e8 u" o0 X
│ % │ jeffrey │ ... 1 E* [' v: e3 I1 |9 K- q6 j! V
│ thomas.loc.gov │ │ ... ; y. U0 O$ F3 S0 }
+----------------+----------+-
9 l! e9 E6 g8 m( u& t
! f1 f! w5 h8 X# {排序后的表看起来像这样: 1 |, ~4 J) Q# L4 L. \. \5 Q
, p. M; E- t9 W# @* ?3 M

" e# |; w, {6 a4 `+----------------+----------+-
+ l" R+ Q4 k; ^& s, ~│ Host │ User │ ... 4 V/ r, \, E9 v9 O' x, t, B
+----------------+----------+- $ r1 h# ?" o0 Q# a
│ thomas.loc.gov │ │ ...
$ s4 v; _# Y: V8 e+ @* ]│ % │ jeffrey │ ...
# f6 K; Y9 c; n+----------------+----------+-
) {' m* k8 {- `$ d/ g* Z$ x
* V3 W, l/ c; S# J; q- B  t一个由jeffrey从thomas.loc.gov的连接被第一个条目匹配,而一个由 ( G2 U0 j- r/ c) J
jeffrey从whitehouse.gov的连接被第二个匹配。 ! }8 S% `8 k" s+ [& k; Q

3 J  {" h( v, ~普遍的误解是认为,对一个给定的用户名,当服务器试图对连接寻找
. G5 f2 s6 P6 g5 o匹配时,明确命名那个用户的所有条目将首先被使用。这明显不是事实。
+ _3 i1 L( q$ u% a- X0 h+ c先前的例子说明了这点,在那里一个由jeffrey从thomas.loc.gov的连接没 ; |8 A* u0 m( `. r
被包含'jeffrey'作为User字段值的条目匹配,但是由没有用户名的题目匹
; x+ O3 I) S+ A  `7 L$ s: K配! : S' ?0 i. K( w) ~: i% N4 t

6 l) @6 e$ t  H' \7 ?如果你有服务器连接的问题,打印出user表并且手工排序它看看第一个
/ P: {4 T1 x# M: b4 K0 E9 q4 c9 i/ ]; P匹配在哪儿进行。
, }7 k' o) v2 K3 s) X) Y" f2 @9 C+ c
% b2 E9 ~" z4 K% S" H' u0 n存取控制,阶段2:请求证实 , ?) W( b+ Q: t+ O8 V* r4 a
一旦你建立了一个连接,服务器进入阶段2。对在此连接上进来的每个 0 {/ X' g) H1 i1 i; R/ T
请求,服务器检查你是否有足够的权限来执行它,它基于你希望执行的操作 8 C0 T/ k5 x1 L- l/ M
类型。这正是在授权表中的权限字段发挥作用的地方。这些权限可以来子 2 R6 e8 A8 R; n9 ]* O5 }
user、db、host、tables_priv或columns_priv表的任何一个。授权表用
0 c# s0 H' c6 U0 m7 pGRANT和REVOKE命令操作。见7.26 GRANT和REVOKE 句法。(你可以发觉参
) g) Z/ ^$ A8 I. B  n, F, ^, D考6.6 权限系统怎样工作很有帮助,它列出了在每个权限表中呈现的字段。)
2 [0 J. p! `( Z# }6 n1 l! \6 P9 I; a0 j( s2 }
user表在一个全局基础上授予赋予你的权限,该权限不管当前的数据库 0 z$ }* o  T1 q. ~& s5 H
是什么均适用。例如,如果user表授予你delete权限, 你可以删除在服务器
  \( l; J9 i7 }. u- L- s) }主机上从任何数据库删除行!换句话说,user表权限是超级用户权限。只把
9 x9 _/ L+ I- P) K- O( @% Huser表的权限授予超级用户如服务器或数据库主管是明智的。对其他用户, % I$ t! \& m' D9 ^9 b
你应该把在user表中的权限设成'N'并且仅在一个特定数据库的基础上授权,
% _) L+ U& t6 {4 B# @使用db和host表。
% N  D& x* u" t7 ~
- b# z# p7 h8 {+ h$ Jdb和host表授予数据库特定的权限。在范围字段的值可以如下被指定: " {) @& L1 J* R6 S! L5 ?& E5 T
. S1 L9 v$ n* ]2 w  k0 p8 O
通配符字符“%”和“_”可被用于两个表的Host和Db字段。
  L! W  C! g4 b在db表的'%'Host值意味着“任何主机”,在db表中一个空白Host值意味 2 g# [$ _2 e0 b; p+ R/ n, O3 W3 K" @
着“对进一步的信息咨询host表”。
0 s* d0 m% t0 }: L在host表的一个'%'或空白Host值意味着“任何主机”。
( w# v- O* ?8 T在两个表中的一个'%'或空白Db值意味着“任何数据库”。 ; L. @% {4 D2 B/ C  O6 i
在两个表中的一个空白User值匹配匿名用户。
6 l! i7 Y. p6 g7 a& }/ Pdb和host表在服务器启动时被读取和排序(同时它读user表)。db表在Host
9 K# n' v! S1 I1 w7 l% |  m8 K、Db和User范围字段上排序,并且host表在Host和Db范围字段上排序。对于 ; ^) N( |; \% u; \! @: o4 n
user表,排序首先放置最特定的值然后最后最不特定的值,并且当服务器寻找 * ~/ s$ Y* t6 t$ }, t2 K/ U
匹配入条目时,它使用它找到的第一个匹配。
, Z4 o: \: J  j0 j9 \& N. B5 W9 G
tables_priv和columns_priv表授予表和列特定的权限。在范围字段的值可
! w6 Q/ Y6 I% x& R以如下被指定:
1 ~. U  b, K% U) `6 v4 G7 V/ f
: R/ h9 V( |# g7 u7 @) |通配符“%”和“_”可用在使用在两个表的Host字段。
% ^4 C4 k, n# E% q4 z2 c在两个表中的一个'%'或空白Host意味着“任何主机”。 5 w# _3 E# V3 S
在两个表中的Db、Table_name和Column_name字段不能包含通配符或空白。 + b7 D/ J' w: p
tables_priv和columns_priv表在Host、Db和User字段上被排序。这类似于 3 q! v( z. u6 w6 X6 n; `6 X
db表的排序,尽管因为只有Host字段可以包含通配符,但排序更简单。
; f% l3 C0 i1 }0 m# [9 g6 d# r7 \3 {( L. z% K3 R9 P
请求证实进程在下面描述。(如果你熟悉存取检查的源代码,你会注意到这
) f( z) B/ H+ d2 t里的描述与在代码使用的算法略有不同。描述等价于代码实际做的东西;它只是 " t! P3 F: x( p+ i- l/ E
不同于使解释更简单。) , A4 H& F- i9 x$ n1 H; d( r
! y' l& v, ~3 ?% s( Z# w6 s
对管理请求(shutdown、reload等等),服务器仅检查user表条目,因为那是
# f: t! r( F# [: W8 L唯一指定管理权限的表。如果条目许可请求的操作,存取被授权了,否则拒绝。
+ w# d, e" D! N1 w) G1 w例如,如果你想要执行mysqladmin shutdown,但是你的user表条目没有为你授
0 m* Y' V8 Y$ O, D- w5 {# P) z予shutdown权限,存取甚至不用检查db或host表就被拒绝。(因为他们不包含 ) K# S8 \. Y& `5 g7 x( p, D
Shutdown_priv行列,没有这样做的必要。) - f/ K1 l" F2 W

/ q3 c, D% ?) m2 P" Y" _对数据库有关的请求(insert、update等等),服务器首先通过查找user表
& D- X$ g: C# c5 f2 \% p) i# m" r条目来检查用户的全局(超级用户)权限。如果条目允许请求的操作,存取被授
/ H- Z" s3 c$ s权。如果在user表中全局权限不够,服务器通过检查db和host表确定特定的用
* Z2 P: ?( h; W, R/ v0 X$ Z$ L6 `  z9 n" C户数据库权限: % c2 e4 f$ K. C/ T

- U& g9 W2 I3 j: u4 {5 W3 R服务器在db表的Host、Db和User字段上查找一个匹配。 Host和User对应连
9 B2 k! G4 f0 [, j5 v( {! X% o6 z接用户的主机名和MySQL用户名。Db字段对应用户想要存取的数据库。如果没有   T) F) e: W" ^' ]& F2 u1 ]5 K" ?% T6 Y
Host和User的条目,存取被拒绝。 - x9 h4 ?, {, U$ |3 B6 Y
如果db表中的条目有一个匹配而且它的Host字段不是空白的,该条目定义用
0 b! O0 ~, l" C户的数据库特定的权限。 + h! e: [) u, j) ?$ E
如果匹配的db表的条目的Host字段是空白的,它表示host表列举主机应该被
/ ~. F: ~2 ~! T5 r8 z允许存取数据库的主机。在这种情况下,在host表中作进一步查找以发现Host和
. A1 \7 O7 X9 l# l& L9 kDb字段上的匹配。如果没有host表条目匹配,存取被拒绝。如果有匹配,用户数
* p7 a' Z- O7 e: @3 h. R1 i据库特定的权限以在db和host表的条目的权限,即在两个条目都是'Y'的权限的交 7 {+ p1 o9 V/ _) o' d
集(而不是并集!)计算。(这样你可以授予在db表条目中的一般权限,然后用host ; w" {& b, \7 D+ a+ c4 `
表条目按一个主机一个主机为基础地有选择地限制它们。)
% r! d& e( b: y+ J: |* S. z9 I在确定了由db和host表条目授予的数据库特定的权限后,服务器把他们加到
& |. V' r& E4 p, B5 K9 C由user表授予的全局权限中。如果结果允许请求的操作,存取被授权。否则,服 # j  D, B; `3 w5 O+ m9 n% T
务器检查在tables_priv和columns_priv表中的用户的表和列权限并把它们加到
1 r, m* {" W* @6 s' l- ~9 M用户权限中。基于此结果允许或拒绝存取。 / A/ a1 s. l: \8 ~5 x+ u1 v

* S$ ^& _% D& g2 Q! X, B4 y用布尔术语表示,前面关于一个用户权限如何计算的描述可以这样总结: 4 x* {# Z& }2 t5 {: T: e" P* F

$ |! U) Q# F. e( @1 z  Lglobal privileges
% G" N3 P0 q; J& e3 o& G/ k2 \OR (database privileges AND host privileges) 8 _8 X) \: W8 [/ u3 J9 ]
OR table privileges
2 C7 J2 ?9 c9 \- KOR column privileges + W$ s" h5 P9 Y, \7 }) H
: J, T% `1 N5 @) x3 U3 ?( s) {8 l
它可能不明显,为什么呢,如果全局user条目的权限最初发现对请求的操作不 4 w. t' {; Q% `2 B
够,服务器以后把这些权限加到数据库、表和列的特定权限。原因是一个请求可能 1 Q1 a# N* B7 p+ P$ Q) [# g% O
要求超过一种类型的权限。例如,如果你执行一个INSERT ... SELECT语句,你就都
+ [' M1 b) j$ I$ p+ ^& i要insert和select权限。你的权限必须如此以便user表条目授予一个权限而db表条 " n4 m7 k  y$ }" R" m
目授予另一个。在这种情况下,你有必要的权限执行请求,但是服务器不能自己把 7 T3 u3 j1 h, q' v) P0 f! A
两个表区别开来;两个条目授予的权限必须组合起来。 9 r1 f! n$ Q$ h/ u5 V6 x" S; a

/ B6 Y, p7 F( O; k5 ]  Q' ?host表能被用来维护一个“安全”服务器列表。在TcX,host表包含一个在本 , t8 b- C7 V. Z' O  ~2 P' q0 _0 P
地的网络上所有的机器的表,这些被授予所有的权限。
) O% E& H. j5 d  B! O
* k/ l( g2 }3 |' R  j你也可以使用host表指定不安全的主机。假定你有一台机器public.your. 1 z! b+ F3 B* @9 z
domain,它位于你不认为是安全的一个公共区域,你可以用下列的host表条目子允
+ G) K! |+ @  {许除了那台机器外的网络上所有主机的存取:
3 s# O) F) M9 y6 a  a& n# e' K) k+ V4 r! q. A% y( O& N

0 D8 ]4 y- l- a! L! m+--------------------+----+- + D- d# e, B0 F( S8 }+ D; d
│ Host │ Db │ ...
' S: ~# Y* r8 M+ u+--------------------+----+- , U+ `# g, b6 Y
│ public.your.domain │ % │ ... (所有权限设为 'N') & q) T7 r+ F- I1 J! I
│ %.your.domain │ % │ ... (所有权限设为 'Y') : H8 A% M6 P, W' v" U
+--------------------+----+- 9 @; H  l2 \8 {9 N
: V! E, M& R+ K- [
当然,你应该总是测试你在授权表中的条目(例如,使用mysqlaccess)让你确保
2 a. G& v3 F- H( o. L你的存取权限实际上以你认为的方式被设置。 & i0 p6 o  J& [% `$ n
+ ^8 m0 x4 _% ~( {4 W& q( N
权限更改何时生效 - |. j4 I  Y4 B  {. Z; ]) b, M+ h
当mysqld启动时,所有的授权表内容被读进存储器并且从那点生效。
! ^+ G1 ?5 |1 v. v7 O' r( U$ L5 O
用GRANT、REVOKE或SET PASSWORD对授权表施行的修改会立即被服务器注意到。
8 [' H) l; H( u  d9 Y3 ?7 g" m4 t0 }
如果你手工地修改授权表(使用INSERT、UPDATE等等),你应该执行一个FLUSH
# I& M0 }( O0 _( E+ `PRIVILEGES语句或运行mysqladmin flush-privileges告诉服务器再装载授权表,否
5 h. r' r7 V6 P$ W+ ^% y4 x则你的改变将不生效,除非你重启服务器。
/ j4 P8 }$ g6 a( o8 v+ D
. Z  _  |0 h  q% b* J0 M当服务器注意到授权表被改变了时,现存的客户连接有如下影响:
7 ^$ A$ U& g1 c* _3 [% q  R. j5 E& m; Q! i8 z+ e
表和列权限在客户的下一次请求时生效。
# v" p5 C6 n! S" g: W1 }; a数据库权限改变在下一个USE db_name命令生效。   h6 J5 V* r& \+ u0 L
全局权限的改变和口令改变在下一次客户连接时生效。 1 }! X) _, d* p4 ~( C1 A
& r  s3 X$ l/ h; M5 I
建立初始的MySQL权限
8 X- o* B. `$ _* K在安装MySQL后,你通过运行scripts/mysql_install_db安装初始的存取权限。
/ g+ F3 U6 |& z! Y% q1 sscripts/mysql_install_db脚本启动mysqld服务器,然后初始化授权表,包含下列
( g& D" t9 y; b9 E. W权限集合: 0 L! r4 F% ~# `2 @9 ^) X

6 ^" ?! }$ Y) r2 FMySQL root用户作为可做任何事情的一个超级用户被创造。连接必须由本地主
/ |8 k/ j% |, I# f机发出。注意:出世的root口令是空的,因此任何人能以root而没有一个口令进行 6 N3 h; u/ \5 C0 s% Q- T
连接并且被授予所有权限。   M8 Z+ \# p* Y' M% k) U% @
一个匿名用户被创造,他可对有一个'test'或以'test_'开始的名字的数据库
3 w3 x. B& i4 S$ x; V做任何时期事情,连接必须由本地主机发出。这意味着任何本地用户能连接并且视 8 P1 o9 a- f& V( X% b
为匿名用户。 & d$ z) D2 q# r' V0 ]
其他权限被拒绝。例如,一般用户不能使用mysqladmin shutdown或
' R3 A+ D8 c8 w- c7 x" q% _mysqladmin processlist。 # }2 R' ^- x$ F6 s1 o5 _- }  Z4 r
注意:对Win32的初始权限是不同的。 / E( C+ c3 F0 r1 _% U# \
, X: B8 g5 U1 Z. g5 \+ t! p  O
既然你的安装初始时广开大门,你首先应该做的事情之一是为MySQL root用户 7 X6 s1 l- F0 i' Y8 x
指定一个口令。你可以做如下(注意,你使用PASSWORD()函数指定口令):
$ m  s1 E! u) f. Q; d, r
$ H: Y) q( v! @0 kshell> mysql -u root mysql 2 p1 }; ?* t+ T2 T
mysql> UPDATE user SET Password=PASSWORD('new_password')
3 c# [2 f0 o7 B: W  bWHERE user='root';
9 M7 A# E: L& d9 i5 `2 Fmysql> FLUSH PRIVILEGES; ! M' T; l% j+ o  @8 @  Z( z: y

2 j& u( V  ?7 G在MySQL 3.22和以上版本中,你可以使用SET PASSWORD语句:
% k- Z/ F! L; j9 D* b4 M8 y
" W6 F- E  _# wshell> mysql -u root mysql
5 \3 f6 {7 t% v# `mysql> SET PASSWORD FOR root=PASSWORD('new_password');
5 S/ ?; t# S: r1 z
/ F5 Z" o: C2 j1 [* y5 o设置口令的另一种方法是使用mysqladmin命令: ; ]1 U/ O! p) }( p0 B: \
6 E+ Z, R/ a( s* @) X2 z1 Z. f, l
shell> mysqladmin -u root password new_password
+ H' m. ?* v) ]4 d) b+ u; b3 F
" i7 |- h2 N/ `$ Y注意:如果你使用第一种方法在user表里直接更新口令,你必须告诉服务器 ! ~* J+ }5 k4 Q$ s, d: j) h
再次读入授权表(用FLUSH PRIVILEGES),因为否则改变将不被注意到。 . |6 E/ I# C1 r0 r

- d! W! w- y1 N, _' W一旦root口令被设置,此后当你作为root与服务器连接时,你必须供应那个 ! |2 Q" E: i: H% h
口令。
; `5 `5 A8 T1 T0 U# a/ g( Y; ~% _& j
2 B8 G/ U6 b$ a8 s$ U% ^你可能希望让root口令为空白以便当你施行附加的安装时,你不需要指定它 7 @, H; J$ |* Y: f1 }
或测试,但是保证在任何真实的生产工作中使用你的安装之前,设置它。 $ F. a* z5 T) d: N; w: x/ E' X4 a. q

. U5 ?: E; w: n8 c9 f  y看看scripts/mysql_install_db脚本,看它如何安装缺省的权限。你可用它
% l2 Q" a% y- x" Q作为一个研究如何增加其他用户的基础。
- n" h3 P  G; M" R$ Y: A& |- e4 g) g$ M: |2 }: B
如果你想要初始的权限不同于上面描述的那些,在你运行mysql_install_db ! X& T. \! f5 K: Z. K2 {3 {
之前,你可以修改它。 2 c3 ~, R/ _: o' B, T8 }! M
6 l& X. h9 G, k" r9 B
为了完全重建权限表,删除在包含mysql数据库的目录下所有“*.frm”,
9 X' a$ o6 r! B& H" X“*.MYI”和“*.MYD”文件。(这是在数据库目录下面命名为“mysql”的目录,   G, Y  R2 `  k* k+ C' k* U2 M; [6 i6 o
当你运行mysqld --help时,它被列出。)然后运行mysql_install_db脚本,可能 * C& ~9 I0 [1 G! ^( }$ ^
在首先编辑它拥有你想要的权限之后。
. a* Z2 H& ?# x' _, T# v+ R
) ]$ B+ l; ?+ k0 W+ X: a注意:对于比MySQL 3.22.10旧的版本,你不应该删除“*.frm”文件。如果
4 L& v- Y3 \: g2 }- L你偶然做了,你应该在运行mysql_install_db之前你的MySQL分发中拷回它们。 , ?) _  g. ^8 n$ Z( M' @( e
9 o0 h. L5 h% j4 K/ V; @7 V3 f. {
向MySQL增加新用户权限 3 V& L9 }5 T1 T+ ]1 l0 q5 r& D7 p  [
你可以有2个不同的方法增加用户:通过使用GRANT语句或通过直接操作MySQL授
8 j" J4 k: ?# X权表。比较好的方法是使用GRANT语句,因为他们是更简明并且好像错误少些。 2 S3 ]* c# n$ H5 N  D9 Z

7 S' j& M" ?3 y. K$ [2 B% H( a$ Q下面的例子显示出如何使用mysql客户安装新用户。这些例子假定权限根据以前
& @% P; [! d* B+ |  M的章节描述的缺省被安装。这意味着为了改变,你必须在mysqld正在运行同一台 ! V* r, l+ m" k+ A" U
机器上,你必须作为MySQL root用户连接,并且root用户必须对mysql数据库有
6 R) U2 T* \5 V; x0 x2 B& ?insert权限和reload管理权限。另外,如果你改变了root用户口令,你必须如下 ; K) f3 }# n# R. M8 T4 c; H# g
的mysql命令指定它。 & |" ]; I1 q, M3 }# |: q5 x7 K  @

# ?6 P' n5 S# b你可以通过发出GRANT语句增加新用户:
! A# r/ ?  t# o) `  g' u) c- y) f0 c) o
shell> mysql --user=root mysql
- R) k! p( B! x8 ^) b* Tmysql> GRANT ALL PRIVILEGES ON *.* TO monty@localhost 5 ~8 s6 w) q9 g& c
IDENTIFIED BY 'something' WITH GRANT OPTION; ; N4 G/ b5 C# f5 S
mysql> GRANT ALL PRIVILEGES ON *.* TO monty@"%"
3 m) f' P  o- q5 m* KIDENTIFIED BY 'something' WITH GRANT OPTION;
* b" k& e+ s0 I( T, kmysql> GRANT RELOAD,PROCESS ON *.* TO admin@localhost; , |. \. t2 U% c% G0 l( U6 ^
mysql> GRANT USAGE ON *.* TO dummy@localhost; : z: J5 q% s7 b( s( z* L
" ]' u9 C. {& w7 f7 y
这些GRANT语句安装3个新用户: 9 S8 A8 z. i4 @9 T
9 B% N6 W/ l3 G$ C" ^4 t
monty
7 R& @+ Q7 U- o可以从任何地方连接服务器的一个完全的超级用户,但是必须使用一个
8 B' W( U, Q) U+ _1 c7 B; h1 Z口令('something'做这个。注意,我们必须对monty@localhost和monty@"%" - \2 m) H& C: |/ G$ r: X) J6 C
发出GRANT语句。如果我们增加localhost条目,对localhost的匿名用户条目
$ m, Z; h* b4 f4 `0 }/ f1 u4 M9 m在我们从本地主机连接接时由mysql_install_db创建的条目将优先考虑,因为 9 q4 b/ h7 o, H9 K# _  S
它有更特定的Host字段值,所以以user表排列顺序看更早到来。 1 r8 {! t9 O; [* v" `- n, w; S
admin ( p3 m* N, o& g
可以从localhost没有一个口令进行连接并且被授予reload和process管理 . p* s, C  Y7 ?' J5 _* b/ v
权限的用户。这允许用户执行mysqladmin reload、mysqladmin refresh和 3 G: ]8 ^- A- D& n( \0 A
mysqladmin flush-*命令,还有mysqladmin processlist。没有授予数据库有 1 J7 G( F+ D( T! X/ o, c& a
关的权限。他们能在以后通过发出另一个GRANT语句授权。
% @, b. w- ~! s1 u  s6 e& x) mdummy * a! P, m7 ?, L
可以不用一个口令连接的一个用户,但是只能从本地主机。全局权限被设 1 ?3 y' B* \+ o5 [3 X2 A
置为'N'--USAGE权限类型允许你无需权限就可设置一个用户。它假定你将在以
" U. A8 O8 T2 i! M/ z后授予数据库相关的权限。 $ T, b  D2 O( T2 ~
你也可以直接通过发出INSERT语句增加同样的用户存取信息,然后告诉服
4 G- ~9 E+ c' ], H' t4 W9 }务器再次装入授权表:
2 h( e2 l9 J/ `8 T9 z3 y3 _6 l1 A4 G4 w' K; m" {. V) |
shell> mysql --user=root mysql
- E- f$ |' U7 k- ^7 Jmysql> INSERT INTO user VALUES('localhost','monty',PASSWORD
, f2 C& h8 V# P" X5 I('something'),
0 G, [; x& `$ J  B: z. Q'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y', 7 x' H' v4 Y- V0 `0 M
'Y','Y')
6 N1 N. D1 v+ g. o8 M+ f" V) e, v' qmysql> INSERT INTO user VALUES('%','monty',PASSWORD('something'),
* ]+ F9 K% S7 d5 J6 B'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y', - c- f+ w: |# ^+ v' @1 y
'Y')
  _/ S" K* O% j7 Kmysql> INSERT INTO user SET Host='localhost',User='admin',
3 t! b! V/ p' ?9 h) M0 T0 }9 a  ZReload_priv='Y', Process_priv='Y';
( x2 P) |5 S* h+ T& Vmysql> INSERT INTO user (Host,User,Password) " c8 F, \$ K+ W9 r
VALUES('localhost','dummy','');
7 ^8 h$ [/ t. `6 Z7 B/ k! ?- g3 gmysql> FLUSH PRIVILEGES;
2 Z9 q9 ]0 n4 ?5 B, h+ ^7 W
/ u6 n/ [9 x' |2 x* F3 `0 F取决于你的MySQL版本,对上述,你可能必须使用一个不同数目'Y'值(在 7 n7 x+ X9 g$ p3 o. s- n' L/ l
3.22.11以前的版本有更少的权限列)。对admin用户,只用在3.22.11开始的版
1 V% o' S% U! h! ^" U' s本具有的更加可读的INSERT扩充的语法。
3 p- a% _/ ~+ x
6 J5 F- X( d+ X0 Q' D" H注意,为了设置一个超级用户,你只需创造一个user表条目,其权限字段设为
4 t! c+ b- A* p* K'Y'。不需要db或host表的条目。
0 ~4 ~& D, m" @0 U
2 n; |; ?+ j6 _$ M" o在user表中的权限列不是由最后一个INSERT语句明确设置的(对dummy用户),
  h9 X2 O" t5 i因此那些列被赋予缺省值'N'。这是GRANT USAGE做的同样的事情。
5 l% p% X0 v7 w7 X) k2 u% n
4 |  h0 x: }0 j, n8 t下列例子增加一个用户custom,他能从主机localhost、server.domain和 ( E: q5 b0 k( z$ Z# r1 ]3 M2 V
whitehouse.gov连接。他只想要从localhost存取bankaccount数据库,从
4 i3 E) {6 B' k/ {' V. P4 S! mwhitehouse.gov存取expenses数据库和从所有3台主机存取customer数据库。他 & x5 R0 Y* H" |! I
想要从所有3台主机上使用口令stupid。 $ ?: _+ z. z! r/ e/ I1 q
( O% l, r4 v  G& X
为了使用GRANT语句设置个用户的权限,运行这些命令:
, Q4 f/ t2 r( q- j# H& k1 o  j, T# u. P/ k( [
shell> mysql --user=root mysql , R- \  }$ @" B  e' T* Q
mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
4 u; s7 ~! Z/ @' K9 h4 S: dON bankaccount.*
$ c+ X' v5 V" O. M6 E( wTO custom@localhost
7 c1 s( c5 {3 o( s, J" L1 C# wIDENTIFIED BY 'stupid';
$ Z) K/ R4 ?- @) s8 g" N: q6 Mmysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
( l* F6 Y/ B4 oON expenses.* $ v" n( a& f" v& Q) _8 a% ~
TO custom@whitehouse.gov 8 A  X3 c4 ]: I1 M$ z5 [( b
IDENTIFIED BY 'stupid';
$ J( Y4 A* T( z& t: @4 q* k6 {! ~mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
7 ]+ h: q  q5 Q: VON customer.*
* f, O; X0 z+ l/ h. E5 NTO custom@'%' 3 N3 R0 W/ O) q/ J; F" m
IDENTIFIED BY 'stupid';
9 D. s# S7 T; p2 [
/ Z: y$ k; X' Y2 M- _# P  n+ S! N通过直接修改授权表设置用户权限,运行这些命令(注意,在结束时 * y0 z( t7 P; ]( p: V$ q) H( }: d
FLUSH PRIVILEGES):
% S3 ~" R5 i3 M$ _; k+ }3 l
1 N: f7 Q5 S7 D' A6 M* F: Q- `" kshell> mysql --user=root mysql
7 B  x; V2 h8 u0 o0 y* Fmysql> INSERT INTO user (Host,User,Password) 9 a8 R& a8 ~. `7 `
VALUES('localhost','custom',PASSWORD('stupid'));
3 Q) M2 J' s& xmysql> INSERT INTO user (Host,User,Password) , C- D  c1 y0 T+ d
VALUES('server.domain','custom',PASSWORD('stupid'));
5 y% y0 N% F6 A. l! v/ Fmysql> INSERT INTO user (Host,User,Password) ( M: |2 o: L, J# w# t; \
VALUES('whitehouse.gov','custom',PASSWORD('stupid')); # \. Z5 X. e6 r7 d8 \
mysql> INSERT INTO db
/ w: Y6 R9 H) r8 x: {/ {(Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv, ( q3 f6 d' A& X. U$ {; j6 H+ f
Create_priv,Drop_priv)
5 o( u: [( \" i3 bVALUES
* m+ ]5 B  F* W9 a('localhost','bankaccount','custom','Y','Y','Y','Y','Y','Y');
2 a- i" I6 q% Z7 O* {2 omysql> INSERT INTO db
0 Y, k  @2 g& J(Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv,
, U% P1 h2 p* U- m8 ?' s+ wCreate_priv,Drop_priv) 0 B$ m0 y2 R8 k! r
VALUES
4 T& b: d4 ?8 c  a' N9 c8 G$ J& ~" Q('whitehouse.gov','expenses','custom','Y','Y','Y','Y','Y','Y');
% V7 P' x1 u  t1 Rmysql> INSERT INTO db # U, S* m- N) F, j& T. K$ y  C
(Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv, / I2 F( B" N6 i: X) A
Create_priv,Drop_priv) ( m# p" p: r* d2 B
VALUES('%','customer','custom','Y','Y','Y','Y','Y','Y');
4 X  q* n% h; v' }# R, s. ~mysql> FLUSH PRIVILEGES; 4 F" w3 t" V% H
0 @- U& G" y7 w2 f6 j; D
头3个INSERT语句增加user表条目,允许用户custom用给定口令从不同的主机
; g) f1 T- J+ p7 d. p  T: N  K进行连接,但是没有授予任何许可(所有权限被设置为缺省值'N')。后3个INSERT 5 n2 Y. J) i- X. A" y) o' B) c/ k
语句增加db表条目,授予custom以bankaccount、expenses和customer数据库权限,
/ }2 U$ j4 f4 V& p: Z! m! D但是只能在从正确的主机存取时。通常,在授权表直接被修改时,服务器必须被告 ( k. O$ M, S- @7 ^% |
知再次装入他们(用FLUSH PRIVILEGES)以便使权限修改生效。   |  }; q% V# e" ~) |. v
) _7 o% S( B: @' s  W0 \. p! E
如果你想要给特定的用户从一个给定的域上的任何机器上存取权限,你可以发
; K( P0 n# e4 a$ R出一个如下的GRANT语句:
' L7 S4 [5 r5 N8 I+ m; R% d: ?/ k3 O% U9 V; Q4 n
mysql> GRANT ... - ?) h4 ^* {# c2 I
ON *.* 2 U) |8 k! V7 _8 A# k
TO myusername@"%.mydomainname.com"
; E8 B6 }7 ^- }+ F& m) ?IDENTIFIED BY 'mypassword';
. [6 {0 R% p% L; Z2 X9 r" _
' r. q. C8 j. u# ?" F+ i为了通过直接修改授权表做同样的事情,这样做: - @% i" T9 k6 y5 x2 E
% I, o6 ?) G( }9 }
mysql> INSERT INTO user VALUES ('%.mydomainname.com', 'myusername', - u) Z; m8 Y3 v! N- z3 v
PASSWORD('mypassword'),...); 6 {8 m. S  I! A" i
mysql> FLUSH PRIVILEGES;
0 O6 L9 H1 j: U1 C6 z9 P
/ Q+ n7 Q2 s: [* P( Q, o. D你也可以使用xmysqladmin、mysql_webadmin甚至xmysql在授权表中插入、改变 9 b& }! {* T1 k1 N
和更新值。你可以在MySQL的Contrib目录找到这些实用程序。
7 q- ]- P1 E9 H6 x: Z5 ~; Y4 N$ B) m* d. q; e
怎样设置口令 . c5 T. U1 k' Z) Q: l, X1 g
在前面小节的例子里说明了一个重要的原则:当你使用INSERT或UPDATE语句存 3 m6 k- Y0 H. v$ j& N/ j2 E$ }
储一个非空的口令时,你必须使用PASSWORD()函数加密它。这是因为在user表中以
9 R+ E5 l* h3 `1 V7 i" c8 y- f  n2 p加密形式存储口令,而不是作为纯文本。如果你忘记这个事实,你可能像这样试图 7 h2 d) A) ^3 B: f5 ^9 M
设置口令:
2 B1 n6 k6 h# B' _; z2 q9 G4 ]/ A5 W+ k0 a7 T# |  E4 F3 z" B! @7 i
shell> mysql -u root mysql
" W+ r+ L- n( m- k0 i2 Kmysql> INSERT INTO user (Host,User,Password) VALUES('%','jeffrey',
0 T) ]- P% N3 v/ l5 q'biscuit'); ) T8 p) o. w1 r$ [
mysql> FLUSH PRIVILEGES 1 d3 S+ a4 O# e' n9 ~& D, b

  _4 q9 D" \5 E) W* g- O' O3 G结果是纯文本值'biscuit'作为口令被存储在user表中。在用户jeffrey试图用 4 `# k6 U5 b% R; B# M
这个口令连接服务器时,mysql客户用PASSWORD()加密它并且将结果送给服务器,服
4 i$ [- k- d# s务器比较在user表中的值(它是纯文本值'biscuit')和加密的口令(而不是 * T: \0 P6 {( p$ I( O
'biscuit'),比较失败并且服务器拒绝连接: % o! Y  t6 z0 I+ ]% r

5 m) ~9 l  ~: F! tshell> mysql -u jeffrey -pbiscuit test
2 N! L6 @+ G5 Z) l0 rAccess denied
% D. T1 ^) ~: G) |
5 [6 S% y% J1 ^9 {" g4 A8 o' ^因为当他们被插入user表时,口令必须被加密,相反,INSERT语句应该象这样 * z( e1 k0 w: {6 H' K
被指定:
  d1 n7 r, j7 R) ~( V9 p5 M% `5 y- [0 u# i
mysql> INSERT INTO user (Host,User,Password)
- @- w+ M2 C% {) l2 CVALUES('%','jeffrey',PASSWORD('biscuit'));
4 f% ?5 T5 N) ]7 p7 b' S* h1 @0 x: ^  C* l6 A7 f
当你使用SET PASSWORD语句时,你也必须使用PASSWORD()函数: / B) V. k0 q) q' W

/ J& O* k! J1 N. L" imysql> SET PASSWORD FOR jeffrey@"%" = PASSWORD('biscuit'); 6 y+ Z1 D2 Z) K9 P7 S  k
/ f2 C/ j* s0 Q% b8 c8 P
如果你使用GRANT ... IDENTIFIED BY语句或mysqladmin password命令设置口 0 [$ D6 X$ |/ S) ]
令,PASSWORD()函数是不必要的。他们都考虑到为你加密口令,多以你可像这样指 2 H# O8 [% _: n6 x4 n+ l
定一个口令'biscuit':
; I, C) ~  ?$ Q, _+ o2 ]/ A( B0 Z
mysql> GRANT USAGE ON *.* TO jeffrey@"%" IDENTIFIED BY 'biscuit'; 4 k) c  c! ~9 C0 Z; _
. T" j: Y: j1 U% O1 ?2 @* A

0 h3 T( }+ }; e/ A- s2 I& |$ n8 }" v# `: J9 _- H* u$ L
shell> mysqladmin -u jeffrey password biscuit 3 I4 C, d) T" _5 `3 r- [
注意: PASSWORD()不是以在Unix口令加密的同样方法施行口令加密。你不应
2 V. v' F( W" T该假定如果你的Unix口令和你的MySQL口令是一样的,PASSWORD()将导致与在Unix
) o8 P1 H5 A+ z* W6 w+ {0 ]  L口令文件被存储的同样的加密值。见6.2 MySQL 用户名和口令。
3 e& S+ R0 H2 i2 I1 p/ h. h# H- I8 v4 M" ^* C
Access denied错误的原因 . m( v# Q7 e; n$ [8 v7 E
当你试着联接MySQL服务器时,如果你碰到Access denied错误,显示在下面 / S7 r- y! [4 F
的表指出一些你能用来更正这个问题的动作:   x4 M0 n! L2 f" s
# N1 G1 U8 o% g
你是在安装MySQL以后运行mysql_install_db的脚本,来设置初始授权表内容 - E0 u* ?. m5 n& [! `' n
吗?如果不是,这样做。见6.10 设置初始MySQL权限。通过执行这个命令测试初 0 i8 S. s" B; I9 j. c  ~9 y6 a3 ]
始权限:
4 F5 [3 a+ b4 ^+ P: \# Vshell> mysql -u root test 9 K+ V- t* B. w' d3 d

! j- f5 o+ S4 F服务器应该让你无误地连接。你也应该保证你在MySQL数据库目录有一个文件
9 E2 ~  x$ m! x0 r. ?( p( l“user.MYD”。通常,它是“PATH/var/mysql/user.MYD”,在此PATH是MySQL安 8 F# }& b0 M# ^/ |! V! S
装根目录的路径。 ( H. D* L& R/ r2 }( |

3 Y/ u. |7 U8 [- I( h% S在一个新的安装以后,你应该连接服务器并且设置你的用户及其存取许可: # q% A8 h5 b2 E. m+ {2 H1 m
shell> mysql -u root mysql
- r- t- ?' n, U" V
8 q; H8 q# V* G( i' ?服务器应该让你连接,因为MySQL root用户初始时没有口令。既然那也是一个
( [% D' s9 g! ]+ Z3 ^安全风险,当你正在设置其他MySQL用户时,设定root口令是一件重要的事请。如 7 S" b6 s# h( Y7 `3 g4 h
果你作为root尝试连接并且得到这个错误:
, ~3 Y9 e* w1 S- ^$ w3 K1 o) H0 B- ?1 u# I, P7 ]1 D
Access denied for user: '@unknown' to database mysql : k$ ~! y9 A! }7 ?' W

. @1 j: T* Q9 \这意味着,你没有一个条目在user表中的一个User列值为'root'并且mysqld : s# |" }6 r& w1 Q
不能为你的客库解析主机名。在这种情况下,你必须用--skip-grant-tables选项 3 e' k) S. b. r: `1 J3 X3 V3 s
重启服务器并且编辑你的“/etc/hosts”或“\windows\hosts”文件为你的主机 5 R! P3 I- A7 J, @' c5 m. f
增加一个条目。 : }0 Z, T. O- n& R9 a/ ?
1 {1 }- x) N4 N6 F, z- _0 J! N/ j
如果你从一个3.22.11以前的版本更新一个现存的MySQL安装到3.22.11版或以
) V4 L7 L7 T' o8 W后版本,你运行了mysql_fix_privilege_tables脚本吗?如果没有,运行它。在
& U' J3 \1 _$ D. c( V( VGRANT语句变得能工作时,授权表的结构用MySQL 3.22.11修改 。
0 @+ y8 S) |3 }6 M" [如果你直接对授权表做修改(使用INSERT或UPDATE语句)并且你的改变似乎被 . h  x' d* D2 G+ g8 y! z6 n
忽略,记住,你必须发出一个FLUSH PRIVILEGES语句或执行一个mysqladmin
1 N1 T' x8 D5 x. e+ P- Rflush-privileges命令导致服务器再次读入表,否则你的改变要道下一次服务器被 # }% `, K2 k3 d0 S' a
重启时再生效。记住在你设定root口令以后,你将不需要指定它,直到在你清洗 8 `( I4 X9 [5 J
(flush)权限以后,因为服务器仍然不会知道你改变了口令!
. y4 n; I0 h1 x* v# X* u如果你的权限似乎在一个会话(session)当中改变了,可能是一个超级用户改变 & q5 h& g3 w* ^# ]8 ~
了他们。再次装入授权表作用于新客户连接,但是它也影响现存的连接,如6.9 权
, `6 d1 U! `0 @9 p限改变何时生效小节所述。
2 z7 c; c, k& ]$ I: ^# ]为了测试,用--skip-grant-tables选项启动mysqld守护进程,然后你可以改变
! O3 f1 N5 ?! k/ \6 h( GMySQL授权表并且使用mysqlaccess脚本检查你的修改是否有如期的效果。当你对你的 9 q0 o. ]/ ]+ B6 ~0 Q- |
改变满意时,执行mysqladmin flush-privileges告诉mysqld服务器开始使用新的权
8 _# v* K2 t% o) U限表。注意:再次装入授权表覆盖了--skip-grant-tables选项。这允许你告诉服务
3 V; p8 I4 t1 w1 i+ B/ k* m器开始使用授权表,而不用停掉并重启它。   A* I# [1 [. X
如果你有一个Perl、Python或ODBC程序的存取问题,试着用mysql -u user_name
0 ~5 |: }; X: U2 {/ i& ~db_name或mysql -u user_name -pyour_pass db_name与服务器连接。如果你能用 ! \( ~, i) g) E9 b
mysql客户连接,这是你程序的一个问题而不是存取权限的问题。(注意在-p和口令 # [! X# I' x9 Y  c
之间没有空格;你也能使用--password=your_pass句法指定口令。) - R# L# ~, c$ G0 T3 ^6 p
如果你不能让口令工作,记得如果你用INSERT, UPDATE或SET PASSWORD语句
2 P, X+ X& G! `( Y# c' \1 v/ M设置口令,你必须使用PASSWORD()函数。如果你用GRANT ... INDENTIFIED BY语
4 S) v+ R7 W4 B, H8 ^0 v0 G: n句或mysqladmin password命令指定口令,PASSWORD()函数是不需要的。 9 o: u( Q$ d7 @9 O6 w. U
localhost是你本地主机名的一个同义词,并且也是如果你不明确地指定主机 : _. ?$ o1 U% F) b
而客户尝试连接的缺省主机。然而,如果你正在运行于一个使用MIT-pthreads的系
0 w! {& i; A, O4 g6 E: @统上,连接localhost是不行的(localhost连接使用Unix套接字进行,它没被 MIT   ~( C2 _# v9 j3 m2 e; q
-pthreads支持),为了在这样的系统上避免这个问题,你应该使用--host选项明确 5 w' w% G( G0 N" D  S3 ]4 @/ U
地命名服务器主机,这将做一个 TCP/IP连接到mysqld服务器。在这种情况下,你 9 B) k0 N9 J( M
必须有在服务器主机上的user表中条目的你真实的主机名。(即使你在服务器同一
% G5 U. s0 Z; w% Z台的主机上运行一个客户程序,这也是真的。) 6 u. d% M# l$ }; f$ o/ |: J) l
当尝试用mysql -u user_name db_name与数据库连接时,如果你得到一个
, k8 V" m6 J* O1 \) E6 S( OAccess denied错误,你可能有与user桌有关的问题,通过执行mysql -u root   n* r$ `7 t) g
mysql并且发出下面的SQL语句检查:
& V; J: M( j  O" ?. I2 R: ~mysql> SELECT * FROM user; ; E  P' x* f$ z

  n* v( s" v0 ^3 l结果应该包含一个有Host和User列的条目匹配你的计算机主机名和你的MySQL用户 ! h" Q) I3 V* N6 g
名。 " R& C% \# {$ z
6 G5 N' ^' A6 X+ X
Access denied错误消息将告诉你,你正在用哪个用户尝试登录,你正在试图 . ]9 d# `" G6 [& j: ^1 w1 i" u
用连接哪个主机,并且你是否正在使用一个口令。通常,你应该在user表中有一
" |7 R- y# L: }' j5 |个条目,正确地匹配在错误消息给出的主机名和用户名。 - g5 _) j7 g1 ?# P7 B" g
如果当你试着从一个不是MySQL服务器正在运行的主机上连接时,你得到下列 8 M7 g6 Y" |# P) h
错误,那么在user表中没有匹配那台主机行: , E! Q0 R% S" D- p
Host ... is not allowed to connect to this MySQL server
6 q+ a) }& l  W
+ F  t* a6 y  Q# U% g你可以通过使用mysql命令行工具(在服务器主机上!)修正它,把你正在试 7 c/ X: V, X/ u2 k7 r5 P$ X8 q
图连接的用户/主机名组合新加一行到user表中。如果你不在运行MySQL 3.22并且
" L( w4 K" Y9 `* o& s你不知道你正在从它连接的机器的IP数字或主机名,你应该把一个'%'条目作为
2 w$ Y, A) }4 h; x# j- aHost列值放在user表中并且在服务器机器上使用--log选项重启mysqld。在试图从
, M) J5 h7 \2 b客户机器连接以后,在MySQL记录文件中的信息将显示你如何真正进行连接。(
6 n: a+ s9 k# u- q6 H) n% i* B( e然后用在记录文件上面显示出的实际的主机名代替user表中的'%'条目。否则, , ^2 {: q9 l/ z- y! n
你将有一个不安全的系统。)
5 K/ u2 t  A+ x" b
) e( q+ R7 k, E- G1 N7 [如果mysql -u root test工作但是mysql -h your_hostname -u root test
1 N2 L. g+ W! N8 k' r0 f/ j, P导致Access denied,那么在user表中你可能没有你的主机的正确名字。这里的 ' I+ |' w9 k- `: z+ i/ X$ ~- s
一个普遍的问题是在user表条目中的Host值指定一个唯一的主机名,但是你系统
- u3 Z0 f9 S1 `% }  z+ L的名字解析例程返回一个完全正规的域名(或相反)。例如,如果你在user表中有
) s8 H$ L7 \/ [, H3 i0 I一个主机是'tcx'的条目,但是你的 DNS告诉MySQL你的主机名是'tcx.subnet. 5 B+ x0 B) Z$ ^, h/ D0 x9 D. F
se',条目将不工作。尝试把一个条目加到user表中,它包含你主机的IP数字作 - ^1 U! c: _$ E2 h
为Host列的值。(另外,你可以把一个条目加到user表中,它有包含一个通配符
' c! n& E% W3 y$ t* ~. {1 c如'tcx.%'的Host值。然而,使用以“%”结尾的主机名是不安全的并且不推荐!)
( b7 O& _; n; \# r如果mysql -u user_name test工作但是mysql -u user_name other_db_name
1 I& q% c1 C" ^: d5 P" y; q不工作,对other_db_name,你在db表中没有没有一个条目列出。 , A3 \0 W% Z0 U4 D+ n% }
当在服务器机器上执行mysql -u user_name db_name时,它工作,但是在其 4 d9 k9 d  w: W- K6 ~/ ^
它客户机器上执行mysql -h host_name -u user_name db_name时,它却不工作,
5 E2 b3 H9 |/ p你没有把客户机器列在user表或db表中。 ( L0 n1 E. o/ I3 a. N
如果你不能弄明白你为什么得到Access denied,从user表中删除所有Host
, ?; L1 C1 p# X: T8 d# m包含通配符值的条目(包含“%”或“_”的条目)。一个很普遍的错误是插入用
/ y' Y4 C6 q& L: e3 O# ~Host='%'和User='some user'插入一个新条目,认为这将允许你指定localhost 7 C% w7 h' s2 E/ @
从同一台机器进行连接。它不工作的原因是缺省权限包括一个有Host='localhost' , O; c) u- d* t1 Y$ V( G
和User=''的条目,因为那个条目一个比'%'更具体的Host值'localhost',当从 $ c' B4 g. I4 l6 z
localhost连接时,它用于指向新条目!正确的步骤是插入Host='localhost'和 0 t. a8 h$ a: d& U1 [
User='some_user'的第2个条目,或删除Host='localhost'和User=''条目。
0 a: Z$ B& P* N$ A0 ]; X; u如果你得到下列错误,你可以有一个与db或host表有关的问题:
) r* Y8 q5 B" n+ q4 K/ A: |Access to database denied ( n7 r' d* A8 ]  X: F
! h2 k$ F* S% H; n" _6 C
如果从db表中选择了在Host列有空值的条目,保证在host表中有一个或多 ) o& I* M# @4 Y( S6 r
个相应的条目,指定运用db表中的哪些主机。如果在使用SQL命令SELECT ...
& v' ^$ g+ @; aINTO OUTFILE或LOAD DATA INFILE时,你得到错误,在user表中的你的条目可 4 _/ d$ B( O6 w4 a; T( d9 T# q' @$ o! I
能启用file权限。
0 P0 k& f& r2 e+ `0 h! `0 B: R) h; o5 N0 ~
记住,客户程序将使用在配置文件或环境变量被指定了的连接参数。如果 2 M/ w$ r. E6 U& @
当你不在命令行上指定他们时,一个客户似乎正在发送错误的缺省连接参数,
) _+ r+ |) R- p% N5 Z- z检查你的环境和在你的主目录下的“.my.cnf”文件。你也可以检查系统范围
( L5 |) ^3 j! G/ t的MySQL配置文件,尽管更不可能将在那里指定那个客户的连接参数。如果当 $ k) _; {0 X7 p/ p, ^- Y" D
你没有任何选项运行一个客户时,你得到Access denied,确认你没在任何选
( \: l0 o8 A' ?& V4 H) I( O1 _' M项文件里指定一个旧的口令!见4.15.4 选项文件。 $ l! B: R( A% F, J! Q2 n3 G
如果任何其它事情失败,用调试选项(例如,--debug=d,general,query) 3 r9 g1 V) O5 _; m, u3 ]( T) c* F; Y
启动mysqld守护进程。这将打印有关尝试连接的主机和用户信息,和发出的每 8 `0 }5 e3 f, W7 y/ [; K$ o
个命令的信息。见G.1 调试一个MySQL服务器。 , j1 E( [0 ?2 G
如果你有任何与MySQL授权表的其它问题,而且觉得你必须邮寄这个问题
& N1 s* n% `/ d3 \" z到邮寄表,总是提供一个MySQL授权表的倾倒副本(dump)。你可用mysqldump
2 b$ v' C. I  I- h: xmysql命令倾倒数据库表。象平时一样,用mysqlbug脚本邮寄你的问题。在一
) c) z; d- L  x些情况下你可能用--skip-grant-tables重启mysqld以便能运行mysqldump。 * h/ S  F6 b/ g+ f+ o/ B
怎样使MySQL安全以对抗解密高手 6 w' \, y) ~" V; d" C
当你连接一个MySQL服务器时,你通常应该使用一个口令。口令不以明文
: Y$ K5 b. v% y0 @, m" o7 K在连接上传输。 3 a4 h* c$ s3 r/ u1 n7 e' p- v

  `3 ~$ Z) l4 [# w: [; K所有其它信息作为能被任何人读懂的文本被传输。如果你担心这个,你可 & I7 Y: C, `6 d4 ]9 |7 t
使用压缩协议(MySQL3.22和以上版本)使事情变得更难。甚至为了使一切更安全 " G- Q% M$ L4 m' j2 |: p3 N+ r
,你应该安装ssh(见http://www.cs.hut.fi/ssh)。用它,你能在一个MySQL服 9 i  m3 T7 u; q; ~- r
务器与一个MySQL客户之间得到一个加密的TCP/IP连接。 . o8 V4 ^% N& U; U8 `$ i7 [7 z6 g

1 f2 L/ [4 J* M& }8 H, E, t7 Q为了使一个MySQL系统安全,强烈要求你考虑下列建议: + l0 K' Y/ Q& M" A2 k
6 t! Q4 v& x, a  V
对所有MySQL用户使用口令。记住,如果other_user没有口令,任何人能简
' D1 x. ^  f+ Y单地用mysql -u other_user db_name作为任何其它的人登录。对客户机/服务器
6 Q3 y7 |' h  w! t* R/ N) ?2 D应用程序,客户可以指定任何用户名是常见的做法。在你运行它以前,你可以通
2 L* |' B& h3 b3 w1 D" ?) K过编辑mysql_install_db脚本改变所有用户的口令,或仅仅MySQL root的口令,
% D$ z: Q* k9 G: W象这样:
$ B2 ^, P# q7 F( ~  n! Lshell> mysql -u root mysql ) q% B; A* f3 R6 S
mysql> UPDATE user SET Password=PASSWORD('new_password') , I  w5 l5 y: o& F
WHERE user='root';
# ]7 m% O1 G, z& b4 E$ f  Gmysql> FLUSH PRIVILEGES; / N7 c% g: ?- \2 L
6 C( I9 O5 b  T7 W1 r. x" D
不要作为Unix的root用户运行MySQL守护进程。mysqld能以任何用户运行,
8 p3 q  ^0 s2 ~7 g7 @你也可以创造一个新的Unix用户mysql使一切更安全。如果你作为其它Unix用户 * w  U: F) |6 e
运行mysqld,你不需要改变在user表中的root用户名,因为MySQL用户名与Unix
. [% U& p, d% J- g. O用户名没关系。你可以作为其它Unix用户编辑mysql.server启动脚本mysqld。 + g$ }* J2 F, v$ M" a
通常这用su命令完成。对于更多的细节,见18.8 怎样作为一个一般用户运行 ' Y- i' \$ [, X4 W6 [3 q
MySQL。
( c1 s- J7 B# V' ^+ ]  J5 M+ b如果你把一个Unix root用户口令放在mysql.server脚本中,确保这个脚本
9 Q" x7 w0 ~$ N) @只能对root是可读的。
  @+ w2 N4 N# {1 [检查那个运行mysqld的Unix用户是唯一的在数据库目录下有读/写权限的用
- X2 ~: S$ }* T" O( |' o户。
) Y, U9 q/ c) ?8 t不要把process权限给所有用户。mysqladmin processlist的输出显示出当 9 Y3 U4 A% ]/ a
前执行的查询正文,如果另外的用户发出一个UPDATE user SET password= * l; ~- h! d3 ]+ m
PASSWORD('not_secure')查询,被允许执行那个命令的任何用户可能看得到。 + t; O% T, K( n! ^2 _+ J
mysqld为有process权限的用户保留一个额外的连接, 以便一个MySQL root用
9 u% S; j7 W8 t2 \4 Z0 Q户能登录并检查,即使所有的正常连接在使用。
6 ^8 o2 Y! D) T不要把file权限给所有的用户。有这权限的任何用户能在拥有mysqld守护
) _8 u, _, _/ ~进程权限的文件系统那里写一个文件!为了使这更安全一些,用SELECT ...
3 {( q5 {$ C$ k2 n+ TINTO OUTFILE生成的所有文件对每个人是可读的,并且你不能覆盖已经存在的
( G' S% d! H* O文件。file权限也可以被用来读取任何作为运行服务器的Unix用户可存取的文 $ E" Z  S6 w) I- W4 ^* W3 Z
件。这可能被滥用,例如,通过使用LOAD DATA装载“/etc/passwd”进一个数
0 M; F$ _. ?5 W: b/ H% L据库表,然后它能用SELECT被读入。   i$ {) |% g* F% ~+ Z3 |
如果你不信任你的DNS,你应该在授权表中使用IP数字而不是主机名。原则
: M- J( h5 h( D& [5 a上讲,--secure选项对mysqld应该使主机名更安全。在任何情况下,你应该非常
  n+ e; G6 [4 v) O; `( P9 F" g小心地使用包含通配符的主机名!
- M5 ~7 ]7 M$ X2 b$ E下列mysqld选项影响安全: " k. q2 q  N) {! L
% s& d6 P  p* U8 Z% v
--secure 3 L3 J8 @* Y+ y: ~( |3 F
由gethostbyname()系统调用返回的IP数字被检查,确保他们解析回到原来 1 d9 i8 C; R% K$ M2 k2 h
的主机名。这对某些外人通过模仿其它主机获得存取权限变得更难。这个选项也 . ?4 G" ~6 t4 B* T. a
增加一些聪明的主机名检查。在MySQL3.21里,选择缺省是关掉的,因为它有时 6 a0 n; m& u& `/ n' u
它花很长时间执行反向解析。MySQL 3.22缓存主机名并缺省地启用了这个选项。
: l% p, t( q0 U) X--skip-grant-tables 9 N0 b1 e1 z( ?2 M0 m1 i- @
这个选项导致服务器根本不使用权限系统。这给每个人以完全存取所有的数
5 c( V$ b6 w% \9 W据库的权力!(通过执行mysqladmin reload,你能告诉一个正在运行的服务器
, \" c9 R' v1 {0 O& _" `8 P) h4 Z/ n: w8 q再次开始使用授权表。)
" F* Z' e* x; W  o; f: r0 d--skip-name-resolve
* Z7 T6 A) ?7 b1 W5 ^! `7 }3 t' r主机名不被解析。所有在授权表的Host的列值必须是IP数字或localhost。 # V! P5 G, F8 F( f7 Y" R! s
--skip-networking
, S6 q6 m8 Z, r# M8 u在网络上不允许TCP/IP连接。所有到mysqld的连接必须经由Unix套接字进
  i$ j$ }$ O" |5 C% i行。这个选项对使用MIT-pthreads的系统是不合适的,因为MIT-pthreads包不 8 @" s3 y! s1 R$ Q( t
支持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 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
看了一屏就晕了。。。
0 j6 h% _9 a% |汗。。( r) I( H/ |/ G1 f& m7 ?4 {
水平不够,消化不了。。
0 ^% [$ K& h' L& M& J不过还是顶一下
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 顶 踩 转发到微博

本版积分规则

关闭

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

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